]> git.proxmox.com Git - mirror_qemu.git/blob - tests/guest-debug/run-test.py
Merge tag 'qga-pull-2024-01-30' of https://github.com/kostyanf14/qemu into staging
[mirror_qemu.git] / tests / guest-debug / run-test.py
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 parser.add_argument("--gdb", help="The gdb binary to use",
31 default=None)
32 parser.add_argument("--gdb-args", help="Additional gdb arguments")
33 parser.add_argument("--output", help="A file to redirect output to")
34 parser.add_argument("--stderr", help="A file to redirect stderr to")
35
36 return parser.parse_args()
37
38
39 def log(output, msg):
40 if output:
41 output.write(msg + "\n")
42 output.flush()
43 else:
44 print(msg)
45
46
47 if __name__ == '__main__':
48 args = get_args()
49
50 # Search for a gdb we can use
51 if not args.gdb:
52 args.gdb = shutil.which("gdb-multiarch")
53 if not args.gdb:
54 args.gdb = shutil.which("gdb")
55 if not args.gdb:
56 print("We need gdb to run the test")
57 exit(-1)
58 if args.output:
59 output = open(args.output, "w")
60 else:
61 output = None
62 if args.stderr:
63 stderr = open(args.stderr, "w")
64 else:
65 stderr = None
66
67 socket_dir = TemporaryDirectory("qemu-gdbstub")
68 socket_name = os.path.join(socket_dir.name, "gdbstub.socket")
69
70 # Launch QEMU with binary
71 if "system" in args.qemu:
72 cmd = f'{args.qemu} {args.qargs} {args.binary}' \
73 f' -S -gdb unix:path={socket_name},server=on'
74 else:
75 cmd = f'{args.qemu} {args.qargs} -g {socket_name} {args.binary}'
76
77 log(output, "QEMU CMD: %s" % (cmd))
78 inferior = subprocess.Popen(shlex.split(cmd))
79
80 # Now launch gdb with our test and collect the result
81 gdb_cmd = "%s %s" % (args.gdb, args.binary)
82 if args.gdb_args:
83 gdb_cmd += " %s" % (args.gdb_args)
84 # run quietly and ignore .gdbinit
85 gdb_cmd += " -q -n -batch"
86 # disable pagination
87 gdb_cmd += " -ex 'set pagination off'"
88 # disable prompts in case of crash
89 gdb_cmd += " -ex 'set confirm off'"
90 # connect to remote
91 gdb_cmd += " -ex 'target remote %s'" % (socket_name)
92 # finally the test script itself
93 if args.test:
94 gdb_cmd += " -x %s" % (args.test)
95
96
97 sleep(1)
98 log(output, "GDB CMD: %s" % (gdb_cmd))
99
100 gdb_env = dict(os.environ)
101 gdb_pythonpath = gdb_env.get("PYTHONPATH", "").split(os.pathsep)
102 gdb_pythonpath.append(os.path.dirname(os.path.realpath(__file__)))
103 gdb_env["PYTHONPATH"] = os.pathsep.join(gdb_pythonpath)
104 result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr,
105 env=gdb_env)
106
107 # A result of greater than 128 indicates a fatal signal (likely a
108 # crash due to gdb internal failure). That's a problem for GDB and
109 # not the test so we force a return of 0 so we don't fail the test on
110 # account of broken external tools.
111 if result > 128:
112 log(output, "GDB crashed? (%d, %d) SKIPPING" % (result, result - 128))
113 exit(0)
114
115 try:
116 inferior.wait(2)
117 except subprocess.TimeoutExpired:
118 log(output, "GDB never connected? Killed guest")
119 inferior.kill()
120
121 exit(result)