aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2015-03-10 01:24:38 -0400
committerMike Frysinger <vapier@gentoo.org>2015-03-10 01:24:38 -0400
commit8115dc905a772153a1cebaf06ca4f0ba2e257caa (patch)
tree8190f3c532ca5ef1973bd1227d7892f11349874f
parentelf.h: sync with glibc (diff)
downloadpax-utils-8115dc905a772153a1cebaf06ca4f0ba2e257caa.tar.gz
pax-utils-8115dc905a772153a1cebaf06ca4f0ba2e257caa.tar.bz2
pax-utils-8115dc905a772153a1cebaf06ca4f0ba2e257caa.zip
lddtree.py: dereference the interp symlink to handle desynced ABIs betterv1.0.2
On aarch64/s390x, the interp is always placed in /lib/ while the libs are normally placed in /lib64/. If the interp is a symlink (which it normally is here), then dereference it to locate the lib paths automatically. This also fixes up some bad lstrip logic in the /usr path expansion. We could update lddtree.sh with a similar fix, but it would take more work as it doesn't have the readlink helper to properly walk symlinks according to an alternative root. Plus, it already uses strings to try and extract the paths the ldso was compiled against, and that seems to work in these cases. Reported-by: Jakub Čajka <jcajka@redhat.com> URL: https://bugzilla.redhat.com/1162184
-rwxr-xr-xlddtree.py18
1 files changed, 14 insertions, 4 deletions
diff --git a/lddtree.py b/lddtree.py
index 4d1b15e..c284182 100755
--- a/lddtree.py
+++ b/lddtree.py
@@ -372,15 +372,25 @@ def ParseELF(path, root='/', prefix='', ldpaths={'conf':[], 'env':[], 'interp':[
interp = bstr(segment.get_interp_name())
dbg(debug, ' interp =', interp)
ret['interp'] = normpath(root + interp)
+ real_interp = readlink(ret['interp'], root, prefixed=True)
ret['libs'][os.path.basename(interp)] = {
'path': ret['interp'],
- 'realpath': readlink(ret['interp'], root, prefixed=True),
+ 'realpath': real_interp,
'needed': [],
}
- # XXX: Should read it and scan for /lib paths.
+ # XXX: Could read it and scan for /lib paths.
+ # If the interp is a symlink, lets follow it on the assumption that it
+ # is in this path purely for ABI reasons, and the distro is using a
+ # different (probably more correct) path. This can come up in some
+ # multilib situations like s390x where /lib64/ contains all the native
+ # libraries, but /lib/ld64.so.1 is the interp hardcoded in gcc, so the
+ # ld64.so.1 is really a symlink to ../lib64/ld64.so.1. In the multiarch
+ # setup, it'll be /lib/ld64.so.1 -> /lib/s390x-linux-gnu/ld64.so.1.
+ # That is why we use |real_interp| here instead of |interp|.
ldpaths['interp'] = [
- normpath(root + os.path.dirname(interp)),
- normpath(root + prefix + '/usr' + os.path.dirname(interp).lstrip(prefix)),
+ os.path.dirname(real_interp),
+ normpath(root + prefix + '/usr/' + os.path.dirname(
+ real_interp)[len(root) + len(prefix):]),
]
dbg(debug, ' ldpaths[interp] =', ldpaths['interp'])
break