Disables allowing the python argparse library from automatically shortening command line arguments, this prevents issues whereby a new command is added and code that wrongly uses the shortened command of an existing argument which is the same as the new command being added will silently change script behaviour. Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
132 lines
3.4 KiB
Python
Executable file
132 lines
3.4 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
#
|
|
# Copyright (c) 2020 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
import argparse
|
|
import logging
|
|
import os
|
|
import socket
|
|
import sys
|
|
|
|
from coredump_parser.log_parser import CoredumpLogFile
|
|
from coredump_parser.elf_parser import CoredumpElfFile
|
|
|
|
import gdbstubs
|
|
|
|
LOGGING_FORMAT = "[%(levelname)s][%(name)s] %(message)s"
|
|
|
|
# Only bind to local host
|
|
GDBSERVER_HOST = ""
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(allow_abbrev=False)
|
|
|
|
parser.add_argument("elffile", help="Zephyr ELF binary")
|
|
parser.add_argument("logfile", help="Coredump binary log file")
|
|
parser.add_argument("--debug", action="store_true",
|
|
help="Print extra debugging information")
|
|
parser.add_argument("--port", type=int, default=1234,
|
|
help="GDB server port")
|
|
parser.add_argument("-v", "--verbose", action="store_true",
|
|
help="Print more information")
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def main():
|
|
args = parse_args()
|
|
|
|
# Setup logging
|
|
logging.basicConfig(format=LOGGING_FORMAT)
|
|
|
|
# Setup logging for "parser"
|
|
logger = logging.getLogger("parser")
|
|
if args.debug:
|
|
logger.setLevel(logging.DEBUG)
|
|
elif args.verbose:
|
|
logger.setLevel(logging.INFO)
|
|
else:
|
|
logger.setLevel(logging.WARNING)
|
|
|
|
# Setup logging for follow code
|
|
logger = logging.getLogger("gdbserver")
|
|
if args.debug:
|
|
logger.setLevel(logging.DEBUG)
|
|
else:
|
|
# Use INFO as default since we need to let user
|
|
# know what is going on
|
|
logger.setLevel(logging.INFO)
|
|
|
|
# Setup logging for "gdbstub"
|
|
logger = logging.getLogger("gdbstub")
|
|
if args.debug:
|
|
logger.setLevel(logging.DEBUG)
|
|
elif args.verbose:
|
|
logger.setLevel(logging.INFO)
|
|
else:
|
|
logger.setLevel(logging.WARNING)
|
|
|
|
if not os.path.isfile(args.elffile):
|
|
logger.error(f"Cannot find file {args.elffile}, exiting...")
|
|
sys.exit(1)
|
|
|
|
if not os.path.isfile(args.logfile):
|
|
logger.error(f"Cannot find file {args.logfile}, exiting...")
|
|
sys.exit(1)
|
|
|
|
logger.info(f"Log file: {args.logfile}")
|
|
logger.info(f"ELF file: {args.elffile}")
|
|
|
|
# Parse the coredump binary log file
|
|
logf = CoredumpLogFile(args.logfile)
|
|
logf.open()
|
|
if not logf.parse():
|
|
logger.error("Cannot parse log file, exiting...")
|
|
logf.close()
|
|
sys.exit(1)
|
|
|
|
# Parse ELF file for code and read-only data
|
|
elff = CoredumpElfFile(args.elffile)
|
|
elff.open()
|
|
if not elff.parse():
|
|
logger.error("Cannot parse ELF file, exiting...")
|
|
elff.close()
|
|
logf.close()
|
|
sys.exit(1)
|
|
|
|
gdbstub = gdbstubs.get_gdbstub(logf, elff)
|
|
|
|
# Start a GDB server
|
|
gdbserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
# Reuse address so we don't have to wait for socket to be
|
|
# close before we can bind to the port again
|
|
gdbserver.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
|
|
gdbserver.bind((GDBSERVER_HOST, args.port))
|
|
gdbserver.listen(1)
|
|
|
|
logger.info(f"Waiting GDB connection on port {args.port}...")
|
|
|
|
conn, remote = gdbserver.accept()
|
|
|
|
if conn:
|
|
logger.info(f"Accepted GDB connection from {remote}")
|
|
|
|
gdbstub.run(conn)
|
|
|
|
conn.close()
|
|
|
|
gdbserver.close()
|
|
|
|
logger.info("GDB session finished.")
|
|
|
|
elff.close()
|
|
logf.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|