Merge tag 'pull-11.2-gdbstub-kvm-231026-1' of https://gitlab.com/stsquad/qemu into staging

testing updates (tcg, gdbstub):

  - make sure we have TCG to run test_acpi_bits
  - fix overflow in linux-sigrtminmax
  - make .dir-locals aware of PYTHONPATH
  - detect gdb in top-level meson
  - fetch kernel assets with symbols for x86, aarch64 and s390 tuxruns
  - use arrays in gdb run-test to make quoting less messy
  - add support for --symbols and --kargs to gdbstub run-test.py
  - restore old kvm gdb test script with a few fixes
  - add tuxrun_kvm_gdb tests for x86,aarch64 and s390

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmrbjRYACgkQ+9DbCVqe
# KkTtGwf/eDJawSsUD6rDYuNEegv5buJVlE5Vkh8EUUSbrr56xstPlclLXZQbXZKN
# gGxw7RGpoZZMUN/RGRbV001E6HhsUhWjkSDFGOH21MkQUj9OPVlroPhFPo+m0Xvb
# ppXSRvK09tXlM7YKFS8GWOT5sYzsHl/b5nbI2UONlLDmLl0futFlVeTMQ/qptR7t
# EKzsi86O6iEb69TuFlypZnIf++NsXYhcgSf/3pWGzLDBcstM+PDqHQn5Y+TTZUS3
# S56sCr6ihLNPRZl3ynkQvFArln3lO8I/K6RlOssRtUZ9QKV0oQ2aZDvMIqBytxBe
# sfBhrL/KrLgL8Uw4S8sQELXR8we+Bg==
# =u32E
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 23 Oct 2026 06:36:38 PM CEST
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* tag 'pull-11.2-gdbstub-kvm-231026-1' of https://gitlab.com/stsquad/qemu:
  tests/functional: add tuxrun kvm gdb test for s390x
  tests/functional: update s390x tuxrun images
  tests/functional: split s390x tuxrun into tcg and kvm run
  tests/functional: add tuxrun kvm gdb test for arm64
  tests/functional: update arm64 tuxrun images
  tests/functional: split aarch64 tuxrun into tcg and kvm run
  tests/functional: add tuxrun kvm gdb test for x86_64
  tests/functional: teach tuxrun about launching gdb tests
  tests/guest-debug: add --symbols option to run-test
  tests/guest-debug: add --kargs option to run-test
  tests/guest-debug: convert cmd to an qemu_cmd array
  tests/guest-debug: convert gdb_cmd to an array
  tests/functional: update x86_64 tuxrun images
  tests/functional: split x86_64 tuxrun into tcg and kvm run
  tests/functional: allow tuxrun tests to be passed "accel"
  meson: move gdb detection into the top level build file
  .dir-locals: include QEMU code in PYTHONPATH
  tests/tcg: fix buffer overflow in multiarch/linux/linux-sigrtminmax
  tests/functional: test_acpi_bits requires TCG

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson committed 2026-10-24 16:08:38 +02:00
commit 594bf10d18
13 files changed
+444 -74

No files matched your search

+7 -1
View File
@@ -1,2 +1,8 @@
((c-mode . ((c-file-style . "stroustrup")
(indent-tabs-mode . nil))))
(indent-tabs-mode . nil)))
(python-mode .
((eval . (when-let* ((root (locate-dominating-file default-directory ".dir-locals.el")))
(setq-local process-environment (copy-sequence process-environment))
(setenv "PYTHONPATH"
(concat (expand-file-name "python" root) ":"
(expand-file-name "tests/functional" root))))))))
+7 -8
View File
@@ -163,6 +163,12 @@ else
iasl = find_program(get_option('iasl'), required: true)
endif
if get_option('gdb') == ''
gdb = find_program(['gdb-multiarch', 'gdb'], required: false)
else
gdb = find_program(get_option('gdb'), required: true)
endif
edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu', 'riscv64-softmmu', 'loongarch64-softmmu' ]
unpack_edk2_blobs = false
foreach target : edk2_targets
@@ -4710,14 +4716,7 @@ summary(summary_info, bool_yn: true, section: 'Directories')
summary_info = {}
summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
summary_info += {'sphinx-build': sphinx_build}
# FIXME: the [binaries] section of machine files, which can be probed
# with find_program(), would be great for passing gdb and genisoimage
# paths from configure to Meson. However, there seems to be no way to
# hide a program (for example if gdb is too old).
if config_host.has_key('GDB')
summary_info += {'gdb': config_host['GDB']}
endif
summary_info += {'gdb': gdb}
summary_info += {'iasl': iasl}
summary_info += {'genisoimage': config_host['GENISOIMAGE']}
if host_os == 'windows' and have_ga
+30 -5
View File
@@ -11,17 +11,20 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset
from qemu_test import Asset, skipIfMissingEnv
from qemu_test.tuxruntest import TuxRunBaselineTest
class TuxRunAarch64Test(TuxRunBaselineTest):
ASSET_ARM64_KERNEL = Asset(
'https://storage.tuxboot.com/buildroot/20241119/arm64/Image',
'b74743c5e89e1cea0f73368d24ae0ae85c5204ff84be3b5e9610417417d2f235')
'https://storage.tuxboot.com/kernels/6.18.54/arm64/Image.gz',
'39f4633bbcb444267d4d829bd28d8868a287c4c160cda64b0fd23fb090571c4e')
ASSET_ARM64_VMLINUX = Asset(
'https://storage.tuxboot.com/kernels/6.18.54/arm64/vmlinux.xz',
'6487eb113ef6e841aedab6cb6fa704006377d68f64dd544570aa42f462a52b85')
ASSET_ARM64_ROOTFS = Asset(
'https://storage.tuxboot.com/buildroot/20241119/arm64/rootfs.ext4.zst',
'a1acaaae2068df4648d04ff75f532aaa8c5edcd6b936122b6f0db4848a07b465')
'https://storage.tuxboot.com/buildroot/20260924/arm64/rootfs.ext4.zst',
'4ab8cec9d1e17dbb1abdf2ae1939ad4f9d0dc2466230f6a119a7c1845cdef0b1')
def test_arm64(self):
self.set_machine('virt')
@@ -32,6 +35,28 @@ class TuxRunAarch64Test(TuxRunBaselineTest):
self.common_tuxrun(kernel_asset=self.ASSET_ARM64_KERNEL,
rootfs_asset=self.ASSET_ARM64_ROOTFS)
def test_arm64_kvm(self):
self.set_machine('virt')
self.require_accelerator('kvm')
self.cpu='host'
self.console='ttyAMA0'
self.wait_for_shutdown=False
self.common_tuxrun(kernel_asset=self.ASSET_ARM64_KERNEL,
rootfs_asset=self.ASSET_ARM64_ROOTFS,
accel="kvm")
@skipIfMissingEnv("QEMU_TEST_GDB")
def test_arm64_kvm_gdb(self):
self.set_machine('virt')
self.require_accelerator('kvm')
self.cpu='host'
self.console='ttyAMA0'
self.wait_for_shutdown=False
self.common_tuxrun_gdb(kernel_asset=self.ASSET_ARM64_KERNEL,
vmlinux_asset=self.ASSET_ARM64_VMLINUX,
rootfs_asset=self.ASSET_ARM64_ROOTFS,
accel="kvm")
ASSET_ARM64BE_KERNEL = Asset(
'https://storage.tuxboot.com/buildroot/20241119/arm64be/Image',
'fd6af4f16689d17a2c24fe0053cc212edcdf77abdcaf301800b8d38fa9f6e109')
@@ -0,0 +1,164 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Generic Kernel GDB script to verify functionality:
# - Single-stepping
# - Hardware breakpoints
# - Software breakpoints
# - Watchpoints
#
# It relies on fairly common kernel points to break at and symbols for
# the kernel. Address space randomisation (kaslr) needs to be disabled.
#
# Copyright (c) 2026 Linaro Limited
#
# Author:
# Alex Bennée <alex.bennee@linaro.org>
#
# This is launched by the tuxrun functional tests via tests/guest-debug/run-test.py
import gdb
from test_gdbstub import main, report
def parse_registers():
"""Parse 'info registers' into a name -> value dictionary."""
regs = {}
for line in gdb.execute("info registers", to_string=True).splitlines():
parts = line.split()
if len(parts) >= 2:
regs[parts[0]] = parts[1]
return regs
def check_step():
"Step an instruction, check it moved."
start_pc = gdb.parse_and_eval('$pc')
gdb.execute("si")
end_pc = gdb.parse_and_eval('$pc')
return not (start_pc == end_pc)
def check_reg_updates(regs_start):
regs_end = parse_registers()
changed = [k for k in regs_start
if k in regs_end and regs_start[k] != regs_end[k]]
report(len(changed) > 0, f"{len(changed)} registers changed.")
def check_break(sym_name):
"Setup breakpoint, continue and check we stopped."
bp = gdb.Breakpoint(sym_name)
gdb.execute("c")
res = bp.hit_count == 1
bp.delete()
return res
def check_hbreak(sym_name):
"Setup hardware breakpoint, continue and check we stopped."
bp = gdb.Breakpoint(sym_name, type = gdb.BP_HARDWARE_BREAKPOINT)
gdb.execute("c")
res = bp.hit_count == 1
bp.delete()
return res
class WatchPoint(gdb.Breakpoint):
def __init__(self, sym_name, type):
super(WatchPoint, self).__init__(sym_name, gdb.BP_WATCHPOINT, type)
def stop(self):
end_pc = gdb.parse_and_eval('$pc')
print("HIT WP @ %s" % (end_pc))
return True
def do_one_watch(sym, wtype, text):
wp = WatchPoint(sym, wtype)
gdb.execute("c")
report_str = "%s for %s" % (text, sym)
if wp.hit_count > 0:
report(True, report_str)
else:
report(False, report_str)
wp.delete()
def check_watches(sym_name):
"Watch a symbol for any access."
# s390 only supports write watchpoints
if "s390" not in gdb.selected_frame().architecture().name():
# Should hit for any read
do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
# Again should hit for reads
do_one_watch(sym_name, gdb.WP_READ, "rwatch")
# Finally when it is written
do_one_watch(sym_name, gdb.WP_WRITE, "watch")
class CatchBreakpoint(gdb.Breakpoint):
def __init__(self, sym_name):
super(CatchBreakpoint, self).__init__(sym_name, type = gdb.BP_BREAKPOINT)
self.sym, ok = gdb.lookup_symbol(sym_name)
def stop(self):
end_pc = gdb.parse_and_eval('$pc')
print("CB: %s == %s" % (end_pc, self.sym.value()))
if end_pc == self.sym.value():
report(False, "Hit final catchpoint")
def run_test():
"Run through the tests one by one"
# get the initial register state
regs_start = parse_registers()
print("Checking we can step the first few instructions")
step_ok = 0
for i in range(3):
if check_step():
step_ok += 1
report(step_ok == 3, "single step in boot code")
# check some registers changed
print("Checking register access works")
check_reg_updates(regs_start)
print("Checking HW breakpoint works")
break_ok = check_hbreak("kernel_init")
report(break_ok, "hbreak @ kernel_init")
# Can't set this up until we are in the kernel proper
# if we make it to run_init_process we've over-run and
# one of the tests failed
print("Setup catch-all for run_init_process")
cbp = CatchBreakpoint("run_init_process")
# We should see wait_for_completion called right at the start of
# kernel_init
print("Checking Normal breakpoint works")
break_ok = check_break("wait_for_completion")
report(break_ok, "break @ wait_for_completion")
print("Checking watchpoint works")
check_watches("system_state")
# check we didn't hit the end
report(cbp.hit_count == 0, "CatchBreakpoint not hit")
main(run_test)
+2 -3
View File
@@ -83,9 +83,8 @@ foreach speed : ['quick', 'thorough']
separator : ':')
# Define the GDB environment variable if gdb is available.
gdb = get_option('gdb')
if gdb != ''
test_env.set('QEMU_TEST_GDB', gdb)
if gdb.found()
test_env.set('QEMU_TEST_GDB', gdb.full_path())
endif
foreach test : target_tests
+98 -10
View File
@@ -9,7 +9,10 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
import logging
import os
import shlex
import subprocess
from qemu_test import QemuSystemTest
from qemu_test import exec_command_and_wait_for_pattern
@@ -18,7 +21,8 @@ from qemu_test import which, get_qemu_img
class TuxRunBaselineTest(QemuSystemTest):
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0'
# nokaslr is needed for gdb tests but it makes things simpler anyway
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 nokaslr'
# Tests are ~10-40s, allow for --debug/--enable-gcov overhead
timeout = 100
@@ -55,17 +59,20 @@ class TuxRunBaselineTest(QemuSystemTest):
failure_message='Kernel panic - not syncing',
vm=vm)
def fetch_tuxrun_assets(self, kernel_asset, rootfs_asset, dtb_asset=None):
def fetch_tuxrun_assets(self, kernel_asset, rootfs_asset,
dtb_asset=None, vmlinux_asset=None):
"""
Fetch the TuxBoot assets.
"""
kernel_image = kernel_asset.fetch()
disk_image = self.uncompress(rootfs_asset)
dtb = dtb_asset.fetch() if dtb_asset is not None else None
vmlinux = self.uncompress(vmlinux_asset) if vmlinux_asset is not None else None
return (kernel_image, disk_image, dtb)
return (kernel_image, disk_image, dtb, vmlinux)
def prepare_run(self, kernel, disk, drive, dtb=None, console_index=0):
def prepare_run(self, accel, kernel, disk, drive,
dtb=None, console_index=0, append = True):
"""
Setup to run and add the common parameters to the system
"""
@@ -79,9 +86,19 @@ class TuxRunBaselineTest(QemuSystemTest):
self.kcmd_line += f" root=/dev/{self.root}"
self.kcmd_line += f" console={self.console}"
self.vm.add_args('-kernel', kernel,
'-append', self.kcmd_line,
'-blockdev', blockdev)
# have we specified an accelerator?
if accel:
self.vm.add_args('-accel', accel)
if kernel:
self.vm.add_args('-kernel', kernel)
# When using the gdb run script we might not want to include
# the kcmd line directly in the QEMU args.
if append:
self.vm.add_args('-append', self.kcmd_line)
self.vm.add_args('-blockdev', blockdev)
# Sometimes we need extra devices attached
if self.extradev:
@@ -118,6 +135,7 @@ class TuxRunBaselineTest(QemuSystemTest):
def common_tuxrun(self,
kernel_asset,
rootfs_asset,
accel=None,
dtb_asset=None,
drive="virtio-blk-device",
haltmsg="reboot: System halted",
@@ -127,10 +145,80 @@ class TuxRunBaselineTest(QemuSystemTest):
special with the command line we can process most things using
the tag metadata.
"""
(kernel, disk, dtb) = self.fetch_tuxrun_assets(kernel_asset, rootfs_asset,
dtb_asset)
(kernel, disk, dtb, _) = self.fetch_tuxrun_assets(kernel_asset,
rootfs_asset,
dtb_asset)
self.prepare_run(kernel, disk, drive, dtb, console_index)
self.prepare_run(accel, kernel, disk, drive, dtb, console_index)
self.vm.launch()
self.run_tuxtest_tests(haltmsg)
os.remove(disk)
def common_tuxrun_gdb(self,
kernel_asset,
vmlinux_asset,
rootfs_asset,
accel=None,
dtb_asset=None,
symbol_off = None,
drive="virtio-blk-device",
console_index=0):
"""
Common path for LKFT tests under gdb. Unlike the common_tuxrun
function we need to launch with the gdb test script and deal
with munging the arguments for that especially.
"""
(kernel, disk, dtb, vmlinux) = self.fetch_tuxrun_assets(kernel_asset,
rootfs_asset,
dtb_asset,
vmlinux_asset)
gdb_path = os.getenv("QEMU_TEST_GDB")
run_script = self.data_file('..', 'guest-debug','run-test.py')
test_script = self.data_file('gdb-scripts', 'kernel_gdb_test.py')
# Instead of launching QEMU via the functional test machinery
# we need to launch it with the gdb run script. We utilise the
# existing prepare_run machinery to build the command line but
# we pass the kernel args separately to avoid horrible string
# escaping.
self.prepare_run(accel, kernel, disk, drive, dtb,
console_index, append = False)
# the functional test machinery adds more stuff for handling
# console redirection which we need to do manually.
qargs = self.vm.args
qargs.extend(["-display", "none", "-serial", "stdio"])
# and the machine type
if self.vm._machine is not None:
qargs.extend(["-machine", self.vm._machine])
cmd = [
str(run_script),
"--qemu", self.qemu_bin,
"--qargs", shlex.join(qargs),
"--kargs", self.kcmd_line,
"--symbols", str(vmlinux),
"--test", str(test_script),
"--gdb", gdb_path,
]
if symbol_off is not None:
cmd.extend(["--symbol-offset", f"{symbol_off}"])
log_cmd = " ".join(f'"{arg}"' if ' ' in arg else arg for arg in cmd)
self.log.info(f"run-test: {log_cmd}")
res = subprocess.run(cmd, text=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
if res.stdout:
console_logger = logging.getLogger('console')
console_logger.info(res.stdout)
self.assertEqual(res.returncode, 0,
f"run-test.py failed ({res.returncode}):\n")
+32 -5
View File
@@ -11,25 +11,52 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset
from qemu_test import Asset, skipIfMissingEnv
from qemu_test.tuxruntest import TuxRunBaselineTest
class TuxRunS390xTest(TuxRunBaselineTest):
ASSET_S390X_KERNEL = Asset(
'https://storage.tuxboot.com/buildroot/20241119/s390/bzImage',
'ee67e91db52a2aed104a7c72b2a08987c678f8179c029626789c35d6dd0fedf1')
'https://storage.tuxboot.com/kernels/6.18.54/s390/bzImage',
'5efeb31754b211440e1595ab11355bb006fe78a2c0604ed0a8c55c4598b71aec')
ASSET_S390X_VMLINUX = Asset(
'https://storage.tuxboot.com/kernels/6.18.54/s390/vmlinux.xz',
'5bbd4d34e0950f88053a9bfd16078896df4b1ee1696fc2ad62488e681a6bdd8e')
ASSET_S390X_ROOTFS = Asset(
'https://storage.tuxboot.com/buildroot/20241119/s390/rootfs.ext4.zst',
'bff7971fc2fef56372d98afe4557b82fd0a785a241e44c29b058e577ad1bbb44')
'https://storage.tuxboot.com/buildroot/20260924/s390/rootfs.ext4.zst',
'5ba18c4d18831c50a0c743990f7bdee1d3b520629d423c55b668d8fbbac9c6f5')
def test_s390(self):
self.set_machine('s390-ccw-virtio')
self.require_accelerator('tcg')
self.wait_for_shutdown=False
self.common_tuxrun(kernel_asset=self.ASSET_S390X_KERNEL,
rootfs_asset=self.ASSET_S390X_ROOTFS,
drive="virtio-blk-ccw",
haltmsg="Requesting system halt")
def test_s390_kvm(self):
self.set_machine('s390-ccw-virtio')
self.require_accelerator('kvm')
self.wait_for_shutdown=False
self.common_tuxrun(kernel_asset=self.ASSET_S390X_KERNEL,
rootfs_asset=self.ASSET_S390X_ROOTFS,
drive="virtio-blk-ccw",
haltmsg="Requesting system halt",
accel="kvm")
@skipIfMissingEnv("QEMU_TEST_GDB")
def test_s390_kvm_gdb(self):
self.set_machine('s390-ccw-virtio')
self.require_accelerator('kvm')
self.wait_for_shutdown=False
self.common_tuxrun_gdb(kernel_asset=self.ASSET_S390X_KERNEL,
vmlinux_asset=self.ASSET_S390X_VMLINUX,
rootfs_asset=self.ASSET_S390X_ROOTFS,
symbol_off="0x3ffe0000000",
drive="virtio-blk-ccw",
haltmsg="Requesting system halt",
accel="kvm")
if __name__ == '__main__':
TuxRunBaselineTest.main()
+3 -3
View File
@@ -31,11 +31,11 @@ class TuxRunSh4Test(TuxRunBaselineTest):
# The test is currently too unstable to do much in userspace
# so we skip common_tuxrun and do a minimal boot and shutdown.
(kernel, disk, dtb) = self.fetch_tuxrun_assets(self.ASSET_SH4_KERNEL,
self.ASSET_SH4_ROOTFS)
(kernel, disk, dtb, _) = self.fetch_tuxrun_assets(self.ASSET_SH4_KERNEL,
self.ASSET_SH4_ROOTFS)
# the console comes on the second serial port
self.prepare_run(kernel, disk,
self.prepare_run(None, kernel, disk,
"driver=ide-hd,bus=ide.0,unit=0",
console_index=1)
self.vm.launch()
@@ -303,6 +303,9 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
"""The main test case implementation."""
self.set_machine('pc')
# see icount comment below
self.require_accelerator('tcg')
iso_file = self.scratch_file('bits-%d.iso' % self.BITS_INTERNAL_VER)
self.assertTrue(os.access(iso_file, os.R_OK))
+39 -6
View File
@@ -11,26 +11,59 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset
from qemu_test import Asset, skipIfMissingEnv
from qemu_test.tuxruntest import TuxRunBaselineTest
class TuxRunX86Test(TuxRunBaselineTest):
ASSET_X86_64_KERNEL = Asset(
'https://storage.tuxboot.com/buildroot/20241119/x86_64/bzImage',
'f57bfc6553bcd6e0a54aab86095bf642b33b5571d14e3af1731b18c87ed5aef8')
'https://storage.tuxboot.com/kernels/6.18.54/x86_64/bzImage',
'24a3ade610c2cc426ff821050de8a35930b0371357d94cc2c334abac6658552b')
ASSET_X86_64_VMLINUX = Asset(
'https://storage.tuxboot.com/kernels/6.18.54/x86_64/vmlinux.xz',
'77bf44cca48c9c1b9c142e16a2311d58b8ae3462b61bce44bcaf9243b5f26628')
ASSET_X86_64_ROOTFS = Asset(
'https://storage.tuxboot.com/buildroot/20241119/x86_64/rootfs.ext4.zst',
'4b8b2a99117519c5290e1202cb36eb6c7aaba92b357b5160f5970cf5fb78a751')
'https://storage.tuxboot.com/buildroot/20260924/x86_64/rootfs.ext4.zst',
'8e310455b0244414ccff29c507f7ccfd4032e3587cc405e49ab0322738e3e27c')
def test_x86_64(self):
self.require_accelerator("tcg")
self.set_machine('q35')
self.cpu="Nehalem"
self.root='sda'
self.wait_for_shutdown=False
self.common_tuxrun(kernel_asset=self.ASSET_X86_64_KERNEL,
rootfs_asset=self.ASSET_X86_64_ROOTFS,
drive="driver=ide-hd,bus=ide.0,unit=0")
drive="driver=ide-hd,bus=ide.0,unit=0",
accel="tcg")
def test_x86_64_kvm(self):
self.require_accelerator("kvm")
self.set_machine('q35')
self.cpu="Nehalem"
self.root='sda'
self.wait_for_shutdown=False
self.common_tuxrun(kernel_asset=self.ASSET_X86_64_KERNEL,
rootfs_asset=self.ASSET_X86_64_ROOTFS,
drive="driver=ide-hd,bus=ide.0,unit=0",
accel="kvm")
@skipIfMissingEnv("QEMU_TEST_GDB")
def test_x86_64_kvm_gdb(self):
self.require_accelerator("kvm")
self.set_machine('q35')
self.cpu="Nehalem"
self.root='sda'
self.wait_for_shutdown=False
self.common_tuxrun_gdb(kernel_asset=self.ASSET_X86_64_KERNEL,
vmlinux_asset=self.ASSET_X86_64_VMLINUX,
rootfs_asset=self.ASSET_X86_64_ROOTFS,
drive="driver=ide-hd,bus=ide.0,unit=0",
accel="kvm")
if __name__ == '__main__':
TuxRunBaselineTest.main()
+58 -27
View File
@@ -25,8 +25,10 @@ def get_args():
required=True)
parser.add_argument("--qargs", help="Qemu arguments for test")
parser.add_argument("--pargs", help="Program arguments for test")
parser.add_argument("--binary", help="Binary to debug",
required=True)
parser.add_argument("--kargs", help="Kernel args to --append")
parser.add_argument("--binary", help="Binary to debug")
parser.add_argument("--symbols", help="Symbol file for binary to debug")
parser.add_argument("--symbol-offset", help="offset to apply to symbols")
parser.add_argument("--test", help="GDB test script")
parser.add_argument('test_args', nargs='*',
help="Additional args for GDB test script. "
@@ -51,6 +53,10 @@ def log(output, msg):
print(msg)
def format_cmd(cmd):
return " ".join(shlex.quote(arg) for arg in cmd)
if __name__ == '__main__':
args = get_args()
@@ -75,55 +81,80 @@ if __name__ == '__main__':
socket_name = os.path.join(socket_dir.name, "gdbstub.socket")
# Launch QEMU with binary
qemu_cmd = [args.qemu]
if args.qargs:
qemu_cmd.extend(shlex.split(args.qargs))
if "system" in args.qemu:
if args.no_suspend:
suspend = ''
else:
suspend = ' -S'
cmd = f'{args.qemu} {args.qargs} {args.binary}' \
f'{suspend} -gdb unix:path={socket_name},server=on'
# for system mode we assume qargs has set-up for binary if
# indeed we have set one.
if args.binary:
qemu_cmd.append(args.binary)
if not args.no_suspend:
qemu_cmd.append("-S")
qemu_cmd.extend(["-gdb", f"unix:path={socket_name},server=on"])
if args.kargs:
qemu_cmd.extend(["--append", args.kargs])
# There is no guest program command-line in system mode.
assert not args.pargs
else:
qemu_cmd.append("-g")
if args.no_suspend:
suspend = ',suspend=n'
qemu_cmd.append(f"{socket_name},suspend=n")
else:
suspend = ''
cmd = f'{args.qemu} {args.qargs} -g {socket_name}{suspend}' \
f' {args.binary}'
if args.pargs:
cmd += f' {args.pargs}'
qemu_cmd.append(f"{socket_name}")
log(output, "QEMU CMD: %s" % (cmd))
inferior = subprocess.Popen(shlex.split(cmd))
# There are no appended args in user-mode
assert not args.kargs
# for user mode binary and args always go at the end
qemu_cmd.append(args.binary)
if args.pargs:
qemu_cmd.extend(shlex.split(args.pargs))
log(output, "QEMU CMD: %s" % (format_cmd(qemu_cmd)))
inferior = subprocess.Popen(qemu_cmd)
# Now launch gdb with our test and collect the result
gdb_cmd = "%s %s" % (args.gdb, args.binary)
gdb_cmd = [args.gdb]
if args.binary:
gdb_cmd.append(args.binary)
if args.gdb_args:
gdb_cmd += " %s" % (args.gdb_args)
gdb_cmd.extend(shlex.split(args.gdb_args))
# run quietly and ignore .gdbinit
gdb_cmd += " -q -n -batch"
gdb_cmd.extend(["-q", "-n", "-batch"])
# disable pagination
gdb_cmd += " -ex 'set pagination off'"
gdb_cmd.extend(["-ex", "set pagination off"])
# disable prompts in case of crash
gdb_cmd += " -ex 'set confirm off'"
gdb_cmd.extend(["-ex", "set confirm off"])
# connect to remote
gdb_cmd += " -ex 'target remote %s'" % (socket_name)
gdb_cmd.extend(["-ex", f"target remote {socket_name}"])
if args.symbols:
sym_arg = f"symbol-file {args.symbols}"
if args.symbol_offset:
sym_arg += f" -o {args.symbol_offset}"
gdb_cmd.extend(["-ex", sym_arg])
# finally the test script itself
if args.test:
if args.test_args:
gdb_cmd += f" -ex \"py sys.argv={args.test_args}\""
gdb_cmd += " -x %s" % (args.test)
gdb_cmd.extend(["-ex", f"py sys.argv={args.test_args}"])
gdb_cmd.extend(["-x", args.test])
sleep(1)
log(output, "GDB CMD: %s" % (gdb_cmd))
log(output, "GDB CMD: %s" % (format_cmd(gdb_cmd)))
gdb_env = dict(os.environ)
gdb_pythonpath = gdb_env.get("PYTHONPATH", "").split(os.pathsep)
gdb_pythonpath.append(os.path.dirname(os.path.realpath(__file__)))
gdb_env["PYTHONPATH"] = os.pathsep.join(gdb_pythonpath)
result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr,
result = subprocess.call(gdb_cmd, stdout=output, stderr=stderr,
env=gdb_env)
# A result of greater than 128 indicates a fatal signal (likely a
-5
View File
@@ -1,11 +1,6 @@
env = find_program('env')
docker_wrapper = find_program('../docker/docker.py')
if get_option('gdb') != ''
gdb = find_program(get_option('gdb'), required: true)
else
gdb = find_program(['gdb-multiarch', 'gdb'], required: false)
endif
prog_check_plugin_output = find_program('./scripts/check_plugin_output.sh')
prog_gdb_test = find_program('../guest-debug/run-test.py')
prog_record_replay = find_program('./scripts/record_replay.sh')
@@ -39,7 +39,7 @@ int main(int argc, char **argv)
assert(qemu);
if (!getenv("QEMU_RTSIG_MAP")) {
char **new_argv = malloc((argc + 2) + sizeof(char *));
char **new_argv = malloc((argc + 2) * sizeof(char *));
int tsig1, hsig1, count1, tsig2, hsig2, count2;
char rt_sigmap[64];