rendered paste body# by snikim
from __future__ import division
import sys, os
import re
prefix = sys.argv[1]
disinp = open(prefix + '.dis')
profinp = open(prefix + '.out')
pat_prof = re.compile('^0x([0-9a-f]{4,6}) ([0-9]+) ([0-9.]+)$')
pat_dis = re.compile('^ +([0-9a-f]{4,6}):[ \t]+[0-9a-f]+[ \t]+([a-zA-Z0-9_-]+)[ \t]+(.*)$')
CANONICALINSTRS = {
}
CONDITIONALS = ('eq', 'ne', 'cs', 'hs', 'cc', 'lo', 'mi', 'pl', 'vs',
'vc', 'hi', 'ls', 'ge', 'lt', 'gt', 'le', 'al')
CONDITIONAL_INSTRS = (
'adc', 'adc_s', 'add', 'add_s', 'and', 'b', 'bl', 'bic', 'blx', 'bx', 'cdp', 'clz',
'cmn', 'cmp', 'eor', 'ldc', 'ldm', 'ldm_ia', 'ldm_db', 'ldr', 'ldr_b', 'ldr_bt',
'ldr_h', 'ldr_sb', 'ldr_sh', 'ldr_t', 'mcr', 'mla', 'mla_s', 'mov', 'mov_s',
'mrc', 'mrs', 'msr', 'mul', 'mul_s', 'mvn', 'mvn_s', 'orr', 'orr_s', 'rsb',
'rsb_s', 'rsc', 'rsc_s', 'sbc', 'sbc_s', 'smlal', 'smlal_s', 'smull', 'smull_s',
'stc', 'stc_l', 'stm', 'stm_p' ,'stm_u', 'stm_db', 'stm_w', 'str', 'str_b',
'str_bt', 'str_h', 'str_t', 'sub', 'sub_s', 'swi', 'swp', 'swp_b', 'teq', 'tst',
'umlal', 'umlal_s', 'umull', 'umull_s',
)
for cond in CONDITIONALS:
for instr in CONDITIONAL_INSTRS:
if '_' in instr:
pfx = instr.split('_')[0]
CANONICALINSTRS[instr.replace('_', '')] = pfx
CANONICALINSTRS[instr.replace('_', cond)] = pfx
else:
CANONICALINSTRS[instr + cond] = instr
CANONICALINSTRS.update({
'bics': 'bic',
})
addrprofs = {}
for l in profinp:
l = l[:-1]
match = pat_prof.match(l)
if match is not None:
addr, count, percent = match.groups()
addr = int(addr, 16)
addrprofs[addr] = {'count': int(count)}
unused = 0
for l in disinp:
l = l[:-1]
match = pat_dis.match(l)
if match is not None:
addr, instr, operands = match.groups()
addr = int(addr, 16)
if addr not in addrprofs:
addrprofs[addr] = {'count': 0}
unused += 1
addrprofs[addr]['instr'] = instr
addrprofs[addr]['operands'] = operands
profs = addrprofs.items()
profs.sort(key=lambda (k, v): (v['count'], k), reverse=True)
totalcalls = sum(v['count'] for k, v in profs)
print "==== basic statistics ===="
print " Total calls:\t\t\t%12d" % totalcalls
print " Total lines of the code:\t%12d" % len(profs)
print " Unused code:\t\t\t%12d (%6.2f%%)" % (unused, unused / len(profs) * 100)
print
perinstr = {}
for addr, info in profs:
instr = CANONICALINSTRS.get(info['instr'], info['instr'])
if instr not in perinstr:
perinstr[instr] = 0
perinstr[instr] += info['count']
perinstr = perinstr.items()
perinstr.sort(key=lambda (k, v): (v, k), reverse=True)
print "==== frequent instructions ===="
accum = 0
for instr, freq in perinstr[:20]:
accum += freq
print "%s\t%10d\t%6.2f%%\t%6.2f%%" % (instr, freq, freq/totalcalls*100,
accum/totalcalls*100)
print
print "==== per-code statistics ===="
accumcalls = 0
for i, (addr, info) in enumerate(profs):
accumcalls += info['count']
print '%6d\t%6.2f%%\t%12d\t%6.2f%%\t%12d\t0x%08x\t%s\t%s' % (
i, i / len(profs) * 100.0,
accumcalls, accumcalls / totalcalls * 100.0,
info['count'],
addr, info['instr'], info['operands'],
)
# ex: ts=8 sts=4 sw=4 et