-
Notifications
You must be signed in to change notification settings - Fork 24
/
symtree.sh
executable file
·98 lines (84 loc) · 1.98 KB
/
symtree.sh
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
#!/bin/bash
argv0=${0##*/}
usage() {
cat <<-EOF
Display libraries that satisfy undefined symbols, as a tree
Usage: ${argv0} [options] <ELF file[s]>
Options:
-x Run with debugging
-h Show this help output
EOF
exit ${1:-0}
}
sym_list() {
# with large strings, bash is much slower than sed
local type=$1; shift
echo "%${type}%$@" | sed "s:,:,%${type}%:g"
}
find_elf() {
echo "$2" | awk -F/ -v lib="$1" '$NF == lib {print}'
}
show_elf() {
local elf=$1
local rlib lib libs
local resolved=$(realpath "${elf}")
local resolved_libs=$(lddtree -l "${resolved}")
printf "%s\n" "${resolved}"
libs=$(scanelf -qF '#F%n' "${resolved}")
local u uu d dd
u=$(scanelf -q -F'%s#F' -s'%u%' "${elf}")
for lib in ${libs//,/ } ; do
lib=${lib##*/}
rlib=$(find_elf "${lib}" "${resolved_libs}")
d=$(scanelf -qF'%s#F' -s`sym_list d "${u}"` "${rlib}")
if [[ -n ${d} ]] ; then
dd=${dd:+${dd},}${d}
printf "%4s%s => %s\n" "" "${lib}" "${d}"
else
printf "%4s%s => %s\n" "" "${lib}" "!?! useless link !?!"
fi
done
uu=
for u in `echo "${u}" | sed 's:,: :g'` ; do
[[ ,${dd}, != *,${u},* ]] && uu=${uu:+${uu},}${u}
done
if [[ -n ${uu} ]] ; then
u=${uu}
dd=$(scanelf -qF'%s#F' -s`sym_list w "${u}"` "${resolved}")
if [[ -n ${dd} ]] ; then
printf "%4s%s => %s\n" "" "WEAK" "${dd}"
uu=
for u in `echo "${u}" | sed 's:,: :g'` ; do
[[ ,${dd}, != *,${u},* ]] && uu=${uu:+${uu},}${u}
done
fi
if [[ -n ${uu} ]] ; then
printf "%4s%s => %s\n" "" "UNRESOLVED" "${uu}"
fi
fi
}
SET_X=false
while getopts hx OPT ; do
case ${OPT} in
x) SET_X=true;;
h) usage;;
*) usage 1;;
esac
done
shift $((OPTIND - 1))
[[ -z $1 ]] && usage 1
${SET_X} && set -x
ret=0
for elf in "$@" ; do
if [[ ! -e ${elf} ]] ; then
error "${elf}: file does not exist"
elif [[ ! -r ${elf} ]] ; then
error "${elf}: file is not readable"
elif [[ -d ${elf} ]] ; then
error "${elf}: is a directory"
else
[[ ${elf} != */* ]] && elf="./${elf}"
show_elf "${elf}" 0 ""
fi
done
exit ${ret}