forked from yhryyq/cfgtool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsinglefunc_dot2graph.py
137 lines (102 loc) · 4.25 KB
/
singlefunc_dot2graph.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from getdot import read_dot_files
from pybgl.graph import DirectedGraph
from collections import namedtuple,deque
"""
def dfs(graph, start_vertex, vertex_map):
visited = set()
stack = deque([start_vertex])
while stack:
v = stack.pop()
if v not in visited:
visited.add(v)
for e in graph.out_edges(v):
target = graph.target(e)
if target not in visited:
stack.append(target)
# 将访问过的顶点转换为 line_number
return [line_number for line_number, vertex in vertex_map.items() if vertex in visited]
"""
def dfs(graph, start_vertex, visited=None):
if visited is None:
visited = set()
stack = [start_vertex]
while stack:
current = stack.pop()
if current not in visited:
visited.add(current)
current_data = node_data_map[current]
print(f"当前顶点: {current}, 行号: {current_data.line_number}, 函数名: {current_data.function_name}")
print(current_data)
if current_data.callsites:
print(f" - Callsites: {current_data.callsites}")
for e in graph.out_edges(current):
target = graph.target(e)
stack.append(target)
return visited
NodeData = namedtuple('NodeData', ['line_number', 'line_flows', 'node_code', 'callsites', 'is_return_line', 'function_name'])
funcs = read_dot_files("./outdir")
#funcs: function_name, line_flows, callsites, node_code, return_lines
graphs = {}
for func in funcs:
g = DirectedGraph()
function_data = {
'line_numbers': list(func[1].keys()),
'line_flows': func[1],
'node_code': func[3],
'callsites': func[2],
'function_name': func[0],
'return_lines': func[4]
}
node_data_map = {}
vertex_map = {} #vertex to lineNumber
#create node for each line
for line_number in function_data['line_numbers']:
v = g.add_vertex()
if line_number in function_data['return_lines']:
return_line = True
else:
return_line = False
node_data = NodeData(
line_number=line_number,
line_flows=function_data['line_flows'].get(line_number, []),
node_code=function_data['node_code'].get(line_number, ''),
callsites=function_data['callsites'].get(line_number, []),
is_return_line = return_line,
function_name=function_data['function_name']
)
#print(node_data)
node_data_map[v] = node_data
vertex_map[line_number] = v
#create edge
for line_number, flows in function_data['line_flows'].items():
source_vertex = vertex_map[line_number]
for target_line_number in flows:
target_vertex = vertex_map[target_line_number]
g.add_edge(source_vertex, target_vertex)
graphs[function_data['function_name']] = {'graph': g, 'node_data_map': node_data_map, 'vertex_map': vertex_map}
"""
for func_name, data in graphs.items():
graph = data['graph']
node_data_map = data['node_data_map']
vertex_map = data['vertex_map']
for v, node_data in node_data_map.items():
for callsite in node_data.callsites:
if callsite in graphs:
called_func_data = graphs[callsite]
called_graph = called_func_data['graph']
called_node_data_map = called_func_data['node_data_map']
called_vertex_map = called_func_data['vertex_map']
entry_line_number = min(called_vertex_map.keys())
entry_vertex = called_vertex_map[entry_line_number]
graph.add_edge(v, entry_vertex)
for rv, rnode_data in called_node_data_map.items():
if rnode_data.is_return_line:
called_graph.add_edge(rv, v)
"""
function_name = "main"
start_line_number = 11
start_graph = graphs[function_name]['graph']
start_vertex = vertex_map[start_line_number]
reachable_vertices = dfs(start_graph, start_vertex)
reachable_info = [(node_data_map[v].line_number, node_data_map[v].function_name) for v in reachable_vertices]
print(f"从函数 {function_name} 的行号 {start_line_number} 可达的行号和函数名: {reachable_info}")