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
|
||||
CROSS ?= xtensa-lx106-elf-
|
||||
|
||||
# Path to the filteroutput.py tool
|
||||
FILTEROUTPUT ?= $(ROOT)/utils/filteroutput.py
|
||||
|
||||
AR = $(CROSS)ar
|
||||
CC = $(CROSS)gcc
|
||||
CPP = $(CROSS)cpp
|
||||
|
@ -385,7 +388,7 @@ size: $(PROGRAM_OUT)
|
|||
$(Q) $(CROSS)size --format=sysv $(PROGRAM_OUT)
|
||||
|
||||
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
|
||||
# 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