diff options
author | Kyle Keen <keenerd@gmail.com> | 2016-07-21 10:25:18 -0400 |
---|---|---|
committer | Kyle Keen <keenerd@gmail.com> | 2016-07-21 10:25:18 -0400 |
commit | 09a4007391cf78c93f08acc11b45d13e64b920a2 (patch) | |
tree | e560e8c82aa0d0d2a913c676179a9a1576ca49f2 | |
parent | 005277b553c6f44979083a9681cadd686c08d27b (diff) | |
download | namcap-09a4007391cf78c93f08acc11b45d13e64b920a2.tar.gz namcap-09a4007391cf78c93f08acc11b45d13e64b920a2.zip |
Use elftools in sodepends
Signed-off-by: Kyle Keen <keenerd@gmail.com>
-rw-r--r-- | Namcap/rules/sodepends.py | 78 |
1 files changed, 31 insertions, 47 deletions
diff --git a/Namcap/rules/sodepends.py b/Namcap/rules/sodepends.py index 92826af..6832ae0 100644 --- a/Namcap/rules/sodepends.py +++ b/Namcap/rules/sodepends.py @@ -25,66 +25,50 @@ from collections import defaultdict import re import os import subprocess -import tempfile import Namcap.package from Namcap.ruleclass import * -libcache = {'i686': {}, 'x86-64': {}} - -def figurebitsize(line): - """ - Given a line of output from readelf (usually Shared library:) return - 'i686' or 'x86-64' if the binary is a 32bit or 64bit binary - """ +from elftools.elf.enums import ENUM_D_TAG +from elftools.elf.elffile import ELFFile +from elftools.elf.dynamic import DynamicSection - address = line.split()[0] - if len(address) == 18: # + '0x' + 16 digits - return 'x86-64' - else: - return 'i686' +libcache = {'i686': {}, 'x86-64': {}} -def scanlibs(fileobj, filename, sharedlibs): +def scanlibs(fileobj, filename): """ - Run "readelf -d" on a file-like object (e.g. a TarFile) + Find shared libraries in a file-like binary object If it depends on a library, store that library's path. - sharedlibs: a dictionary { library => set(ELF files using that library) } + returns: a dictionary { library => set(ELF files using that library) } """ - shared = re.compile('Shared library: \[(.*)\]') # test magic bytes magic = fileobj.read(4) if magic[:4] != b"\x7fELF": - return - - # read the rest of file - tmp = tempfile.NamedTemporaryFile(delete=False) - tmp.write(magic + fileobj.read()) - tmp.close() - - try: - p = subprocess.Popen(["readelf", "-d", tmp.name], - env = {"LANG": "C"}, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - var = p.communicate() - assert(p.returncode == 0) - for j in var[0].decode('ascii').splitlines(): - 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) - finally: - os.unlink(tmp.name) + return {} + + fileobj.seek(0) + elffile = ELFFile(fileobj) + sharedlibs = defaultdict(set) + for section in elffile.iter_sections(): + if not isinstance(section, DynamicSection): + continue + for tag in section.iter_tags(): + # DT_NEEDED means shared library + if tag.entry.d_tag != 'DT_NEEDED': + continue + bitsize = elffile.elfclass + architecture = {32:'i686', 64:'x86-64'}[bitsize] + libname = tag.needed.decode('utf-8') + try: + libpath = os.path.abspath( + libcache[architecture][libname])[1:] + sharedlibs[libpath].add(filename) + except KeyError: + # We didn't know about the library, so add it for fail later + sharedlibs[libname].add(filename) + return sharedlibs def finddepends(liblist): """ @@ -157,7 +141,7 @@ class SharedLibsRule(TarballRule): if not entry.isfile(): continue f = tar.extractfile(entry) - scanlibs(f, entry.name, liblist) + liblist.update(scanlibs(f, entry.name)) f.close() # Ldd all the files and find all the link and script dependencies |