image.png
根据上图中的结论,PDT 可以由 Reversed CFG 求 Dominance Tree 而得。

给出一个 CFG:

  1. from graphviz import Digraph
  2. from IPython.display import Image
  3. code = """
  4. 0 Start
  5. 1 A
  6. 2 B
  7. 3 C
  8. 4 D
  9. 5 E
  10. 6 F
  11. 7 End
  12. """
  13. buggy_nos = [14]
  14. buggy_nos = [ str(a) for a in buggy_nos ]
  15. gz=Digraph("CFG",'comment',None,None,'png',None,"UTF-8",
  16. {'rankdir':'TB'},
  17. {'color':'black','fontcolor':'black','fontname':'FangSong','fontsize':'12','style':'rounded','shape':'box'},
  18. {'color':'#999999','fontcolor':'#888888','fontsize':'10','fontname':'FangSong'},None,False)
  19. for line in code.strip().split("\n"):
  20. # print("ll:", line)
  21. l_num, l_code = line.split(" ", 1)
  22. if l_code.strip() == '{' or l_code.strip() == '}':
  23. continue
  24. if l_code == 'End' or l_code == 'Start':
  25. l_text = l_code
  26. else:
  27. l_text = l_code
  28. if l_num in buggy_nos:
  29. gz.node( l_num, l_text, {'color':'red','fontcolor':'red'})
  30. else:
  31. gz.node( l_num, l_text )
  32. CFG_edges = [[0, 1], [1, 2], [1, 3], [2, 4], [3, 4], [4, 5], [5, 6], [6, 7], [6, 5]]
  33. for a, b in CFG_edges:
  34. gz.edge( str(a), str(b))
  35. # print(gz.source)
  36. gz.view()
  37. Image("CFG.gv.png")

输出:
image.png

生成 PDT:

  1. gz=Digraph("PDT",'comment',None,None,'png',None,"UTF-8",
  2. {'rankdir':'TB'},
  3. {'color':'black','fontcolor':'black','fontname':'FangSong','fontsize':'12','style':'rounded','shape':'box'},
  4. {'color':'#999999','fontcolor':'#888888','fontsize':'10','fontname':'FangSong'},None,False)
  5. for line in code.strip().split("\n"):
  6. # print("ll:", line)
  7. l_num, l_code = line.split(" ", 1)
  8. if l_code.strip() == '{' or l_code.strip() == '}':
  9. continue
  10. if l_code == 'End' or l_code == 'Start':
  11. l_text = l_code
  12. else:
  13. l_text = l_code
  14. if l_num in buggy_nos:
  15. gz.node( l_num, l_text, {'color':'red','fontcolor':'red'})
  16. else:
  17. gz.node( l_num, l_text )
  18. reversed_cfg_edges = []
  19. for row in CFG_edges:
  20. reversed_cfg_edges.append( [row[1], row[0]] )
  21. G = nx.DiGraph()
  22. G.add_edges_from(reversed_cfg_edges)
  23. start = reversed_cfg_edges[0][0]
  24. for edge in reversed_cfg_edges:
  25. for node in edge:
  26. if node >= start:
  27. start = node
  28. edgelist = sorted(nx.immediate_dominators(G, start).items())
  29. edgelist = [list(x) for x in edgelist]
  30. for a, b in edgelist:
  31. gz.edge( str(b), str(a))
  32. # print(gz.source)
  33. gz.view()
  34. Image("PDT.gv.png")

得到的 PDT 为:

image.png