blob: a39c009d2610c826262e26ef102e9d05da7cfd0e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
#!/usr/bin/env bash
#
# lddsafe - Safely print shared library dependencies (similar to ldd).
# Author: Ricardo Garcia Gonzalez.
# Author: Ivan Mironov.
# License: Public domain code.
#
# Better for grep and expected output of other tools.
export LANG=C
# Expand globs to nothing when no match is found.
shopt -s nullglob
# Print error and exit.
die()
{
echo "ERROR: $1" 1>&2
exit 1
}
# Find required program.
findexec()
{
which "$1" >/dev/null 2>/dev/null || die "$1 not found"
}
# Check file exists and is readable.
checkreadable()
{
[ -r "$1" ] || die "$1 missing or not readable"
}
# Check for bash version.
[ -n "$BASH_VERSION" ] || die "Bash required"
[ ${BASH_VERSINFO[0]} -ge 4 ] || die "Bash version 4 or later required"
# Check needed programs.
findexec objdump
findexec readelf
findexec dirname
findexec sed
# Check needed files.
checkreadable /etc/ld.so.conf
# Check arguments.
[ "$1" == "-n" ] && recursive=0 || recursive=1
[ "$1" == "-n" ] && shift
if [ $# -eq 0 ]; then
echo "Usage: $( basename $0 ) [-n] FILE..." 2>&1
exit 1
fi
for arg in "$@"; do
checkreadable "$1"
done
# Recursively print the list of files included from /etc/ld.so.conf.
ld_so_conf_deps()
{
echo "$1"
dirname="$( dirname "$1" )"
patterns="$( sed -n 's/^include[\ \t]\+\(.\+\)$/\1/p' "$1" )"
set -o noglob
for pattern in $patterns; do
set +o noglob
case $pattern in
/*)
for file in $pattern; do
ld_so_conf_deps "$file"
done
;;
*)
for file in $dirname/$pattern; do
ld_so_conf_deps "$file"
done
;;
esac
done
set +o noglob
}
# Additional library directories.
LD_LIBRARY_PATH_LIBS="${LD_LIBRARY_PATH//:/ }"
MORELIBDIRS="$( sed '/^include[\ \t]/d' $( ld_so_conf_deps /etc/ld.so.conf ) )"
# Search for a given library name.
searchlib()
{
found=0
for libdir in $LIBDIRS; do
path="$libdir"/"$1"
if [ -r "$path" ]; then
found=1
break
fi
done
[ $found -eq 1 ] && echo "$path"
}
# Already visited libraries.
declare -A VISITEDLIBS
# Print dependency results, recursively.
recursivedeps()
{
for lib in $( objdump -p "$1" | \
sed -n 's,^ *NEEDED \+\([^ ]\+\) *$,\1,p' ); do
if [ ! "${VISITEDLIBS[$lib]}" ]; then
VISITEDLIBS["$lib"]=1
file=`searchlib "$lib"`
if [ "$file" ]; then
echo " $lib => $file"
[ $recursive -eq 1 ] && recursivedeps "$file"
else
echo " $lib => not found"
fi
fi
done
}
# Search symbol names in library directories.
for arg in "$@"; do
# Print file name when more than one file given.
[ $# -gt 1 ] && echo "${arg}:"
# Set appropriate library search directories.
class=$( readelf -h $arg 2>/dev/null | \
sed -n 's/^[ \t]*Class:[\ \t]\+\(.\+\)/\1/p' )
if [ -z "$class" ]; then
echo "$arg: not an ELF file" 2>&1
continue
fi
if [ $class != ELF32 -a $class != ELF64 ]; then
echo "$arg: unknown ELF format" 2>&1
continue
fi
if [ $class == ELF64 ]; then
if [ -d /lib64 ]; then
stdlibs="/lib64 /usr/lib64"
else
stdlibs="/lib /usr/lib"
fi
else # $class == ELF32
if [ -d /lib32 ]; then
stdlibs="/lib32 /usr/lib32"
else
stdlibs="/lib /usr/lib"
fi
fi
LIBDIRS="$LD_LIBRARY_PATH_LIBS $MORELIBDIRS $stdlibs"
# Get a unique list of library dependencies for this argument.
unset VISITEDLIBS
declare -A VISITEDLIBS
recursivedeps "$arg"
done
exit 0
|