wqdebug 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
wqdebug/__init__.py
ADDED
|
File without changes
|
wqdebug/wqdebug.py
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import re
|
|
4
|
+
import shutil
|
|
5
|
+
import argparse
|
|
6
|
+
import traceback
|
|
7
|
+
import tarfile
|
|
8
|
+
import glob
|
|
9
|
+
#import wq_coredump
|
|
10
|
+
from coredump.elf32 import *
|
|
11
|
+
from coredump.corefile import *
|
|
12
|
+
|
|
13
|
+
class WqDebug:
|
|
14
|
+
def __init__(self, log: str = "", wpk: str = "", elf: str = ""):
|
|
15
|
+
self.log = log
|
|
16
|
+
self.wpk = wpk
|
|
17
|
+
self.elf = elf
|
|
18
|
+
self.dumps = {}
|
|
19
|
+
self.dumps_index = 0
|
|
20
|
+
if self.log == "":
|
|
21
|
+
self.log = "test/test.log"
|
|
22
|
+
|
|
23
|
+
def start(self):
|
|
24
|
+
if self.select_log_file():
|
|
25
|
+
if self.find_coredump():
|
|
26
|
+
self.select_coredump()
|
|
27
|
+
|
|
28
|
+
def select_log_file(self):
|
|
29
|
+
user_input = input(
|
|
30
|
+
f"log:\n{self.log}\n请拖入LOG文件或输入文件路径, 输入回车Enter使用推荐文件:\n"
|
|
31
|
+
)
|
|
32
|
+
if user_input:
|
|
33
|
+
self.log = user_input
|
|
34
|
+
while not os.path.isfile(self.log):
|
|
35
|
+
print("文件路径不存在,请重新输入。")
|
|
36
|
+
self.select_log_file()
|
|
37
|
+
return True
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def serach_elf_file(core: str, log_path: str, wpk_path: str):
|
|
41
|
+
core_name_mapping = {"acore": "core0", "bcore": "core1", "dcore": "core4"}
|
|
42
|
+
core_name = core_name_mapping.get(core, "core0")
|
|
43
|
+
file_paths = [
|
|
44
|
+
os.path.join(os.path.dirname(log_path), f"*_{core}.elf"), # opencore
|
|
45
|
+
os.path.join(os.path.dirname(log_path), f"*_{core_name}.elf"), # ADK
|
|
46
|
+
os.path.join(os.path.dirname(wpk_path), f"*_{core_name}.elf"), # ADK
|
|
47
|
+
os.path.join(os.path.dirname(wpk_path), f"*_{core}.elf"), # opencore
|
|
48
|
+
os.path.join(
|
|
49
|
+
os.path.dirname(wpk_path), f"{core_name}", f"*_{core_name}.elf"
|
|
50
|
+
), # ADK
|
|
51
|
+
os.path.join(
|
|
52
|
+
os.path.dirname(wpk_path).replace("package", "bin"),
|
|
53
|
+
"tws_2_0",
|
|
54
|
+
f"{core}",
|
|
55
|
+
f"*_{core}.elf",
|
|
56
|
+
), # opencore
|
|
57
|
+
]
|
|
58
|
+
for file_path in file_paths:
|
|
59
|
+
# print(file_path)
|
|
60
|
+
for f in glob.glob(file_path):
|
|
61
|
+
# print(f)
|
|
62
|
+
if os.path.isfile(f):
|
|
63
|
+
return f
|
|
64
|
+
|
|
65
|
+
def select_elf_file(self, core="core0"):
|
|
66
|
+
# print(f"select_elf_file {core}")
|
|
67
|
+
if not os.path.isfile(self.elf):
|
|
68
|
+
self.elf = self.serach_elf_file(core, self.log, self.wpk)
|
|
69
|
+
user_input = input(
|
|
70
|
+
f"elf:\n{self.elf}\n请拖入ELF文件或输入文件路径, 输入回车Enter使用推荐文件:\n"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
if user_input:
|
|
74
|
+
self.elf = user_input
|
|
75
|
+
while not os.path.isfile(self.elf) or not self.elf.split(".")[-1] == "elf":
|
|
76
|
+
print("无效的ELF文件,请重新输入。")
|
|
77
|
+
self.select_elf_file("")
|
|
78
|
+
return self.elf
|
|
79
|
+
|
|
80
|
+
def find_coredump(self):
|
|
81
|
+
rc_mcause_coredump_old = re.compile(
|
|
82
|
+
r"[\[|【].*?([m|c]cause: .*?)\n[\s\S]*?"
|
|
83
|
+
r"================= CORE DUMP START =================([\s\S]*?)"
|
|
84
|
+
r"================= CORE DUMP END ================="
|
|
85
|
+
)
|
|
86
|
+
rc_mcause_coredump = re.compile(
|
|
87
|
+
r"[\[|【]([A|B|D]).*?([m|c]cause: .*?)\n[\s\S]*?"
|
|
88
|
+
r"================= CORE\d? DUMP START =================([\s\S]*?)"
|
|
89
|
+
r"================= CORE\d? DUMP END ================="
|
|
90
|
+
)
|
|
91
|
+
rc_time_coredump = re.compile(r".*?>")
|
|
92
|
+
rc_time_coredump_old = re.compile(r".*?\] ")
|
|
93
|
+
with open(self.log, "r", encoding="utf-8", errors="ignore") as f:
|
|
94
|
+
log_data_all = f.read()
|
|
95
|
+
print(f"正在查找LOG文件中的coredump信息...")
|
|
96
|
+
log_data_list = log_data_all.split("Core dump has written to uart")
|
|
97
|
+
found_coredump = False
|
|
98
|
+
index = 0
|
|
99
|
+
for log_data in log_data_list:
|
|
100
|
+
# print("log_data=", log_data[0:128])
|
|
101
|
+
match_list = rc_mcause_coredump.finditer(log_data)
|
|
102
|
+
for m in match_list:
|
|
103
|
+
reason = f"{index}. {m.group(1)}core {m.group(2)}"
|
|
104
|
+
print(reason)
|
|
105
|
+
self.dumps[reason] = re.sub(
|
|
106
|
+
rc_time_coredump_old,
|
|
107
|
+
"",
|
|
108
|
+
re.sub(rc_time_coredump, "", m.group(3)),
|
|
109
|
+
)
|
|
110
|
+
found_coredump = True
|
|
111
|
+
index += 1
|
|
112
|
+
if index >= 2:
|
|
113
|
+
break
|
|
114
|
+
if not found_coredump:
|
|
115
|
+
print(f"正在查找rc_mcause_coredump_old...")
|
|
116
|
+
for log_data in log_data_list:
|
|
117
|
+
# print("log_data=", log_data[0:128])
|
|
118
|
+
match_list = rc_mcause_coredump_old.finditer(log_data)
|
|
119
|
+
for m in match_list:
|
|
120
|
+
reason = f"{index}. {m.group(1)}"
|
|
121
|
+
print(reason)
|
|
122
|
+
self.dumps[reason] = re.sub(
|
|
123
|
+
rc_time_coredump_old,
|
|
124
|
+
"",
|
|
125
|
+
re.sub(rc_time_coredump, "", m.group(2)),
|
|
126
|
+
)
|
|
127
|
+
found_coredump = True
|
|
128
|
+
index += 1
|
|
129
|
+
if index >= 2:
|
|
130
|
+
break
|
|
131
|
+
|
|
132
|
+
if not found_coredump:
|
|
133
|
+
print(f"{self.log} LOG 文件无效,未找到有效的coredump信息。")
|
|
134
|
+
else:
|
|
135
|
+
print(f"找到 {len(self.dumps)} 个coredump信息")
|
|
136
|
+
return True
|
|
137
|
+
|
|
138
|
+
def get_core_name(self, dump):
|
|
139
|
+
rc_core_name = re.compile(r"([A|B|D])core")
|
|
140
|
+
# print(rc_core_name, dump)
|
|
141
|
+
core_name = re.search(rc_core_name, dump)
|
|
142
|
+
if core_name:
|
|
143
|
+
return core_name.group()
|
|
144
|
+
return "acore"
|
|
145
|
+
|
|
146
|
+
def select_coredump(self):
|
|
147
|
+
user_input = input(f"\n请输入 coredump 编号, 输入回车Enter使用默认0\n:")
|
|
148
|
+
if not user_input:
|
|
149
|
+
self.dumps_index = 0
|
|
150
|
+
print(f"{list(self.dumps.keys())[self.dumps_index]}")
|
|
151
|
+
elif user_input.isdigit() and 0 <= int(user_input) < len(self.dumps):
|
|
152
|
+
self.dumps_index = int(user_input)
|
|
153
|
+
print(f"{list(self.dumps.keys())[self.dumps_index]}")
|
|
154
|
+
else:
|
|
155
|
+
print(f"请输入是介于 0 到 {len(self.dumps) - 1} 之间的数字")
|
|
156
|
+
self.select_coredump()
|
|
157
|
+
|
|
158
|
+
core_name = self.get_core_name(list(self.dumps.keys())[self.dumps_index])
|
|
159
|
+
elf = self.select_elf_file(core_name)
|
|
160
|
+
if not os.path.exists("temp"):
|
|
161
|
+
os.makedirs("temp")
|
|
162
|
+
shutil.copy(elf, f"temp/coredump_{core_name}.elf")
|
|
163
|
+
|
|
164
|
+
reason = list(self.dumps.keys())[self.dumps_index]
|
|
165
|
+
with open(os.path.join(f"temp/coredump_{core_name}.b64"), "w") as f:
|
|
166
|
+
f.write(self.dumps[reason].strip())
|
|
167
|
+
|
|
168
|
+
# loader = wq_coredump.WQCoreDumpFileLoader(
|
|
169
|
+
# f"temp/coredump_{core_name}.b64", True
|
|
170
|
+
# )
|
|
171
|
+
# coredump_bin = loader.create_corefile(f"temp/coredump_{core_name}.bin")
|
|
172
|
+
|
|
173
|
+
coredump_bin = f"temp/coredump_{core_name}.bin"
|
|
174
|
+
cf = CoreFile(machine="riscv")
|
|
175
|
+
cf.load(corefile=f"temp/coredump_{core_name}.b64")
|
|
176
|
+
cf.save(coredump_bin)
|
|
177
|
+
|
|
178
|
+
coredump_elf = f"temp/coredump_{core_name}.elf"
|
|
179
|
+
gdbinit = "gdbinit.py"
|
|
180
|
+
gdb = "riscv/bin/riscv32-unknown-elf-gdb"
|
|
181
|
+
if not os.path.isfile(gdb):
|
|
182
|
+
self.download_gdb()
|
|
183
|
+
cmd = (
|
|
184
|
+
f"start wsl echo \033[91m {reason} \033[0m;"
|
|
185
|
+
f"{gdb} -q -command={gdbinit} --nw -core={coredump_bin} {coredump_elf};read"
|
|
186
|
+
)
|
|
187
|
+
print(cmd)
|
|
188
|
+
os.system(cmd)
|
|
189
|
+
sys.exit(0)
|
|
190
|
+
|
|
191
|
+
def download_gdb(self):
|
|
192
|
+
this_dir = os.path.dirname(__file__)
|
|
193
|
+
gdb_path = f"\\\\192.168.100.55\\share\\wuqi_toolchain\\riscv_gdb.tar.gz"
|
|
194
|
+
local_gdb = os.path.join("\\riscv")
|
|
195
|
+
print("未找到GDB,下载中 ......")
|
|
196
|
+
print(gdb_path)
|
|
197
|
+
if not os.path.exists(local_gdb):
|
|
198
|
+
shutil.copy2(gdb_path, this_dir)
|
|
199
|
+
print("下载完成")
|
|
200
|
+
tarfile.open(os.path.join(this_dir, os.path.basename(gdb_path))).extractall(
|
|
201
|
+
path=this_dir
|
|
202
|
+
)
|
|
203
|
+
os.remove(os.path.join(this_dir, os.path.basename(gdb_path)))
|
|
204
|
+
print(os.path.join(this_dir, os.path.basename(gdb_path)))
|
|
205
|
+
|
|
206
|
+
def main():
|
|
207
|
+
__version__ = "0.0.0.1"
|
|
208
|
+
print(f"wq debug v:{__version__}")
|
|
209
|
+
os.chdir(os.path.dirname(__file__))
|
|
210
|
+
print(sys.argv)
|
|
211
|
+
try:
|
|
212
|
+
parser = argparse.ArgumentParser(description=f"wq debug v:{__version__}")
|
|
213
|
+
parser.add_argument(
|
|
214
|
+
"-l",
|
|
215
|
+
"--log",
|
|
216
|
+
help="log file path",
|
|
217
|
+
nargs="?",
|
|
218
|
+
const="",
|
|
219
|
+
type=str,
|
|
220
|
+
default="",
|
|
221
|
+
)
|
|
222
|
+
parser.add_argument("-e", "--elf", help="elf file path", type=str, default="")
|
|
223
|
+
parser.add_argument(
|
|
224
|
+
"-w",
|
|
225
|
+
"--wpk",
|
|
226
|
+
help="wpk file path, infer the elf file path from the wpk file path",
|
|
227
|
+
nargs="?",
|
|
228
|
+
const="",
|
|
229
|
+
type=str,
|
|
230
|
+
default="",
|
|
231
|
+
)
|
|
232
|
+
args = parser.parse_args()
|
|
233
|
+
# print(args.log, args.wpk, args.elf)
|
|
234
|
+
wq_debug = WqDebug(args.log, args.wpk, args.elf)
|
|
235
|
+
wq_debug.start()
|
|
236
|
+
except Exception as e:
|
|
237
|
+
print(e)
|
|
238
|
+
traceback.print_exc()
|
|
239
|
+
input("请按下回车键退出...")
|
|
240
|
+
|
|
241
|
+
if __name__ == "__main__":
|
|
242
|
+
main()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: wqdebug
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python module for wuqi debug
|
|
5
|
+
Home-page: UNKNOWN
|
|
6
|
+
Author: deng.weiwei
|
|
7
|
+
Author-email: deng.weiwei@wuqi-tech.com
|
|
8
|
+
License: Apache License 2.0
|
|
9
|
+
Platform: UNKNOWN
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
23
|
+
Requires-Python: >=3.6
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# wqdebug
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
pip install wqdebug
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
wqdebug log.txt core.elf
|
|
33
|
+
|
|
34
|
+
## Develop
|
|
35
|
+
pip install -e .
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
wqdebug/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
wqdebug/wqdebug.py,sha256=7FDzB8s_nKM27tXUmnDak1JLXju3O3hE6B4bgv0njQg,9511
|
|
3
|
+
wqdebug-1.0.0.dist-info/METADATA,sha256=xafHhtK6nPgMIl6gvS8QzEP8930cko0ZLljFkJSUkZQ,1047
|
|
4
|
+
wqdebug-1.0.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
5
|
+
wqdebug-1.0.0.dist-info/entry_points.txt,sha256=ix3_TA7GmEqoZrj3Wm2dKaMn9Y8UK7CzOBLtshsHeEQ,50
|
|
6
|
+
wqdebug-1.0.0.dist-info/top_level.txt,sha256=hhf-ZrcV5IeL12n1B6GuG6qZKbWMlCNXOL1M951iSWw,8
|
|
7
|
+
wqdebug-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
wqdebug
|