-
Notifications
You must be signed in to change notification settings - Fork 0
/
scopeguard.py
96 lines (74 loc) · 2.7 KB
/
scopeguard.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
#!/usr/bin/python3
'''
Active comment allows gdb to automatically set breakpoints and provide information based on the content of files.
'''
import gdb
import os
import re
from colorama import *
init()
gdb.sg_active = True
SCOPE_HEADER = f"{Fore.GREEN+Style.BRIGHT}[ScopeGuard]{Style.RESET_ALL}:"
print(f"{SCOPE_HEADER} ScopeGuard active. Disable with sg off")
def is_local_path(f):
return not any([
f is None,
f == "",
f.startswith("../sysdeps"),
f.startswith("/usr/"),
f.startswith("/build/"),
".so" in f[-6:],
"system-suppplied" in f,
])
def on_break(event):
if not gdb.sg_active:
return
local_frames = []
local_frame_info = []
other_frames = []
frame_num = 1
lowest_frame = 0
cur_frame = gdb.newest_frame()
while cur_frame is not None:
frame_function = cur_frame.function()
if frame_function is None:
print(f"{SCOPE_HEADER} Did you not include debug information in your files?")
break
frame_file = frame_function.name
frame_path = frame_function.symtab.fullname()
frame_line = frame_function.line
frame_num += 1
if is_local_path(frame_path):
local_frames.append(cur_frame)
frame_info = f"{frame_file}({frame_function}:{frame_line})"
local_frame_info.append((frame_num, frame_info))
else:
other_frames.append(cur_frame)
if len(local_frames) == 0:
lowest_frame += 1
cur_frame = cur_frame.older()
if local_frames:
up_log = gdb.execute(f"up-silently {lowest_frame}", to_string=True)
else:
print(f"{SCOPE_HEADER} Could not find a local frame!")
return
if lowest_frame > 0:
print(f"{SCOPE_HEADER} Skipped over {lowest_frame} frames to show your function.")
if len(local_frames) > 1:
print(f"{SCOPE_HEADER} Use {Style.DIM}f <number>{Style.RESET_ALL} to inspect that function:")
for f_num, f_info in local_frame_info:
print(f"{SCOPE_HEADER} {Style.DIM}f {f_num}{Style.RESET_ALL} | {f_info}")
gdb.events.stop.connect(on_break)
class ScopeGuardToggle(gdb.Command):
def __init__(self, name):
super().__init__(name, gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
if arg.lower() in ["off", "false"]:
gdb.sg_active = False
print(f"{SCOPE_HEADER} ScopeGuard inactive.")
elif arg.lower() in ["on", "true"]:
gdb.sg_active = True
print(f"{SCOPE_HEADER} ScopeGuard active.")
else:
print("scopeguard used incorrectly. use sg [on/off]")
ScopeGuardToggle("sg")