80 lines
3.0 KiB
Python
80 lines
3.0 KiB
Python
import sys, os, cPickle, argparse
|
|
#Process the data of a workspace and prints out some global information
|
|
|
|
def parse_arguments():
|
|
################################################################################
|
|
# parse arguments
|
|
parser = argparse.ArgumentParser(description='Extract different statistic and information from a manticore workspace')
|
|
parser.add_argument('--workspace', type=str, default=None,
|
|
help='A folder name fpor temporaries and results. (default mcore_?????)')
|
|
parser.add_argument('--pcfreq', action='store_true', help='Print out visited pc and frequency')
|
|
parser.add_argument('--visited', action='store_true', help='Print out visited pc set')
|
|
parser.add_argument('--bbs', action='store_true', help='Print out visited basic blocks ')
|
|
|
|
parser.add_argument('workspace', type=str, nargs=1, metavar='WORKSPACE',
|
|
help='The folder name for temporaries and results' )
|
|
parsed = parser.parse_args(sys.argv[1:])
|
|
parsed.workspace = parsed.workspace[0]
|
|
|
|
assert int(parsed.pcfreq) + int(parsed.visited)+ int(parsed.bbs) == 1, "Choose one option one option from: --pcfreq --visited"
|
|
return parsed
|
|
|
|
|
|
args = parse_arguments()
|
|
workspace = args.workspace
|
|
|
|
#search previously generated states
|
|
saved_states = [ os.path.join(workspace, filename) for filename in os.listdir(workspace) if filename.endswith('.pkl') ]
|
|
#prepare a dictionary to hold stats
|
|
db = {}
|
|
edges = {}
|
|
for filename in saved_states:
|
|
try:
|
|
with open(filename, "r") as f:
|
|
#load the whole saved state (memory/cpu/solver/..)
|
|
state = cPickle.loads(f.read())
|
|
lastpc = 'ROOT'
|
|
for proc, pc in state.visited:
|
|
assert proc == 0, 'Multi process no supported'
|
|
db[pc] = db.setdefault(pc,0) + 1
|
|
edges.setdefault(lastpc,[]).append(pc)
|
|
lastpc=pc
|
|
except Exception,e:
|
|
print "#Failed to load saved state %s (%s)"%(filename,e)
|
|
|
|
if args.pcfreq :
|
|
print '#PC: frequency'
|
|
for pc, freq in sorted(db.items(), key=lambda x: -x[1]):
|
|
print '%x: %d'%(pc,freq)
|
|
elif args.visited:
|
|
print '#PC'
|
|
for pc in db.keys():
|
|
print '%x'%pc
|
|
elif args.bbs:
|
|
assert len(set(edges['ROOT'])) == 1, "Something is wrong it should be only one root"
|
|
bbs = set()
|
|
for targets in edges.values():
|
|
if len(set(targets)) > 1:
|
|
[ bbs.add(x) for x in set(targets) ]
|
|
bbs.add('ROOT')
|
|
print '#BBs'
|
|
for origin in bbs:
|
|
if origin not in edges:
|
|
targets = set()
|
|
else:
|
|
targets = set(edges[origin])
|
|
while len(targets) == 1:
|
|
node = list(targets)[0]
|
|
if node in edges:
|
|
targets = set(edges[node])
|
|
else:
|
|
targets = ['END']
|
|
break
|
|
|
|
def p(x):
|
|
return isinstance(x, (int, long)) and hex(x) or x
|
|
|
|
print '%s -> [%s]'%(p(origin), ', '.join(map(p, targets)) )
|
|
|
|
|