forked from 4z0t/SCFA-python-patcher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Debug.py
141 lines (111 loc) · 3.54 KB
/
Debug.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
136
137
138
139
140
141
import os
import sys
from pathlib import Path
import re
LOC_ADDR_RE = re.compile("loc_([0-9a-fA-F]){1,6}")
SPACES_RE = re.compile(" +")
def get_log_path(args: list[str]) -> str:
found = False
for arg in args:
if found:
return arg
if arg == "/log":
found = True
continue
return None
def extract_crash_data(log_path: Path) -> list[str]:
result = []
with open(log_path, "r") as log_file:
line = ""
while not line.startswith("Exit code:"):
line = log_file.readline()
while not line.startswith("MiniDump:"):
result.append(line)
line = log_file.readline()
return result
def load_exe_map(map_path: Path) -> list[tuple[int, str]]:
map: list[tuple[int, str]] = []
with open(map_path, "r") as map_file:
line = map_file.readline()
while line:
line = line.strip()
address, name = line.split(" ", 1)
map.append((int(address, 16), name))
line = map_file.readline()
return map
def load_sect_map(map_path: Path) -> list[tuple[int, str]]:
map: list[tuple[int, str]] = []
is_text = False
with open(map_path, "r") as map_file:
line = map_file.readline()
while line:
cur_line = line.strip()
line = map_file.readline()
if cur_line.startswith(".text"):
is_text = True
continue
if not cur_line.startswith("0x"):
is_text = False
continue
if is_text:
cur_line = SPACES_RE.sub(" ", cur_line)
address, name = cur_line.split(" ", 1)
map.append((int(address, 16), name))
return map
def can_convert_to_hex(num: str):
try:
int(num, 16)
return True
except ValueError:
return False
def get_stack_trace(data: list[str]) -> list[int]:
stack_trace = []
for line in data:
if line.startswith("Stacktrace:"):
_, * trace = line.split(" ")
stack_trace.extend((int(i, 16)
for i in trace if can_convert_to_hex(i)))
break
return stack_trace
def format_stack_trace(trace: list[int], names: list[tuple[int, str]]) -> str:
def find_name(address: int) -> tuple[int, str]:
start = 0
end = len(names)
while True:
middle = (start+end)//2
addr, name = names[middle]
if addr > address:
end = middle
else:
start = middle
if end - start <= 1:
return names[start]
s = []
for addr in trace:
address, name = find_name(addr)
s.append(f"{address:08x}\t{name}")
return "\n".join(s)
def main(patches_folder_path, args):
code = os.system(" ".join(args))
if code == 0:
return
log_file_name = get_log_path(args)
if log_file_name is None:
print("Couldn't find log file name")
return
log_path = Path(log_file_name)
data = extract_crash_data(log_path)
for line in data[::-1]:
if line.strip() == "":
data.pop()
else:
break
exe_map = load_exe_map(Path("./statistics/exe.map"))
sect = load_sect_map(Path(patches_folder_path)/"build"/"sectmap.txt")
exe_map.extend(sect)
stack_trace = get_stack_trace(data)
s = format_stack_trace(stack_trace, exe_map)
print("".join(data))
print(s)
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2:])