qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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)