If an ELF file specifies a list of RPATHs, for each shared library
dependency search each RPATH and see if the package contains it in that
location.
FS#43239
Signed-off-by: Nicola Squartini <tensor5@gmail.com>
---
Namcap/rules/sodepends.py | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/Namcap/rules/sodepends.py b/Namcap/rules/sodepends.py
index 92826af..527f511 100644
--- a/Namcap/rules/sodepends.py
+++ b/Namcap/rules/sodepends.py
@@ -28,6 +28,7 @@ import subprocess
import tempfile
import Namcap.package
from Namcap.ruleclass import *
+from Namcap.rules.rpath import get_rpaths
libcache = {'i686': {}, 'x86-64': {}}
@@ -43,7 +44,7 @@ def figurebitsize(line):
else:
return 'i686'
-def scanlibs(fileobj, filename, sharedlibs):
+def scanlibs(fileobj, filename, sharedlibs, tarlist):
"""
Run "readelf -d" on a file-like object (e.g. a TarFile)
@@ -52,6 +53,7 @@ def scanlibs(fileobj, filename, sharedlibs):
sharedlibs: a dictionary { library => set(ELF files using that library) }
"""
shared = re.compile('Shared library: \[(.*)\]')
+ origin = re.compile('^\$ORIGIN|^\$\{ORIGIN\}')
# test magic bytes
magic = fileobj.read(4)
@@ -71,18 +73,31 @@ def scanlibs(fileobj, filename, sharedlibs):
var = p.communicate()
assert(p.returncode == 0)
for j in var[0].decode('ascii').splitlines():
+ found = False
n = shared.search(j)
# Is this a Shared library: line?
if n != None:
# Find out its architecture
architecture = figurebitsize(j)
- try:
- libpath = os.path.abspath(
- libcache[architecture][n.group(1)])[1:]
- sharedlibs.setdefault(libpath, set()).add(filename)
- except KeyError:
- # We didn't know about the library, so add it for fail later
- sharedlibs.setdefault(n.group(1), set()).add(filename)
+ # If file has RPATH, check if shared library is already packaged
+ for rpath in get_rpaths(tmp.name):
+ # Expand $ORIGIN
+ realrpath = origin.sub(os.path.dirname(filename), rpath)
+ libpath = os.path.normpath(os.path.join(realrpath, n.group(1)))
+ # Remove possible leading '/'
+ libpath = re.sub('^/', '', libpath)
+ if libpath in tarlist:
+ sharedlibs.setdefault(libpath, set()).add(filename)
+ found = True
+ break
+ if not found:
+ try:
+ libpath = os.path.abspath(
+ libcache[architecture][n.group(1)])[1:]
+ sharedlibs.setdefault(libpath, set()).add(filename)
+ except KeyError:
+ # We didn't know about the library, so add it for fail later
+ sharedlibs.setdefault(n.group(1), set()).add(filename)
finally:
os.unlink(tmp.name)
@@ -157,7 +172,7 @@ class SharedLibsRule(TarballRule):
if not entry.isfile():
continue
f = tar.extractfile(entry)
- scanlibs(f, entry.name, liblist)
+ scanlibs(f, entry.name, liblist, tar.getnames())
f.close()
# Ldd all the files and find all the link and script dependencies
--
2.8.2