seenbefore = {}
totcalls = 0
for insnaddr, calladdr, usage in info[6]:
- callinfo = funcs[calladdr]
+ callinfo = funcs.get(calladdr)
+ if callinfo is None:
+ continue
if callinfo[2] is None:
calcmaxstack(funcs, calladdr)
if callinfo[0] not in seenbefore:
# Try to arrange output so that functions that call each other are
# near each other.
-def orderfuncs(funcnames, availnames, funcs):
- l = [(availnames[name][5], name)
- for name in funcnames if name in availnames]
+def orderfuncs(funcaddrs, availfuncs):
+ l = [(availfuncs[funcaddr][5], availfuncs[funcaddr][0], funcaddr)
+ for funcaddr in funcaddrs if funcaddr in availfuncs]
l.sort()
l.reverse()
out = []
while l:
- count, name = l.pop(0)
- if name not in availnames:
+ count, name, funcaddr = l.pop(0)
+ if funcaddr not in availfuncs:
continue
- callnames = [funcs[calls[1]][0] for calls in availnames[name][6]]
- del availnames[name]
- out = out + orderfuncs(callnames, availnames, funcs) + [name]
+ calladdrs = [calls[1] for calls in availfuncs[funcaddr][6]]
+ del availfuncs[funcaddr]
+ out = out + orderfuncs(calladdrs, availfuncs) + [funcaddr]
return out
# Update function info with a found "yield" point.
im = re_usestack.match(insn)
if im is not None:
- if insn[:5] == 'pushl' or insn[:6] == 'pushfl':
+ if insn.startswith('pushl') or insn.startswith('pushfl'):
stackusage += 4
continue
- elif insn[:5] == 'pushw' or insn[:6] == 'pushfw':
+ elif insn.startswith('pushw') or insn.startswith('pushfw'):
stackusage += 2
continue
stackusage += int(im.group('num'), 16)
insnaddr = m.group('insnaddr')
calladdr = m.group('calladdr')
if calladdr is None:
- if insn[:6] == 'lcallw':
+ if insn.startswith('lcallw'):
noteCall(cur, subfuncs, insnaddr, -1, stackusage + 4)
noteYield(cur, stackusage + 4)
- elif insn[:3] == 'int':
+ elif insn.startswith('int'):
noteCall(cur, subfuncs, insnaddr, -1, stackusage + 6)
noteYield(cur, stackusage + 6)
- elif insn[:3] == 'sti':
+ elif insn.startswith('sti'):
noteYield(cur, stackusage)
else:
# misc instruction
if '+' in ref:
# Inter-function jump.
pass
- elif insn[:1] == 'j':
+ elif insn.startswith('j'):
# Tail call
noteCall(cur, subfuncs, insnaddr, calladdr, 0)
- elif insn[:5] == 'calll':
+ elif insn.startswith('calll'):
noteCall(cur, subfuncs, insnaddr, calladdr, stackusage + 4)
else:
print "unknown call", ref
#print "other", repr(line)
# Calculate maxstackusage
- bynames = {}
for funcaddr, info in funcs.items():
- bynames[info[0]] = info
if info[2] is not None:
continue
calcmaxstack(funcs, funcaddr)
# Sort functions for output
- funcnames = bynames.keys()
- funcnames = orderfuncs(funcnames, bynames.copy(), funcs)
+ funcaddrs = orderfuncs(funcs.keys(), funcs.copy())
# Show all functions
print OUTPUTDESC
- for funcname in funcnames:
+ for funcaddr in funcaddrs:
name, basicusage, maxusage, yieldusage, maxyieldusage, count, calls = \
- bynames[funcname]
+ funcs[funcaddr]
if maxusage == 0 and maxyieldusage is None:
continue
yieldstr = ""
if maxyieldusage is not None:
yieldstr = ",%d" % maxyieldusage
- print "\n%s[%d,%d%s]:" % (funcname, basicusage, maxusage, yieldstr)
+ print "\n%s[%d,%d%s]:" % (name, basicusage, maxusage, yieldstr)
for insnaddr, calladdr, stackusage in calls:
- callinfo = funcs[calladdr]
+ callinfo = funcs.get(calladdr, ("<unknown>", 0, 0, 0, None))
yieldstr = ""
if callinfo[4] is not None:
yieldstr = ",%d" % (stackusage + callinfo[4])