rizin/test/scripts/gdbserver.py
2026-05-30 07:14:18 +08:00

71 lines
2.2 KiB
Python
Executable file

#!/usr/bin/env python3
r"""
This script launches gdbserver in a subprocess and waits until it's ready to receive
a new connection since it's not possible to know if gdbserver is ready to connect
to with `oodf` after executing it as a background task using `& !gdbserver ...`.
Example usage in a test:
!scripts/gdbserver.py --port PORT --binary bins/elf/analysis/calls_x64
It's important to note that PORT has to be unique for each test since all tests
run in parallel and may attempt to open the same port at the same time.
"""
import argparse
import os
import subprocess
def execute(cmd):
with subprocess.Popen(
cmd, stderr=subprocess.PIPE, universal_newlines=True
) as popen:
for stderr_line in iter(popen.stderr.readline, ""):
yield stderr_line
def main():
parser = argparse.ArgumentParser(
description="Run gdbserver in a new process with the given arguments and exit "
"once gdbserver is ready for new connections"
)
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", default="1234")
parser.add_argument("--binary", default="")
parser.add_argument(
"--output",
default=False,
action="store_true",
help="print stdout output from gdbserver",
)
parser.add_argument(
"--multi",
default=False,
action="store_true",
help="start gdbserver in multi-process (extended-remote) mode",
)
args = parser.parse_args()
while True:
cmd = ["gdbserver"]
if args.multi:
cmd.append("--multi") # --multi comes before HOST:PORT
cmd.append(f"{args.host}:{args.port}")
if args.binary:
cmd.append(args.binary)
for output in execute(cmd):
if args.output:
print(output)
# Exit once gdbserver is ready for connections
if "Listening on port" in output:
os._exit(0) # pylint: disable=protected-access
# gdbserver might fail to start if the port is taken
if "Can't bind address" in output:
print(output)
os._exit(1) # pylint: disable=protected-access
if __name__ == "__main__":
main()