
* No Usermode default * no tui * gg * try fix CI * fmt --------- Co-authored-by: Dominik Maier <dmnk@google.com>
70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
#!/usr/bin/python3
|
|
|
|
import json
|
|
import os
|
|
import networkx as nx
|
|
import sys
|
|
|
|
cfg = dict()
|
|
|
|
if "CFG_OUTPUT_PATH" not in os.environ:
|
|
sys.exit("CFG_OUTPUT_PATH not set")
|
|
|
|
input_path = os.environ["CFG_OUTPUT_PATH"]
|
|
|
|
|
|
for dirpath, _, files in os.walk(input_path):
|
|
for x in files:
|
|
if x.endswith(".cfg"):
|
|
cfg[x] = json.load(open(os.path.join(dirpath, x)))
|
|
|
|
G = nx.DiGraph()
|
|
GG = nx.DiGraph()
|
|
# First add all the edges
|
|
|
|
node_ids = 0
|
|
f_ids = 0
|
|
|
|
fname2id = dict()
|
|
|
|
for mname, module in cfg.items():
|
|
fnname2SG = dict()
|
|
# First, add all the intra-procedural edges
|
|
|
|
for fname, v in module["edges"].items():
|
|
if fname not in fname2id:
|
|
GG.add_node(f_ids, label=fname)
|
|
fname2id[fname] = f_ids
|
|
f_ids += 1
|
|
|
|
sz = len(v)
|
|
for idx in range(node_ids, node_ids + sz):
|
|
G.add_node(idx)
|
|
G.nodes[idx]["label"] = mname + " " + fname + " " + str(idx - node_ids)
|
|
node_id_list = list(range(node_ids, node_ids + sz))
|
|
node_ids += sz
|
|
SG = G.subgraph(node_id_list)
|
|
fnname2SG[fname] = SG
|
|
for src, dsts in enumerate(v):
|
|
for item in dsts:
|
|
G.add_edge(node_id_list[src], node_id_list[item])
|
|
|
|
# Next, build inter-procedural edges
|
|
for fname, calls in module["calls"].items():
|
|
for idx, target_fns in calls.items():
|
|
# G.nodes isn't sorted
|
|
|
|
src = sorted(fnname2SG[fname].nodes())[0] + int(idx)
|
|
for target_fn in target_fns:
|
|
if target_fn in fnname2SG:
|
|
offset = module["entries"][target_fn]
|
|
|
|
dst = sorted(fnname2SG[target_fn].nodes)[0] + offset
|
|
|
|
# Now we have 2 index, build the edge
|
|
G.add_edge(src, dst)
|
|
GG.add_edge(fname2id[fname], fname2id[target_fn])
|
|
|
|
nx.nx_agraph.write_dot(G, "cfg.xdot")
|
|
nx.nx_agraph.write_dot(GG, "cg.xdot")
|