Skip to content
Snippets Groups Projects

sodepends: fix listing binaries, check libdepends, libprovides

Merged Balló György requested to merge bgyorgy/namcap:fix-sodepends-list into master
1 unresolved thread
Files
2
+ 38
7
@@ -35,7 +35,7 @@ from elftools.elf.dynamic import DynamicSection
libcache = {'i686': {}, 'x86-64': {}}
def scanlibs(fileobj, filename, custom_libs, sharedlibs, libprovides):
def scanlibs(fileobj, filename, custom_libs, liblist, libdepends, libprovides):
"""
Find shared libraries in a file-like binary object
@@ -60,26 +60,30 @@ def scanlibs(fileobj, filename, custom_libs, sharedlibs, libprovides):
bitsize = elffile.elfclass
architecture = {32:'i686', 64:'x86-64'}[bitsize]
libname = tag.needed
soname = libname.rsplit('.so', 1)[0] + '.so'
libdepends[soname].add(filename)
if libname in custom_libs:
sharedlibs[custom_libs[libname][1:]].add(filename)
liblist[custom_libs[libname][1:]].add(filename)
continue
try:
libpath = os.path.abspath(
libcache[architecture][libname])[1:]
sharedlibs[libpath].add(filename)
liblist[libpath].add(filename)
except KeyError:
# We didn't know about the library, so add it for fail later
sharedlibs[libname].add(filename)
liblist[libname].add(filename)
def finddepends(liblist):
def finddepends(liblist, infos):
"""
Find packages owning a list of libraries
Returns:
dependlist -- a dictionary { package => set(libraries) }
libdependlist -- a dictionary { soname => package }
orphans -- the list of libraries without owners
"""
dependlist = defaultdict(set)
libdependlist = {}
somatches = {}
actualpath = {}
@@ -108,9 +112,16 @@ def finddepends(liblist):
if j == actualpath[k] or (j.startswith(actualpath[k]) and so_end.match(j[len(actualpath[k]):])):
dependlist[pkg.name].add(k)
foundlibs.add(k)
# Check if the dependency can be satisfied by soname
soname = os.path.basename(k).rsplit('.so', 1)[0] + '.so'
stripped_provides = [Namcap.package.strip_depend_info(d) for d in pkg.provides]
if soname in stripped_provides:
libdependlist[soname] = pkg.name
else:
infos.append(("libdepends-missing-provides %s %s", (soname, pkg.name )))
orphans = list(knownlibs - foundlibs)
return dependlist, orphans
return dependlist, libdependlist, orphans
def filllibcache():
var = subprocess.Popen('ldconfig -p',
@@ -134,8 +145,10 @@ class SharedLibsRule(TarballRule):
description = "Checks dependencies caused by linked shared libraries"
def analyze(self, pkginfo, tar):
liblist = defaultdict(set)
libdepends = defaultdict(set)
libprovides = defaultdict(set)
dependlist = {}
libdependlist = {}
filllibcache()
os.environ['LC_ALL'] = 'C'
pkg_so_files = ['/' + n for n in tar.getnames() if '.so' in n]
@@ -156,7 +169,7 @@ class SharedLibsRule(TarballRule):
f.close()
# Ldd all the files and find all the link and script dependencies
dependlist, orphans = finddepends(liblist)
dependlist, libdependlist, orphans = finddepends(liblist, self.infos)
# Handle "no package associated" errors
self.warnings.extend([("library-no-package-associated %s", i)
@@ -174,6 +187,24 @@ class SharedLibsRule(TarballRule):
))
self.infos.append(("link-level-dependence %s in %s", (pkg, str(files))))
# Check for soname dependencies, filter out internal dependencies
libdependlist = dict(filter(lambda elem: elem[1] != pkginfo["name"], libdependlist.items()))
for i in libdependlist:
if i in pkginfo["depends"]:
self.infos.append(("libdepends-detected-satisfied %s %s (%s)", (i, libdependlist[i], str(list(libdepends[i])))))
continue
if i in pkginfo["optdepends"]:
self.warnings.append(("libdepends-detected-but-optional %s %s (%s)", (i, libdependlist[i], str(list(libdepends[i])))))
continue
self.warnings.append(("libdepends-detected-not-included %s %s (%s)", (i, libdependlist[i], str(list(libdepends[i])))))
for i in pkginfo["depends"]:
if i.endswith('.so') and i not in libdependlist:
self.warnings.append(("libdepends-not-needed %s", i))
self.infos.append(("libdepends-by-namcap-sight depends=(%s)", ' '.join(libdependlist) ))
# Check provided libraries
for i in libprovides:
if i in pkginfo["provides"]:
Loading