Skip to content

Commit 76c086c

Browse files
Jyri Sarhalgirdwood
authored andcommitted
scripts: sof-crash-decode: support debug_stream.py exception format
The debug_stream.py tool outputs exception records in a format that differs from the QEMU format the decoder originally targeted: - Register values can be (nil) instead of 0x0, e.g. 'A4 (nil)' - Backtrace entries are on separate lines after 'Backtrace:' rather than all on a single line - Additional registers LCOUNT and THREADPTR are present Update the parser to handle both formats: - Fix (nil) regex: the trailing word boundary anchor failed on the closing parenthesis; split hex and decimal into separate capture groups to avoid the issue - Parse backtrace entries across multiple lines after the Backtrace: header, stopping when a line contains non-backtrace content - Add LCOUNT and THREADPTR to the accepted register list The existing single-line backtrace and QEMU register formats continue to work unchanged. Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
1 parent 331b378 commit 76c086c

1 file changed

Lines changed: 24 additions & 12 deletions

File tree

scripts/sof-crash-decode.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -157,32 +157,44 @@ def parse_crash_log(content):
157157
elif re.match(r'^AR\d{2}$', reg):
158158
reg = f"AR{int(reg[2:])}"
159159

160-
if re.match(r'^(PC|PR|SP|A\d+|AR\d+|EXCCAUSE|VADDR|LBEG|LEND|SAR|EPC\d+|EPS\d+|PS)$', reg):
160+
if re.match(r'^(PC|PR|SP|A\d+|AR\d+|EXCCAUSE|VADDR|LBEG|LEND|LCOUNT|SAR|EPC\d+|EPS\d+|PS|THREADPTR)$', reg):
161161
registers[reg] = val
162162
else:
163163
# Standard format
164164
# regex for registers: we want standalone pairs like PC 0x123 or A0 0x123 or EXCCAUSE 9
165-
reg_pattern = re.compile(r'\b([A-Z0-9]+)\s+(0x[0-9a-fA-F]+|\d+|(?:nil))\b')
165+
# Also handle (nil) for zero-valued registers like A4 (nil) or THREADPTR (nil)
166+
reg_pattern = re.compile(r'\b([A-Z0-9]+)\s+(?:(0x[0-9a-fA-F]+)\b|(\d+)\b|\(nil\))')
166167
for match in reg_pattern.finditer(content):
167168
reg = match.group(1)
168-
val_str = match.group(2)
169-
if val_str == "(nil)":
170-
val = 0
171-
elif val_str.startswith("0x"):
172-
val = int(val_str, 16)
169+
hex_str = match.group(2)
170+
dec_str = match.group(3)
171+
if hex_str:
172+
val = int(hex_str, 16)
173+
elif dec_str:
174+
val = int(dec_str)
173175
else:
174-
val = int(val_str)
176+
val = 0
175177

176178
# Keep only known registers or likely candidates
177-
if re.match(r'^(PC|PR|SP|A\d+|AR\d+|EXCCAUSE|VADDR|LBEG|LEND|SAR|EPC\d+|EPS\d+|PS)$', reg):
179+
if re.match(r'^(PC|PR|SP|A\d+|AR\d+|EXCCAUSE|VADDR|LBEG|LEND|LCOUNT|SAR|EPC\d+|EPS\d+|PS|THREADPTR)$', reg):
178180
registers[reg] = val
179181

180-
# Backtrace parsing
182+
# Backtrace parsing: support both single-line and multi-line formats
183+
# Single-line: "Backtrace: 0xPC:0xSP 0xPC:0xSP ..."
184+
# Multi-line: "Backtrace:\n0xPC:0xSP\n0xPC:0xSP\n..."
181185
bt_idx = content.find("Backtrace:")
182186
if bt_idx != -1:
183-
bt_line = content[bt_idx:content.find('\n', bt_idx)]
187+
bt_rest = content[bt_idx + len("Backtrace:"):]
184188
bt_pattern = re.compile(r'(0x[0-9a-fA-F]+):(0x[0-9a-fA-F]+)')
185-
for match in bt_pattern.finditer(bt_line):
189+
for match in bt_pattern.finditer(bt_rest):
190+
# Stop if we hit a line that doesn't look like backtrace data
191+
preceding = bt_rest[:match.start()]
192+
# Allow only whitespace/newlines between entries
193+
last_newline = preceding.rfind('\n')
194+
if last_newline != -1:
195+
line_before = preceding[last_newline + 1:match.start()].strip()
196+
if line_before and not bt_pattern.match(line_before):
197+
break
186198
pc = int(match.group(1), 16)
187199
sp = int(match.group(2), 16)
188200
backtraces.append((pc, sp))

0 commit comments

Comments
 (0)