Skip to content

Commit d002ce5

Browse files
authored
[runtimes] Add a qemu-system executor script (#68643)
This is useful when trying to test libc++/libc++abi/libunwind against a baremetal enviroment (e.g. picolibc). See also https://reviews.llvm.org/D155521
1 parent acd7b77 commit d002ce5

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

libcxx/utils/qemu_baremetal.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env python3
2+
# ===----------------------------------------------------------------------===##
3+
#
4+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
# See https://llvm.org/LICENSE.txt for license information.
6+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
#
8+
# ===----------------------------------------------------------------------===##
9+
10+
"""qemu_baremetal.py is a utility for running a program with QEMU's system mode.
11+
12+
It is able to pass command line arguments to the program and forward input and
13+
output (if the underlying baremetal enviroment supports QEMU semihosting).
14+
"""
15+
16+
import argparse
17+
import os
18+
import platform
19+
import subprocess
20+
import sys
21+
22+
23+
def main():
24+
parser = argparse.ArgumentParser()
25+
parser.add_argument("--qemu", type=str, required=True)
26+
parser.add_argument("--cpu", type=str, required=False)
27+
parser.add_argument("--machine", type=str, default="virt")
28+
parser.add_argument(
29+
"--qemu-arg", dest="qemu_args", type=str, action="append", default=[]
30+
)
31+
parser.add_argument("--semihosting", action="store_true", default=True)
32+
parser.add_argument("--no-semihosting", dest="semihosting", action="store_false")
33+
parser.add_argument("--execdir", type=str, required=True)
34+
parser.add_argument("test_binary")
35+
parser.add_argument("test_args", nargs=argparse.ZERO_OR_MORE, default=[])
36+
args = parser.parse_args()
37+
if not os.path.exists(args.test_binary):
38+
sys.exit(f"Expected argument to be a test executable: '{args.test_binary}'")
39+
qemu_commandline = [
40+
args.qemu,
41+
"-chardev",
42+
"stdio,mux=on,id=stdio0",
43+
"-monitor",
44+
"none",
45+
"-serial",
46+
"none",
47+
"-machine",
48+
f"{args.machine},accel=tcg",
49+
"-device",
50+
f"loader,file={args.test_binary},cpu-num=0",
51+
"-nographic",
52+
*args.qemu_args,
53+
]
54+
if args.cpu:
55+
qemu_commandline += ["-cpu", args.cpu]
56+
57+
if args.semihosting:
58+
# Use QEMU's semihosting support to pass argv (supported by picolibc)
59+
semihosting_config = f"enable=on,chardev=stdio0,arg={args.test_binary}"
60+
for arg in args.test_args:
61+
semihosting_config += f",arg={arg}"
62+
qemu_commandline += ["-semihosting-config", semihosting_config]
63+
elif args.test_args:
64+
sys.exit(
65+
"Got non-empty test arguments but do no know how to pass them to "
66+
"QEMU without semihosting support"
67+
)
68+
os.execvp(qemu_commandline[0], qemu_commandline)
69+
70+
71+
if __name__ == "__main__":
72+
exit(main())

0 commit comments

Comments
 (0)