109 lines
4.1 KiB
Python
Executable File
109 lines
4.1 KiB
Python
Executable File
import pdbparse
|
|
import os
|
|
from operator import itemgetter,attrgetter
|
|
from bisect import bisect_right
|
|
from pdbparse.undecorate import undecorate
|
|
from itertools import islice, count
|
|
|
|
class DummyOmap(object):
|
|
def remap(self, addr):
|
|
return addr
|
|
|
|
class Lookup(object):
|
|
def __init__(self, mods):
|
|
self.addrs = {}
|
|
self._cache = {}
|
|
|
|
not_found = []
|
|
|
|
for pdbname,base in mods:
|
|
pdbbase = ".".join(os.path.basename(pdbname).split('.')[:-1])
|
|
if not os.path.exists(pdbname):
|
|
print "WARN: %s not found" % pdbname
|
|
not_found.append( (base, pdbbase) )
|
|
continue
|
|
|
|
#print "Loading symbols for %s..." % pdbbase
|
|
try:
|
|
# Do this the hard way to avoid having to load
|
|
# the types stream in mammoth PDB files
|
|
pdb = pdbparse.parse(pdbname, fast_load=True)
|
|
pdb.STREAM_DBI.load()
|
|
pdb._update_names()
|
|
pdb.STREAM_GSYM = pdb.STREAM_GSYM.reload()
|
|
if pdb.STREAM_GSYM.size:
|
|
pdb.STREAM_GSYM.load()
|
|
pdb.STREAM_SECT_HDR = pdb.STREAM_SECT_HDR.reload()
|
|
pdb.STREAM_SECT_HDR.load()
|
|
# These are the dicey ones
|
|
pdb.STREAM_OMAP_FROM_SRC = pdb.STREAM_OMAP_FROM_SRC.reload()
|
|
pdb.STREAM_OMAP_FROM_SRC.load()
|
|
pdb.STREAM_SECT_HDR_ORIG = pdb.STREAM_SECT_HDR_ORIG.reload()
|
|
pdb.STREAM_SECT_HDR_ORIG.load()
|
|
|
|
except AttributeError, e:
|
|
pass
|
|
#except Exception, e:
|
|
# print "WARN: error %s parsing %s, skipping" % (e,pdbbase)
|
|
# not_found.append( (base, pdbbase) )
|
|
# continue
|
|
|
|
try:
|
|
sects = pdb.STREAM_SECT_HDR_ORIG.sections
|
|
omap = pdb.STREAM_OMAP_FROM_SRC
|
|
except AttributeError as e:
|
|
# In this case there is no OMAP, so we use the given section
|
|
# headers and use the identity function for omap.remap
|
|
sects = pdb.STREAM_SECT_HDR.sections
|
|
omap = DummyOmap()
|
|
gsyms = pdb.STREAM_GSYM
|
|
if not hasattr(gsyms, 'globals'):
|
|
gsyms.globals = []
|
|
|
|
last_sect = max(sects, key=attrgetter('VirtualAddress'))
|
|
limit = base + last_sect.VirtualAddress + last_sect.Misc.VirtualSize
|
|
|
|
self.addrs[base,limit] = {}
|
|
self.addrs[base,limit]['name'] = pdbbase
|
|
self.addrs[base,limit]['addrs'] = []
|
|
for sym in gsyms.globals:
|
|
if not hasattr(sym, 'offset'): continue
|
|
off = sym.offset
|
|
try:
|
|
virt_base = sects[sym.segment-1].VirtualAddress
|
|
except IndexError:
|
|
continue
|
|
|
|
mapped = omap.remap(off+virt_base) + base
|
|
self.addrs[base,limit]['addrs'].append((mapped,sym.name))
|
|
|
|
self.addrs[base,limit]['addrs'].sort(key=itemgetter(0))
|
|
|
|
self.locs = {}
|
|
self.names = {}
|
|
for base,limit in self.addrs:
|
|
mod = self.addrs[base,limit]['name']
|
|
symbols = self.addrs[base,limit]['addrs']
|
|
self.locs[base,limit] = [a[0] for a in symbols]
|
|
self.names[base,limit] = [a[1] for a in symbols]
|
|
|
|
def lookup(self, loc):
|
|
if loc in self._cache:
|
|
return self._cache[loc]
|
|
|
|
for base,limit in self.addrs:
|
|
if loc >= base and loc < limit:
|
|
mod = self.addrs[base,limit]['name']
|
|
symbols = self.addrs[base,limit]['addrs']
|
|
locs = self.locs[base,limit]
|
|
names = self.names[base,limit]
|
|
idx = bisect_right(locs, loc) - 1
|
|
diff = loc - locs[idx]
|
|
if diff:
|
|
ret = "%s!%s+%#x" % (mod,names[idx],diff)
|
|
else:
|
|
ret = "%s!%s" % (mod,names[idx])
|
|
self._cache[loc] = ret
|
|
return ret
|
|
return "unknown"
|