commit: ef15f6016726ad3e06db747f188bd9db9d5ffb71 Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> AuthorDate: Thu Aug 20 14:29:39 2015 +0000 Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> CommitDate: Thu Aug 20 14:29:39 2015 +0000 URL: https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=ef15f601
lddtree.sh: fix interp handling when doing a full listing On Debian multiarch systems, the ldso path is symlinked to a different search path (and the main path isn't searched at all). When listing the deps of an ELF which links against the ldso, we end up showing the ldso being loaded by two different paths: $ ./lddtree.sh -a /bin/bash bash => /bin/bash (interpreter => /lib64/ld-linux-x86-64.so.2) libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 ld-linux-x86-64.so.2 => /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ... Fix the output to show that ld-linux-x86-64.so.2 was located at the same path as the original interpreter as that better matches the runtime ldso behavior. $ ./lddtree.sh -a /bin/bash bash => /bin/bash (interpreter => /lib64/ld-linux-x86-64.so.2) libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 Reported-by: Tomasz Buchert <tomasz <AT> debian.org> lddtree.sh | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lddtree.sh b/lddtree.sh index 07be7ab..8e6501f 100755 --- a/lddtree.sh +++ b/lddtree.sh @@ -126,7 +126,7 @@ find_elf() { show_elf() { local elf=$1 indent=$2 parent_elfs=$3 local rlib lib libs - local interp resolved + local resolved find_elf "${elf}" resolved=${_find_elf} elf=${elf##*/} @@ -143,6 +143,8 @@ show_elf() { printf "${resolved:-not found}" fi if [[ ${indent} -eq 0 ]] ; then + local elf_specs interp full_interp + elf_specs=$(elf_specs "${resolved}") interp=$(scanelf -qF '#F%i' "${resolved}") [[ -n ${interp} ]] && interp="${ROOT}${interp#/}" @@ -159,6 +161,7 @@ show_elf() { sed -nr -e "/^\/.*lib/{s|^/?|${ROOT}|;s|/$||;s|/?:/?|\n${ROOT}|g;p}" ) fi + full_interp=${interp} interp=${interp##*/} # If we are in non-list mode, then we want to show the "duplicate" interp # lines -- first the header (interp=>xxx), and then the DT_NEEDED line to @@ -183,8 +186,19 @@ show_elf() { # No need for leading comma w/my_allhits as we guarantee it always # starts with one due to the way we append the value above. [[ ${my_allhits}, == *,${lib},* ]] && continue - find_elf "${lib}" "${resolved}" - rlib=${_find_elf} + # If the interp is being linked against directly, re-use the existing + # full path rather than perform a search for it. When systems symlink + # the interp to a diff location, we might locate a different path, and + # displaying both doesn't make sense as it doesn't match the runtime -- + # the ldso won't load another copy of ldso into memory from the search + # path, it'll re-use the existing copy that was loaded from the full + # hardcoded path. + if [[ ${lib} == "${interp}" ]] ; then + rlib=${full_interp} + else + find_elf "${lib}" "${resolved}" + rlib=${_find_elf} + fi show_elf "${rlib:-${lib}}" $((indent + 4)) "${parent_elfs}" done }