Add 'filteroutput.py' tool to automatically do addr2line lookups on likely hex values
This commit is contained in:
parent
f9fb0f212c
commit
b414e0b946
2 changed files with 109 additions and 1 deletions
|
@ -75,6 +75,9 @@ FLAVOR ?= release # or debug
|
||||||
# Compiler names, etc. assume gdb
|
# Compiler names, etc. assume gdb
|
||||||
CROSS ?= xtensa-lx106-elf-
|
CROSS ?= xtensa-lx106-elf-
|
||||||
|
|
||||||
|
# Path to the filteroutput.py tool
|
||||||
|
FILTEROUTPUT ?= $(ROOT)/utils/filteroutput.py
|
||||||
|
|
||||||
AR = $(CROSS)ar
|
AR = $(CROSS)ar
|
||||||
CC = $(CROSS)gcc
|
CC = $(CROSS)gcc
|
||||||
CPP = $(CROSS)cpp
|
CPP = $(CROSS)cpp
|
||||||
|
@ -385,7 +388,7 @@ size: $(PROGRAM_OUT)
|
||||||
$(Q) $(CROSS)size --format=sysv $(PROGRAM_OUT)
|
$(Q) $(CROSS)size --format=sysv $(PROGRAM_OUT)
|
||||||
|
|
||||||
test: flash
|
test: flash
|
||||||
screen $(ESPPORT) 115200
|
$(FILTEROUTPUT) --port $(ESPPORT) --baud 115200 --elf $(PROGRAM_OUT)
|
||||||
|
|
||||||
# the rebuild target is written like this so it can be run in a parallel build
|
# the rebuild target is written like this so it can be run in a parallel build
|
||||||
# environment without causing weird side effects
|
# environment without causing weird side effects
|
||||||
|
|
105
utils/filteroutput.py
Executable file
105
utils/filteroutput.py
Executable file
|
@ -0,0 +1,105 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# 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()
|
||||||
|
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()
|
||||||
|
if not addr2line.endswith(": ?? ??:0"):
|
||||||
|
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()
|
Loading…
Reference in a new issue