|
|
@@ -7,8 +7,83 @@ import struct |
|
|
|
|
|
|
|
__version__ = '0.1' |
|
|
|
|
|
|
|
|
|
|
|
verbose = False |
|
|
|
|
|
|
|
|
|
|
|
class ParseError(Exception): |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
class MsvcDemangler: |
|
|
|
# http://www.kegel.com/mangle.html |
|
|
|
|
|
|
|
def __init__(self, symbol): |
|
|
|
self._symbol = symbol |
|
|
|
self._pos = 0 |
|
|
|
|
|
|
|
def lookahead(self): |
|
|
|
return self._symbol[self._pos] |
|
|
|
|
|
|
|
def consume(self): |
|
|
|
ret = self.lookahead() |
|
|
|
self._pos += 1 |
|
|
|
return ret |
|
|
|
|
|
|
|
def match(self, c): |
|
|
|
if self.lookahead() != c: |
|
|
|
raise ParseError |
|
|
|
self.consume() |
|
|
|
|
|
|
|
def parse(self): |
|
|
|
self.match('?') |
|
|
|
name = self.parse_name() |
|
|
|
qualifications = self.parse_qualifications() |
|
|
|
return '::'.join(qualifications + [name]) |
|
|
|
|
|
|
|
def parse_name(self): |
|
|
|
if self.lookahead() == '?': |
|
|
|
return self.consume() + self.consume() |
|
|
|
else: |
|
|
|
name = self.parse_id() |
|
|
|
self.match('@') |
|
|
|
return name |
|
|
|
|
|
|
|
def parse_qualifications(self): |
|
|
|
qualifications = [] |
|
|
|
while self.lookahead() != '@': |
|
|
|
name = self.parse_id() |
|
|
|
qualifications.append(name) |
|
|
|
self.match('@') |
|
|
|
return qualifications |
|
|
|
|
|
|
|
def parse_id(self): |
|
|
|
s = '' |
|
|
|
while True: |
|
|
|
c = self.lookahead() |
|
|
|
if c.isalnum() or c in '_': |
|
|
|
s += c |
|
|
|
self.consume() |
|
|
|
else: |
|
|
|
break |
|
|
|
return s |
|
|
|
|
|
|
|
|
|
|
|
def demangle(name): |
|
|
|
if name.startswith('_'): |
|
|
|
name = name[1:] |
|
|
|
idx = name.rfind('@') |
|
|
|
if idx != -1 and name[idx+1:].isdigit(): |
|
|
|
name = name[:idx] |
|
|
|
return name |
|
|
|
if name.startswith('?'): |
|
|
|
demangler = MsvcDemangler(name) |
|
|
|
return demangler.parse() |
|
|
|
|
|
|
|
return name |
|
|
|
return name |
|
|
|
|
|
|
|
|
|
|
|
class Profile: |
|
|
|
|
|
|
|
def __init__(self): |
|
|
@@ -19,15 +94,6 @@ class Profile: |
|
|
|
self.last_stamp = 0 |
|
|
|
self.stamp_base = 0 |
|
|
|
|
|
|
|
def demangle(self, name): |
|
|
|
if name.startswith('_'): |
|
|
|
name = name[1:] |
|
|
|
idx = name.rfind('@') |
|
|
|
if idx != -1 and name[idx+1:].isdigit(): |
|
|
|
name = name[:idx] |
|
|
|
# TODO: Demangle C++ names |
|
|
|
return name |
|
|
|
|
|
|
|
def unwrap_stamp(self, stamp): |
|
|
|
if stamp < self.last_stamp: |
|
|
|
self.stamp_base += 1 << 32 |
|
|
@@ -47,7 +113,7 @@ class Profile: |
|
|
|
if type != 'f': |
|
|
|
continue |
|
|
|
addr = int(addr, 16) |
|
|
|
name = self.demangle(name) |
|
|
|
name = demangle(name) |
|
|
|
if last_addr == addr: |
|
|
|
# TODO: handle collapsed functions |
|
|
|
#assert last_name == name |
|
|
@@ -197,9 +263,7 @@ def main(): |
|
|
|
profile.read_data(arg) |
|
|
|
profile.write_report() |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
main() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|