Created
December 28, 2019 01:02
-
-
Save sarfata/a06d8aaff7697a742f885ef774a7df1d to your computer and use it in GitHub Desktop.
A Python version of the esp32 exception decoder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import argparse | |
import re | |
import os | |
import subprocess | |
import sys | |
class ESP32CrashParser(object): | |
def __init__(self, toolchain_path, elf_path): | |
self.toolchain_path = toolchain_path | |
self.gdb_path = os.path.join(toolchain_path, "bin", "xtensa-esp32-elf-gdb") | |
self.addr2line_path = os.path.join(toolchain_path, "bin", "xtensa-esp32-elf-addr2line") | |
if not os.path.exists(self.gdb_path): | |
raise Exception("GDB for ESP not found in {} - {} does not exist.\nUse --toolchain to point to " | |
"your toolchain folder.".format(self.toolchain_path, self.gdb_path)) | |
if not os.path.exists(self.addr2line_path): | |
raise Exception("addr2line for ESP not found in {} - {} does not exist.\nUse --toolchain to point to " | |
"your toolchain folder.".format(self.toolchain_path, self.addr2line_path)) | |
self.elf_path = elf_path | |
if not os.path.exists(self.elf_path): | |
raise Exception("ELF file not found: '{}'".format(self.elf_path)) | |
def parse_text(self, text): | |
m = re.search('Backtrace: (.*)', text) | |
if m: | |
print "Stack trace:" | |
for l in self.parse_stack(m.group(1)): | |
print " " + l | |
else: | |
print "No stack trace found." | |
''' | |
Decode one stack or backtrace. | |
See: https://github.com/me-no-dev/EspExceptionDecoder/blob/master/src/EspExceptionDecoder.java#L402 | |
''' | |
def parse_stack(self, text): | |
r = re.compile('40[0-2][0-9a-fA-F]{5}') | |
m = r.findall(text) | |
return self.decode_function_addresses(m) | |
def decode_function_address(self, address): | |
args = [self.addr2line_path, "-e", self.elf_path, "-aipfC", address] | |
return subprocess.check_output(args).strip() | |
def decode_function_addresses(self, addresses): | |
out = [] | |
for a in addresses: | |
out.append(self.decode_function_address(a)) | |
return out | |
''' | |
GDB Should produce line number: https://github.com/me-no-dev/EspExceptionDecoder/commit/a78672da204151cc93979a96ed9f89139a73893f | |
However it does not produce anything for me. So not using it for now. | |
''' | |
def decode_function_addresses_with_gdb(self, addresses): | |
args = [self.gdb_path, "--batch"] | |
# Disable user config file which might interfere here | |
args.extend(["-iex", "set auto-load local-gdbinit off"]) | |
args.append(self.elf_path) | |
args.extend(["-ex", "set listsize 1"]) | |
for address in addresses: | |
args.append("-ex") | |
args.append("l *0x{}".format(address)) | |
args.extend(["-ex", "q"]) | |
print "Running: {}".format(args) | |
out = subprocess.check_output(args) | |
print out | |
def main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument("--toolchain", help="Path to the Xtensa toolchain", | |
default=os.path.join(os.environ.get("HOME"), ".platformio/packages/toolchain-xtensa32")) | |
parser.add_argument("--elf", help="Path to the ELF file of the firmware", | |
default=".pioenvs/kbox32/firmware.elf") | |
parser.add_argument("input", type=argparse.FileType('r'), default=sys.stdin) | |
args = parser.parse_args() | |
crash_parser = ESP32CrashParser(args.toolchain, args.elf) | |
crash_parser.parse_text(args.input.read()) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment