106 lines
3.6 KiB
Python
Executable file
106 lines
3.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
#
|
|
# A thin Python wrapper around addr2line, can monitor esp-open-rtos
|
|
# output and uses gdb to convert any suitable looking hex numbers
|
|
# found in the output into function and line numbers.
|
|
#
|
|
# Works with a serial port if the --port option is supplied.
|
|
# Otherwise waits for input on stdin.
|
|
#
|
|
import serial
|
|
import argparse
|
|
import re
|
|
import os
|
|
import os.path
|
|
import subprocess
|
|
import termios
|
|
import sys
|
|
import time
|
|
|
|
# Try looking up anything in the executable address space
|
|
RE_EXECADDR = r"(0x)?40([0-9]|[a-z]){6}"
|
|
|
|
def find_elf_file():
|
|
out_files = []
|
|
for top,_,files in os.walk('.', followlinks=False):
|
|
for f in files:
|
|
if f.endswith(".out"):
|
|
out_files.append(os.path.join(top,f))
|
|
if len(out_files) == 1:
|
|
return out_files[0]
|
|
elif len(out_files) > 1:
|
|
print("Found multiple .out files: %s. Please specify one with the --elf option." % out_files)
|
|
else:
|
|
print("No .out file found under current directory. Please specify one with the --elf option.")
|
|
sys.exit(1)
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='esp-open-rtos output filter tool', prog='filteroutput')
|
|
parser.add_argument(
|
|
'--elf', '-e',
|
|
help="ELF file (*.out file) to load symbols from (if not supplied, will search for one)"),
|
|
parser.add_argument(
|
|
'--port', '-p',
|
|
help='Serial port to monitor (will monitor stdin if None)',
|
|
default=None)
|
|
parser.add_argument(
|
|
'--baud', '-b',
|
|
help='Baud rate for serial port',
|
|
type=int,
|
|
default=74880)
|
|
parser.add_argument(
|
|
'--reset-on-connect', '-r',
|
|
help='Reset ESP8266 (via DTR) on serial connect. (Linux resets even if not set, except when using NodeMCU-style auto-reset circuit.)',
|
|
action='store_true')
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.elf is None:
|
|
args.elf = find_elf_file()
|
|
elif not os.path.exists(args.elf):
|
|
print("ELF file '%s' not found" % args.elf)
|
|
sys.exit(1)
|
|
|
|
if args.port is not None:
|
|
print("Opening %s at %dbps..." % (args.port, args.baud))
|
|
port = serial.Serial(args.port, baudrate=args.baud)
|
|
if args.reset_on_connect:
|
|
print("Resetting...")
|
|
port.setDTR(False)
|
|
time.sleep(0.1)
|
|
port.setDTR(True)
|
|
|
|
else:
|
|
print("Reading from stdin...")
|
|
port = sys.stdin
|
|
# disable echo
|
|
try:
|
|
old_attr = termios.tcgetattr(sys.stdin.fileno())
|
|
attr = termios.tcgetattr(sys.stdin.fileno())
|
|
attr[3] = attr[3] & ~termios.ECHO
|
|
termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, attr)
|
|
except termios.error:
|
|
pass
|
|
|
|
try:
|
|
while True:
|
|
line = port.readline().decode('ISO-8859-1')
|
|
if line == '':
|
|
break
|
|
print(line.strip())
|
|
for match in re.finditer(RE_EXECADDR, line, re.IGNORECASE):
|
|
addr = match.group(0)
|
|
if not addr.startswith("0x"):
|
|
addr = "0x"+addr
|
|
# keeping addr2line and feeding it addresses on stdin didn't seem to work smoothly
|
|
addr2line = subprocess.check_output(["xtensa-lx106-elf-addr2line","-pfia","-e","%s" % args.elf, addr], cwd=".").strip()
|
|
pattern = ": ?? ??:0"
|
|
if not addr2line.endswith(pattern.encode()):
|
|
print("\n%s\n" % addr2line.strip())
|
|
finally:
|
|
if args.port is None:
|
|
# restore echo
|
|
termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, old_attr)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|