Files
Eric Hennenfent 451965f03a Blacken Manticore (#1438)
* Add black to CI tests

I'd rather have blackening be an optional check, but this will work for now

* Yep, messed up Travis

Again, sorry about the commit spam

* Bump accepted line length to 120

Going to auto-format at 100 but will allow 20% overruns

* Blacken

* Cap line length at 100

rip my undisciplined coding habits

* update black on the fly if necessary

* Ignore CC errors

* Only check modified files

* Only python files

* Re-blacken post merge

* Re-Blacken

* Fix deleted files

* Explicitly invoke python

The +x must not have gotten commited

* Forgot to blacken again

Hoisted on my own petard

* Re-blacken
2019-05-23 15:19:24 -05:00

98 lines
3.1 KiB
Python

import sys, os, pickle, 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 for 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 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 states
db = {}
edges = {}
for filename in saved_states:
try:
with open(filename, "rb") as f:
# load the whole saved state (memory/cpu/solver/..)
state = pickle.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 as e:
print(f"#Failed to load saved state {filename} ({str(e)})")
if args.pcfreq:
print("#PC: frequency")
for pc, freq in sorted(list(db.items()), key=lambda x: -x[1]):
print(f"{pc:x}: {freq}")
elif args.visited:
print("#PC")
for pc in list(db.keys()):
print(f"{pc:x}")
elif args.bbs:
assert len(set(edges["ROOT"])) == 1, "Something is wrong; there should be only one root"
bbs = set()
for targets in list(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 hex(x) if isinstance(x, int) else x
print(f'{p(origin)} -> [{", ".join(map(p, targets))}]')