-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgdb_script.py
More file actions
55 lines (51 loc) · 1.73 KB
/
gdb_script.py
File metadata and controls
55 lines (51 loc) · 1.73 KB
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
import gdb
from graphviz import Digraph
# FUNCTION_NAMES and OUTFILE are passed in from outside via execfile arguments
class CallTracer:
def __init__(self, function_names, graph_name=None):
self.function_names = function_names
self.breakpoints = {}
for fn in function_names:
self.breakpoints[fn] = TracerBreakpoint(fn, internal=True, tracer=self)
self.dg = Digraph(graph_name)
self.nodes = set(function_names)
self.edges = set()
self.direct_connection_found = False
gdb.events.exited.connect(self.on_exit)
def on_breakpoint(self, breakpoint):
name = None
previous_name = None
f = gdb.newest_frame()
leaf_name = f.name()
while f is not None:
previous_name = name
name = f.name()
if not name:
name = "0x{:x}".format(f.pc())
if name not in self.nodes:
self.dg.node(name)
self.nodes.add(name)
if previous_name is not None and (name, previous_name) not in self.edges:
self.dg.edge(name, previous_name)
self.edges.add((name, previous_name))
if name != leaf_name and name in self.function_names:
self.direct_connection_found = True
break
f = f.older()
def on_exit(self, event):
if len(self.function_names) >= 2:
if self.direct_connection_found:
gdb.write("Direct connection found.\n")
else:
gdb.write("No direct connection between functions.\n")
self.dg.save(OUTFILE)
class TracerBreakpoint(gdb.Breakpoint):
def __init__(self, *args, **kwargs):
self.tracer = kwargs.pop("tracer")
gdb.Breakpoint.__init__(self, *args, **kwargs)
def stop(self):
try:
self.tracer.on_breakpoint(self)
finally:
return False
c = CallTracer(FUNCTION_NAMES, "test_graph")