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
 }

Reply via email to