diff options
author | Mike Frysinger <vapier@gentoo.org> | 2015-03-10 01:24:38 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2015-03-10 01:24:38 -0400 |
commit | 8115dc905a772153a1cebaf06ca4f0ba2e257caa (patch) | |
tree | 8190f3c532ca5ef1973bd1227d7892f11349874f | |
parent | elf.h: sync with glibc (diff) | |
download | pax-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-x | lddtree.py | 18 |
1 files changed, 14 insertions, 4 deletions
@@ -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 |