diff options
author | Mike Frysinger <vapier@gentoo.org> | 2009-12-01 10:20:23 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-12-01 10:20:23 +0000 |
commit | a62782a2eed7815a6cd09d2c696e05d3656eaa25 (patch) | |
tree | a4044dad45bb3a9ba8449dc365224f2ca13abd77 /symtree.sh | |
parent | extend symbol lookup syntax to allow matching of symbols based on more fields (diff) | |
download | pax-utils-a62782a2eed7815a6cd09d2c696e05d3656eaa25.tar.gz pax-utils-a62782a2eed7815a6cd09d2c696e05d3656eaa25.tar.bz2 pax-utils-a62782a2eed7815a6cd09d2c696e05d3656eaa25.zip |
first cut at displaying a tree of which libraries satisfy which undefined symbols
Diffstat (limited to 'symtree.sh')
-rwxr-xr-x | symtree.sh | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/symtree.sh b/symtree.sh new file mode 100755 index 0000000..64a3333 --- /dev/null +++ b/symtree.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +source lddtree /../..source.lddtree || exit 1 + +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 "%%~"`echo ",$@" | sed "s:,:,%${type}%:g"` +} +show_elf() { + local elf=$1 + local rlib lib libs + local resolved=$(find_elf "${elf}") + + 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}") + + 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 + +([[ $1 == "" ]] || [[ $1 == --help ]]) && usage 1 +opts="hx" +getopt -Q -- "${opts}" "$@" || exit 1 +eval set -- $(getopt -- "${opts}" "$@") +while [[ -n $1 ]] ; do + case $1 in + -x) SET_X=true;; + -h) usage;; + --) shift; break;; + -*) usage 1;; + esac + shift +done + +${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} |