71 lines
2.2 KiB
Python
Executable file
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()
|