From bcf98eac370f6188e16580af0e6694b9107e43fb Mon Sep 17 00:00:00 2001 From: Kevin ORourke Date: Wed, 28 Feb 2024 14:30:03 +0100 Subject: [PATCH] scripts: coredump: coredump_gdbserver in pipeline Add support to coredump_gdbserver.py for running in a pipeline, communicating through stdin/stdout instead of a socket. This allows starting it from inside gdb, with: target remote | coredump_gdbserver.py --pipe Signed-off-by: Kevin ORourke --- doc/services/debugging/coredump.rst | 22 +++++++++++++- scripts/coredump/coredump_gdbserver.py | 41 ++++++++++++++++++++------ 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/doc/services/debugging/coredump.rst b/doc/services/debugging/coredump.rst index ed7bb34f51ee..ed3e233d3b35 100644 --- a/doc/services/debugging/coredump.rst +++ b/doc/services/debugging/coredump.rst @@ -55,7 +55,8 @@ This usually involves the following steps: 3. Start the custom GDB server using the script :zephyr_file:`scripts/coredump/coredump_gdbserver.py` with the core dump - binary log file, and the Zephyr ELF file as parameters. + binary log file, and the Zephyr ELF file as parameters. The GDB server + can also be started from within GDB, see below. 4. Start the debugger corresponding to the target architecture. @@ -220,6 +221,25 @@ in :file:`coredump.log`: #2 0x00100492 in func_1 (addr=0x0) at zephyr/rtos/zephyr/samples/hello_world/src/main.c:28 #3 0x001004c8 in main () at zephyr/rtos/zephyr/samples/hello_world/src/main.c:42 +Starting the GDB server from within GDB +--------------------------------------- + +You can use ``target remote |`` to start the custom GDB server from inside +GDB, instead of in a separate shell. + +1. Start GDB: + + .. code-block:: console + + /x86_64-zephyr-elf/bin/x86_64-zephyr-elf-gdb build/zephyr/zephyr.elf + +2. Inside GDB, start the GDB server using the ``--pipe`` option: + + .. code-block:: console + + (gdb) target remote | ./scripts/coredump/coredump_gdbserver.py --pipe build/zephyr/zephyr.elf coredump.bin + + File Format *********** diff --git a/scripts/coredump/coredump_gdbserver.py b/scripts/coredump/coredump_gdbserver.py index f53e71b73621..3ffe3d9cfb92 100755 --- a/scripts/coredump/coredump_gdbserver.py +++ b/scripts/coredump/coredump_gdbserver.py @@ -21,6 +21,23 @@ GDBSERVER_HOST = "" +class FakeSocket: + def __init__(self) -> None: + self.in_stream = sys.stdin.buffer + self.out_stream = sys.stdout.buffer + + def recv(self, bufsize): + return self.in_stream.read(bufsize) + + def send(self, data): + n = self.out_stream.write(data) + self.out_stream.flush() + return n + + def close(self): + pass + + def parse_args(): parser = argparse.ArgumentParser(allow_abbrev=False) @@ -30,6 +47,8 @@ def parse_args(): help="Print extra debugging information") parser.add_argument("--port", type=int, default=1234, help="GDB server port") + parser.add_argument("--pipe", action="store_true", + help="Use stdio to communicate with gdb") parser.add_argument("-v", "--verbose", action="store_true", help="Print more information") @@ -99,19 +118,23 @@ def main(): gdbstub = gdbstubs.get_gdbstub(logf, elff) - # Start a GDB server - gdbserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if not args.pipe: + # 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) + # 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) + gdbserver.bind((GDBSERVER_HOST, args.port)) + gdbserver.listen(1) - logger.info(f"Waiting GDB connection on port {args.port}...") + logger.info(f"Waiting GDB connection on port {args.port}...") - conn, remote = gdbserver.accept() + conn, remote = gdbserver.accept() + else: + conn = FakeSocket() + remote = "pipe" if conn: logger.info(f"Accepted GDB connection from {remote}")