1#!/usr/bin/env python3 2# 3# Copyright (c) 2020 Intel Corporation 4# 5# SPDX-License-Identifier: Apache-2.0 6 7import argparse 8import logging 9import os 10import socket 11import sys 12 13from coredump_parser.log_parser import CoredumpLogFile 14from coredump_parser.elf_parser import CoredumpElfFile 15 16import gdbstubs 17 18LOGGING_FORMAT = "[%(levelname)s][%(name)s] %(message)s" 19 20# Only bind to local host 21GDBSERVER_HOST = "" 22 23 24def parse_args(): 25 parser = argparse.ArgumentParser(allow_abbrev=False) 26 27 parser.add_argument("elffile", help="Zephyr ELF binary") 28 parser.add_argument("logfile", help="Coredump binary log file") 29 parser.add_argument("--debug", action="store_true", 30 help="Print extra debugging information") 31 parser.add_argument("--port", type=int, default=1234, 32 help="GDB server port") 33 parser.add_argument("-v", "--verbose", action="store_true", 34 help="Print more information") 35 36 return parser.parse_args() 37 38 39def main(): 40 args = parse_args() 41 42 # Setup logging 43 logging.basicConfig(format=LOGGING_FORMAT) 44 45 # Setup logging for "parser" 46 logger = logging.getLogger("parser") 47 if args.debug: 48 logger.setLevel(logging.DEBUG) 49 elif args.verbose: 50 logger.setLevel(logging.INFO) 51 else: 52 logger.setLevel(logging.WARNING) 53 54 # Setup logging for follow code 55 logger = logging.getLogger("gdbserver") 56 if args.debug: 57 logger.setLevel(logging.DEBUG) 58 else: 59 # Use INFO as default since we need to let user 60 # know what is going on 61 logger.setLevel(logging.INFO) 62 63 # Setup logging for "gdbstub" 64 logger = logging.getLogger("gdbstub") 65 if args.debug: 66 logger.setLevel(logging.DEBUG) 67 elif args.verbose: 68 logger.setLevel(logging.INFO) 69 else: 70 logger.setLevel(logging.WARNING) 71 72 if not os.path.isfile(args.elffile): 73 logger.error(f"Cannot find file {args.elffile}, exiting...") 74 sys.exit(1) 75 76 if not os.path.isfile(args.logfile): 77 logger.error(f"Cannot find file {args.logfile}, exiting...") 78 sys.exit(1) 79 80 logger.info(f"Log file: {args.logfile}") 81 logger.info(f"ELF file: {args.elffile}") 82 83 # Parse the coredump binary log file 84 logf = CoredumpLogFile(args.logfile) 85 logf.open() 86 if not logf.parse(): 87 logger.error("Cannot parse log file, exiting...") 88 logf.close() 89 sys.exit(1) 90 91 # Parse ELF file for code and read-only data 92 elff = CoredumpElfFile(args.elffile) 93 elff.open() 94 if not elff.parse(): 95 logger.error("Cannot parse ELF file, exiting...") 96 elff.close() 97 logf.close() 98 sys.exit(1) 99 100 gdbstub = gdbstubs.get_gdbstub(logf, elff) 101 102 # Start a GDB server 103 gdbserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 104 105 # Reuse address so we don't have to wait for socket to be 106 # close before we can bind to the port again 107 gdbserver.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 108 109 gdbserver.bind((GDBSERVER_HOST, args.port)) 110 gdbserver.listen(1) 111 112 logger.info(f"Waiting GDB connection on port {args.port}...") 113 114 conn, remote = gdbserver.accept() 115 116 if conn: 117 logger.info(f"Accepted GDB connection from {remote}") 118 119 gdbstub.run(conn) 120 121 conn.close() 122 123 gdbserver.close() 124 125 logger.info("GDB session finished.") 126 127 elff.close() 128 logf.close() 129 130 131if __name__ == "__main__": 132 main() 133