-
Notifications
You must be signed in to change notification settings - Fork 3
/
lib_finder.py
95 lines (79 loc) · 3.1 KB
/
lib_finder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import os
import subprocess
import binascii
import struct
class LibFinder:
def __init__ (self):
self.resultCache = {}
def _getDebugLink (self, binPath):
objdumpOutput = subprocess.Popen(["objdump", "-s", "-w", "-j", ".gnu_debuglink", binPath], stdout=subprocess.PIPE).communicate()[0]
debugName = None
debugCrc = None
#print "parsing objdump output ..."
bytes = ''
for line in objdumpOutput.split('\n'):
if not(line.startswith(' ')):
continue
line = line[1:] # strip leading space
(addr, asciiBytes) = line.split(' ', 1)
dwords = asciiBytes.split(' ', 4)[:4]
bytes += binascii.a2b_hex("".join(dwords))
pos = bytes.find('\0')
if pos >= 0:
debugName = bytes[:pos]
remainder = bytes[pos+1:]
crcBytes = remainder[-4:]
if len(crcBytes) == 4:
debugCrc = struct.unpack('L', crcBytes)[0]
#print "crc: 0x%x" % debugCrc
return (debugName, debugCrc)
def _calcCrc (self, path):
fd = open(path, 'rb')
return (binascii.crc32(fd.read()) & 0xffffffff)
def findDebugBin (self, binPath):
"""
Returns the path of an external debuginfo library, or None if no
matching debuginfo library could be found.
"""
if self.resultCache.has_key(binPath):
return self.resultCache[binPath]
else:
res = self._findDebugBin_uncached(binPath)
self.resultCache[binPath] = res
return res
def _findDebugBin_uncached (self, binPath):
(debugName, debugCrc) = self._getDebugLink(binPath)
if debugName is None:
debugName = os.path.basename(binPath)
templates = [
"%(dir)s/%(name)s",
"%(dir)s/%(name)s.debug",
"%(dir)s/%(debug)s",
"%(dir)s/%(debug)s.debug",
"%(dir)s/.debug/%(debug)s",
"%(dir)s/.debug/%(debug)s.debug",
"/usr/lib/debug/%(dir)s/%(debug)s",
"/usr/lib/debug/%(dir)s/%(debug)s.debug",
]
for t in templates:
path = t % {'dir': os.path.dirname(binPath), 'name': os.path.basename(binPath), 'debug': debugName}
#print "checking '%s' ..." % path
if not(os.path.exists(path)):
continue
if debugCrc is not None:
crc = self._calcCrc(path)
if crc == debugCrc:
#print "debug file %s has matching CRC" % path
return path
elif path.find('debug') >= 0:
print "debug file %s exists but CRC doesn't match (found 0x%08x, expected 0x%08x)" % (path, crc, debugCrc)
return None
if __name__ == '__main__':
import sys
libFinder = LibFinder()
origBinary = sys.argv[1]
debugBinary = libFinder.findDebugBin(origBinary)
if debugBinary is None:
print "no separate debug symbols found for '%s'" % origBinary
else:
print "debug symbols for '%s' are stored in '%s'" % (origBinary, debugBinary)