From eab4472ee6e948da30e6dd0b6f784c926056fbd6 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Sun, 25 May 2008 01:35:53 +0900 Subject: Demangle C++ symbols. --- bin/win32kprof.py | 90 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 13 deletions(-) (limited to 'bin') diff --git a/bin/win32kprof.py b/bin/win32kprof.py index 9e0873a5cec..836b17e2d29 100755 --- a/bin/win32kprof.py +++ b/bin/win32kprof.py @@ -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() - - - -- cgit v1.2.3