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 <elf_file>  <log_file>

Signed-off-by: Kevin ORourke <kevin.orourke@ferroamp.se>
This commit is contained in:
Kevin ORourke 2024-02-28 14:30:03 +01:00 committed by Anas Nashif
parent 7058c2283f
commit 98aa10d6ea
2 changed files with 53 additions and 10 deletions

View file

@ -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
<path to SDK>/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
***********

View file

@ -21,6 +21,23 @@ LOGGING_FORMAT = "[%(levelname)s][%(name)s] %(message)s"
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}")