1 |
commit: d38e2718a641ce67d3caf598de5534e6ebef9e64 |
2 |
Author: Anthony G. Basile <blueness <AT> gentoo <DOT> org> |
3 |
AuthorDate: Tue May 27 17:37:52 2014 +0000 |
4 |
Commit: Anthony G. Basile <blueness <AT> gentoo <DOT> org> |
5 |
CommitDate: Tue May 27 17:37:52 2014 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/elfix.git;a=commit;h=d38e2718 |
7 |
|
8 |
misc/ldd: initial commit of python ldd script |
9 |
|
10 |
--- |
11 |
misc/ldd/ldd.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
12 |
1 file changed, 95 insertions(+) |
13 |
|
14 |
diff --git a/misc/ldd/ldd.py b/misc/ldd/ldd.py |
15 |
new file mode 100755 |
16 |
index 0000000..afb03b6 |
17 |
--- /dev/null |
18 |
+++ b/misc/ldd/ldd.py |
19 |
@@ -0,0 +1,95 @@ |
20 |
+#!/usr/bin/env python |
21 |
+ |
22 |
+import sys |
23 |
+import re, glob |
24 |
+from optparse import OptionParser |
25 |
+ |
26 |
+from elftools import __version__ |
27 |
+from elftools.common.exceptions import ELFError |
28 |
+from elftools.common.py3compat import bytes2str |
29 |
+from elftools.elf.elffile import ELFFile |
30 |
+from elftools.elf.dynamic import DynamicSection |
31 |
+ |
32 |
+class ReadElf(object): |
33 |
+ def __init__(self, file): |
34 |
+ """ file: stream object with the ELF file to read |
35 |
+ """ |
36 |
+ self.elffile = ELFFile(file) |
37 |
+ |
38 |
+ def display_dynamic_dt_needed(self): |
39 |
+ """ Display the dynamic DT_NEEDED contained in the file |
40 |
+ """ |
41 |
+ for section in self.elffile.iter_sections(): |
42 |
+ if not isinstance(section, DynamicSection): |
43 |
+ continue |
44 |
+ |
45 |
+ for tag in section.iter_tags(): |
46 |
+ if tag.entry.d_tag == 'DT_NEEDED': |
47 |
+ sys.stdout.write('\t%s\n' % bytes2str(tag.needed) ) |
48 |
+ |
49 |
+ |
50 |
+def ldpath(ld_so_conf='/etc/ld.so.conf'): |
51 |
+ """ Generate paths to search for libraries from ld.so.conf. Recursively |
52 |
+ parse included files. We assume correct syntax and the ld.so.cache |
53 |
+ is in sync with ld.so.conf. |
54 |
+ """ |
55 |
+ with open(ld_so_conf, 'r') as path_file: |
56 |
+ lines = path_file.read() |
57 |
+ lines = re.sub('#.*', '', lines) # kill comments |
58 |
+ lines = list(re.split(':+|\s+|\t+|\n+|,+', lines)) # man 8 ldconfig |
59 |
+ |
60 |
+ include_globs = [] |
61 |
+ for l in lines: |
62 |
+ if l == '': |
63 |
+ lines.remove('') |
64 |
+ if l == 'include': |
65 |
+ f = lines[lines.index(l) + 1] |
66 |
+ lines.remove(l) |
67 |
+ lines.remove(f) |
68 |
+ include_globs.append(f) |
69 |
+ |
70 |
+ include_files = [] |
71 |
+ for g in include_globs: |
72 |
+ include_files = include_files + glob.glob('/etc/' + g) |
73 |
+ for c in include_files: |
74 |
+ lines = lines + ldpath(c) |
75 |
+ |
76 |
+ return list(set(lines)) |
77 |
+ |
78 |
+ |
79 |
+SCRIPT_DESCRIPTION = 'Print shared library dependencies' |
80 |
+VERSION_STRING = '%%prog: based on pyelftools %s' % __version__ |
81 |
+ |
82 |
+def main(): |
83 |
+ optparser = OptionParser( |
84 |
+ usage='usage: %prog <elf-file>', |
85 |
+ description=SCRIPT_DESCRIPTION, |
86 |
+ add_help_option=False, # -h is a real option of readelf |
87 |
+ prog='ldd.py', |
88 |
+ version=VERSION_STRING) |
89 |
+ optparser.add_option('-h', '--help', |
90 |
+ action='store_true', dest='help', |
91 |
+ help='Display this information') |
92 |
+ options, args = optparser.parse_args() |
93 |
+ |
94 |
+ #if options.help or len(args) == 0: |
95 |
+ #optparser.print_help() |
96 |
+ #sys.exit(0) |
97 |
+ |
98 |
+ for f in args: |
99 |
+ with open(f, 'rb') as file: |
100 |
+ try: |
101 |
+ readelf = ReadElf(file) |
102 |
+ if len(args) > 1: |
103 |
+ sys.stdout.write('%s : \n' % f) |
104 |
+ readelf.display_dynamic_dt_needed() |
105 |
+ except ELFError as ex: |
106 |
+ sys.stderr.write('ELF error: %s\n' % ex) |
107 |
+ sys.exit(1) |
108 |
+ |
109 |
+ lines = ldpath() |
110 |
+ print(lines) |
111 |
+ |
112 |
+ |
113 |
+if __name__ == '__main__': |
114 |
+ main() |