根据上图中的结论,PDT 可以由 Reversed CFG 求 Dominance Tree 而得。
给出一个 CFG:
from graphviz import Digraph
from IPython.display import Image
code = """
0 Start
1 A
2 B
3 C
4 D
5 E
6 F
7 End
"""
buggy_nos = [14]
buggy_nos = [ str(a) for a in buggy_nos ]
gz=Digraph("CFG",'comment',None,None,'png',None,"UTF-8",
{'rankdir':'TB'},
{'color':'black','fontcolor':'black','fontname':'FangSong','fontsize':'12','style':'rounded','shape':'box'},
{'color':'#999999','fontcolor':'#888888','fontsize':'10','fontname':'FangSong'},None,False)
for line in code.strip().split("\n"):
# print("ll:", line)
l_num, l_code = line.split(" ", 1)
if l_code.strip() == '{' or l_code.strip() == '}':
continue
if l_code == 'End' or l_code == 'Start':
l_text = l_code
else:
l_text = l_code
if l_num in buggy_nos:
gz.node( l_num, l_text, {'color':'red','fontcolor':'red'})
else:
gz.node( l_num, l_text )
CFG_edges = [[0, 1], [1, 2], [1, 3], [2, 4], [3, 4], [4, 5], [5, 6], [6, 7], [6, 5]]
for a, b in CFG_edges:
gz.edge( str(a), str(b))
# print(gz.source)
gz.view()
Image("CFG.gv.png")
生成 PDT:
gz=Digraph("PDT",'comment',None,None,'png',None,"UTF-8",
{'rankdir':'TB'},
{'color':'black','fontcolor':'black','fontname':'FangSong','fontsize':'12','style':'rounded','shape':'box'},
{'color':'#999999','fontcolor':'#888888','fontsize':'10','fontname':'FangSong'},None,False)
for line in code.strip().split("\n"):
# print("ll:", line)
l_num, l_code = line.split(" ", 1)
if l_code.strip() == '{' or l_code.strip() == '}':
continue
if l_code == 'End' or l_code == 'Start':
l_text = l_code
else:
l_text = l_code
if l_num in buggy_nos:
gz.node( l_num, l_text, {'color':'red','fontcolor':'red'})
else:
gz.node( l_num, l_text )
reversed_cfg_edges = []
for row in CFG_edges:
reversed_cfg_edges.append( [row[1], row[0]] )
G = nx.DiGraph()
G.add_edges_from(reversed_cfg_edges)
start = reversed_cfg_edges[0][0]
for edge in reversed_cfg_edges:
for node in edge:
if node >= start:
start = node
edgelist = sorted(nx.immediate_dominators(G, start).items())
edgelist = [list(x) for x in edgelist]
for a, b in edgelist:
gz.edge( str(b), str(a))
# print(gz.source)
gz.view()
Image("PDT.gv.png")
得到的 PDT 为: