aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2014-05-27 13:37:52 -0400
committerAnthony G. Basile <blueness@gentoo.org>2014-05-27 13:37:52 -0400
commitd38e2718a641ce67d3caf598de5534e6ebef9e64 (patch)
tree18ef83f9e198ec99e25fb49b682285fc8cc3a7f7
parentmisc/install-xattr/Makefile: fix install rule (diff)
downloadelfix-d38e2718a641ce67d3caf598de5534e6ebef9e64.tar.gz
elfix-d38e2718a641ce67d3caf598de5534e6ebef9e64.tar.bz2
elfix-d38e2718a641ce67d3caf598de5534e6ebef9e64.zip
misc/ldd: initial commit of python ldd script
-rwxr-xr-xmisc/ldd/ldd.py95
1 files changed, 95 insertions, 0 deletions
diff --git a/misc/ldd/ldd.py b/misc/ldd/ldd.py
new file mode 100755
index 0000000..afb03b6
--- /dev/null
+++ b/misc/ldd/ldd.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+
+import sys
+import re, glob
+from optparse import OptionParser
+
+from elftools import __version__
+from elftools.common.exceptions import ELFError
+from elftools.common.py3compat import bytes2str
+from elftools.elf.elffile import ELFFile
+from elftools.elf.dynamic import DynamicSection
+
+class ReadElf(object):
+ def __init__(self, file):
+ """ file: stream object with the ELF file to read
+ """
+ self.elffile = ELFFile(file)
+
+ def display_dynamic_dt_needed(self):
+ """ Display the dynamic DT_NEEDED contained in the file
+ """
+ for section in self.elffile.iter_sections():
+ if not isinstance(section, DynamicSection):
+ continue
+
+ for tag in section.iter_tags():
+ if tag.entry.d_tag == 'DT_NEEDED':
+ sys.stdout.write('\t%s\n' % bytes2str(tag.needed) )
+
+
+def ldpath(ld_so_conf='/etc/ld.so.conf'):
+ """ Generate paths to search for libraries from ld.so.conf. Recursively
+ parse included files. We assume correct syntax and the ld.so.cache
+ is in sync with ld.so.conf.
+ """
+ with open(ld_so_conf, 'r') as path_file:
+ lines = path_file.read()
+ lines = re.sub('#.*', '', lines) # kill comments
+ lines = list(re.split(':+|\s+|\t+|\n+|,+', lines)) # man 8 ldconfig
+
+ include_globs = []
+ for l in lines:
+ if l == '':
+ lines.remove('')
+ if l == 'include':
+ f = lines[lines.index(l) + 1]
+ lines.remove(l)
+ lines.remove(f)
+ include_globs.append(f)
+
+ include_files = []
+ for g in include_globs:
+ include_files = include_files + glob.glob('/etc/' + g)
+ for c in include_files:
+ lines = lines + ldpath(c)
+
+ return list(set(lines))
+
+
+SCRIPT_DESCRIPTION = 'Print shared library dependencies'
+VERSION_STRING = '%%prog: based on pyelftools %s' % __version__
+
+def main():
+ optparser = OptionParser(
+ usage='usage: %prog <elf-file>',
+ description=SCRIPT_DESCRIPTION,
+ add_help_option=False, # -h is a real option of readelf
+ prog='ldd.py',
+ version=VERSION_STRING)
+ optparser.add_option('-h', '--help',
+ action='store_true', dest='help',
+ help='Display this information')
+ options, args = optparser.parse_args()
+
+ #if options.help or len(args) == 0:
+ #optparser.print_help()
+ #sys.exit(0)
+
+ for f in args:
+ with open(f, 'rb') as file:
+ try:
+ readelf = ReadElf(file)
+ if len(args) > 1:
+ sys.stdout.write('%s : \n' % f)
+ readelf.display_dynamic_dt_needed()
+ except ELFError as ex:
+ sys.stderr.write('ELF error: %s\n' % ex)
+ sys.exit(1)
+
+ lines = ldpath()
+ print(lines)
+
+
+if __name__ == '__main__':
+ main()