Skip to content

Instantly share code, notes, and snippets.

@jld
Created April 21, 2015 02:08
Show Gist options
  • Select an option

  • Save jld/6ab22330ba9a857b180f to your computer and use it in GitHub Desktop.

Select an option

Save jld/6ab22330ba9a857b180f to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import os, sys, bisect, re
class Module:
def __init__(self, name):
self.name = name
self.files = []
self.funcs = []
self.lines = []
def parse_line(self, line):
head, tail = line.split(" ", 1)
if head == "FILE":
filenum, name = tail.split(" ", 1)
filenum = int(filenum, 10)
if name.startswith("hg:"):
name = name.split(":")[2]
while len(self.files) <= filenum:
self.files.append(None)
self.files[filenum] = name
elif head == "FUNC":
addr, length, params, name = tail.split(" ", 3)
addr = int(addr, 16)
length = int(length, 16)
self.funcs.append((addr, length, name))
elif head == "PUBLIC" or head == "STACK":
pass
else:
addr = int(head, 16)
length, line, filenum = tail.split(" ", 2)
length = int(length, 16)
line = int(line, 10)
filenum = int(filenum, 10)
self.lines.append((addr, length, line, filenum))
def lookup(self, addr):
bf = bisect.bisect(self.funcs, (addr,))
if bf == 0:
return None
faddr, flen, fname = self.funcs[bf - 1]
if addr > faddr + flen:
return None
bl = bisect.bisect(self.lines, (addr,))
if bl == 0:
return fname
laddr, llen, lline, lfile = self.lines[bl - 1]
if addr > laddr + llen:
return fname
return ("%s %s:%d" % (fname, self.files[lfile], lline))
def read_symbols(modules, path):
this_module = None
with open(path) as file:
for line in file:
line = line.rstrip()
if line.startswith("MODULE "):
kwd, os, arch, blob, name = line.split(" ", 4)
if name not in modules:
modules[name] = Module(name)
this_module = modules[name]
else:
this_module.parse_line(line)
def main(argv):
modules = {}
for arg in argv:
if os.path.isfile(arg):
read_symbols(modules, arg)
else:
for root, dirnames, filenames in os.walk(arg):
for filename in filenames:
if filename.endswith(".sym"): #???
read_symbols(modules, os.path.join(root, filename))
FIXABLE = re.compile('\?\?\?\[(.*/)?(?P<file>[^/]*)\+(?P<offset>0x[0-9a-f]+)\]')
def fix(m):
filename = m.group("file").rstrip()
offset = int(m.group("offset"), 16)
if filename not in modules:
return m.group(0)
xlation = modules[filename].lookup(offset)
if not xlation:
return m.group(0)
return "%s (%s+0x%x)" % (xlation, filename, offset)
for line in sys.stdin:
sys.stdout.write(re.sub(FIXABLE, fix, line))
if __name__ == '__main__':
main(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment