run-test.py (3368B)
1 #!/usr/bin/env python3 2 # 3 # Run a gdbstub test case 4 # 5 # Copyright (c) 2019 Linaro 6 # 7 # Author: Alex Bennée <alex.bennee@linaro.org> 8 # 9 # This work is licensed under the terms of the GNU GPL, version 2 or later. 10 # See the COPYING file in the top-level directory. 11 # 12 # SPDX-License-Identifier: GPL-2.0-or-later 13 14 import argparse 15 import subprocess 16 import shutil 17 import shlex 18 import os 19 from time import sleep 20 from tempfile import TemporaryDirectory 21 22 def get_args(): 23 parser = argparse.ArgumentParser(description="A gdbstub test runner") 24 parser.add_argument("--qemu", help="Qemu binary for test", 25 required=True) 26 parser.add_argument("--qargs", help="Qemu arguments for test") 27 parser.add_argument("--binary", help="Binary to debug", 28 required=True) 29 parser.add_argument("--test", help="GDB test script", 30 required=True) 31 parser.add_argument("--gdb", help="The gdb binary to use", 32 default=None) 33 parser.add_argument("--output", help="A file to redirect output to") 34 35 return parser.parse_args() 36 37 38 def log(output, msg): 39 if output: 40 output.write(msg + "\n") 41 output.flush() 42 else: 43 print(msg) 44 45 46 if __name__ == '__main__': 47 args = get_args() 48 49 # Search for a gdb we can use 50 if not args.gdb: 51 args.gdb = shutil.which("gdb-multiarch") 52 if not args.gdb: 53 args.gdb = shutil.which("gdb") 54 if not args.gdb: 55 print("We need gdb to run the test") 56 exit(-1) 57 if args.output: 58 output = open(args.output, "w") 59 else: 60 output = None 61 62 socket_dir = TemporaryDirectory("qemu-gdbstub") 63 socket_name = os.path.join(socket_dir.name, "gdbstub.socket") 64 65 # Launch QEMU with binary 66 if "system" in args.qemu: 67 cmd = "%s %s %s -gdb unix:path=%s,server=on" % (args.qemu, 68 args.qargs, 69 args.binary, 70 socket_name) 71 else: 72 cmd = "%s %s -g %s %s" % (args.qemu, args.qargs, socket_name, 73 args.binary) 74 75 log(output, "QEMU CMD: %s" % (cmd)) 76 inferior = subprocess.Popen(shlex.split(cmd)) 77 78 # Now launch gdb with our test and collect the result 79 gdb_cmd = "%s %s" % (args.gdb, args.binary) 80 # run quietly and ignore .gdbinit 81 gdb_cmd += " -q -n -batch" 82 # disable prompts in case of crash 83 gdb_cmd += " -ex 'set confirm off'" 84 # connect to remote 85 gdb_cmd += " -ex 'target remote %s'" % (socket_name) 86 # finally the test script itself 87 gdb_cmd += " -x %s" % (args.test) 88 89 90 sleep(1) 91 log(output, "GDB CMD: %s" % (gdb_cmd)) 92 93 result = subprocess.call(gdb_cmd, shell=True, stdout=output) 94 95 # A result of greater than 128 indicates a fatal signal (likely a 96 # crash due to gdb internal failure). That's a problem for GDB and 97 # not the test so we force a return of 0 so we don't fail the test on 98 # account of broken external tools. 99 if result > 128: 100 log(output, "GDB crashed? (%d, %d) SKIPPING" % (result, result - 128)) 101 exit(0) 102 103 try: 104 inferior.wait(2) 105 except subprocess.TimeoutExpired: 106 log(output, "GDB never connected? Killed guest") 107 inferior.kill() 108 109 exit(result)