IGNORE = ['screenc', 'BX_PANIC']
# Find out maximum stack usage for a function
-def calcmaxstack(funcs, func):
- info = funcs[func]
- if func.split('.')[0] in IGNORE:
- # Function is hardcoded to report 0 stack usage
- info[1] = 0
- return
+def calcmaxstack(funcs, funcaddr):
+ info = funcs[funcaddr]
# Find max of all nested calls.
- max = info[0]
- info[1] = max
- for addr, callfname, usage in info[2]:
- callinfo = funcs[callfname]
- if callinfo[1] is None:
- calcmaxstack(funcs, callfname)
- totusage = usage + callinfo[1]
+ max = info[1]
+ info[2] = max
+ for insnaddr, calladdr, usage in info[3]:
+ callinfo = funcs[calladdr]
+ if callinfo[2] is None:
+ calcmaxstack(funcs, calladdr)
+ if callinfo[0].split('.')[0] in IGNORE:
+ # This called function is ignored - don't contribute it to
+ # the max stack.
+ continue
+ totusage = usage + callinfo[2]
if totusage > max:
max = totusage
- info[1] = max
+ info[2] = max
hex_s = r'[0-9a-f]+'
-re_func = re.compile(r'^' + hex_s + r' <(?P<func>.*)>:$')
+re_func = re.compile(r'^(?P<funcaddr>' + hex_s + r') <(?P<func>.*)>:$')
re_asm = re.compile(
- r'^[ ]*(?P<addr>' + hex_s + r'):\t.*\t'
- r'(addr32 )?(?P<insn>[a-z0-9]+ [^<]*)( <(?P<ref>.*)>)?$')
+ r'^[ ]*(?P<insnaddr>' + hex_s
+ + r'):\t.*\t(addr32 )?(?P<insn>.+?)[ ]*((?P<calladdr>' + hex_s
+ + r') <(?P<ref>.*)>)?$')
re_usestack = re.compile(
r'^(push.*)|(sub.* [$](?P<num>0x' + hex_s + r'),%esp)$')
def calc():
- # funcs = {funcname: [basicstackusage, maxstackusage
- # , [(addr, callfname, stackusage), ...]] }
- funcs = {'<indirect>': [0, 0, []]}
+ # funcs[funcaddr] = [funcname, basicstackusage, maxstackusage
+ # , [(addr, callfname, stackusage), ...]]
+ funcs = {-1: ['<indirect>', 0, 0, []]}
cur = None
atstart = 0
stackusage = 0
m = re_func.match(line)
if m is not None:
# Found function
- cur = [0, None, []]
- funcs[m.group('func')] = cur
+ funcaddr = int(m.group('funcaddr'), 16)
+ funcs[funcaddr] = cur = [m.group('func'), 0, None, []]
stackusage = 0
atstart = 1
subfuncs = {}
stackusage += int(im.group('num'), 16)
if atstart:
- cur[0] = stackusage
+ cur[1] = stackusage
atstart = 0
- ref = m.group('ref')
- if ref is None:
+ calladdr = m.group('calladdr')
+ if calladdr is None:
if insn[:6] == 'lcallw':
stackusage += 4
- ref = '<indirect>'
+ calladdr = -1
else:
# misc instruction - just ignore
continue
else:
# Jump or call insn
+ calladdr = int(calladdr, 16)
+ ref = m.group('ref')
if '+' in ref:
# Inter-function jump - reset stack usage to
# preamble usage
- stackusage = cur[0]
+ stackusage = cur[1]
continue
- if ref.split('.')[0] in IGNORE:
- # Call ignored - list only for informational purposes
- stackusage = 0
- elif insn[:1] == 'j':
+ if insn[:1] == 'j':
# Tail call
stackusage = 0
elif insn[:5] == 'calll':
stackusage += 4
else:
print "unknown call", ref
- if (ref, stackusage) not in subfuncs:
- cur[2].append((m.group('addr'), ref, stackusage))
- subfuncs[(ref, stackusage)] = 1
+ if (calladdr, stackusage) not in subfuncs:
+ cur[3].append((m.group('insnaddr'), calladdr, stackusage))
+ subfuncs[(calladdr, stackusage)] = 1
# Reset stack usage to preamble usage
- stackusage = cur[0]
+ stackusage = cur[1]
continue
#print "other", repr(line)
# Calculate maxstackusage
- for func, info in funcs.items():
- if info[1] is not None:
+ bynames = {}
+ for funcaddr, info in funcs.items():
+ bynames[info[0]] = info
+ if info[2] is not None:
continue
- calcmaxstack(funcs, func)
+ calcmaxstack(funcs, funcaddr)
# Show all functions
- funcnames = funcs.keys()
+ funcnames = bynames.keys()
funcnames.sort()
- for func in funcnames:
- basicusage, maxusage, calls = funcs[func]
+ for funcname in funcnames:
+ name, basicusage, maxusage, calls = bynames[funcname]
if maxusage == 0:
continue
- print "\n%s[%d,%d]:" % (func, basicusage, maxusage)
- for addr, callfname, stackusage in calls:
- callinfo = funcs[callfname]
+ print "\n%s[%d,%d]:" % (funcname, basicusage, maxusage)
+ for insnaddr, calladdr, stackusage in calls:
+ callinfo = funcs[calladdr]
print " %04s:%-40s [%d+%d,%d]" % (
- addr, callfname, stackusage, callinfo[0], stackusage+callinfo[1])
+ insnaddr, callinfo[0], stackusage, callinfo[1]
+ , stackusage+callinfo[2])
def main():
calc()