tests/tcg: Add late gdbstub attach test

Add a small test to prevent regressions.
Make sure that host_interrupt_signal is not visible to the guest.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-Id: <20250117001542.8290-9-iii@linux.ibm.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20250207153112.3939799-18-alex.bennee@linaro.org>
This commit is contained in:
Ilya Leoshkevich 2025-02-07 15:31:12 +00:00 committed by Alex Bennée
parent 628d64222e
commit 24c61663dc
4 changed files with 90 additions and 3 deletions

View file

@ -36,6 +36,8 @@ def get_args():
parser.add_argument("--gdb-args", help="Additional gdb arguments")
parser.add_argument("--output", help="A file to redirect output to")
parser.add_argument("--stderr", help="A file to redirect stderr to")
parser.add_argument("--no-suspend", action="store_true",
help="Ask the binary to not wait for GDB connection")
return parser.parse_args()
@ -73,10 +75,19 @@ if __name__ == '__main__':
# Launch QEMU with binary
if "system" in args.qemu:
if args.no_suspend:
suspend = ''
else:
suspend = ' -S'
cmd = f'{args.qemu} {args.qargs} {args.binary}' \
f' -S -gdb unix:path={socket_name},server=on'
f'{suspend} -gdb unix:path={socket_name},server=on'
else:
cmd = f'{args.qemu} {args.qargs} -g {socket_name} {args.binary}'
if args.no_suspend:
suspend = ',suspend=n'
else:
suspend = ''
cmd = f'{args.qemu} {args.qargs} -g {socket_name}{suspend}' \
f' {args.binary}'
log(output, "QEMU CMD: %s" % (cmd))
inferior = subprocess.Popen(shlex.split(cmd))

View file

@ -130,6 +130,13 @@ run-gdbstub-follow-fork-mode-parent: follow-fork-mode
--bin $< --test $(MULTIARCH_SRC)/gdbstub/follow-fork-mode-parent.py, \
following parents on fork)
run-gdbstub-late-attach: late-attach
$(call run-test, $@, env LATE_ATTACH_PY=1 $(GDB_SCRIPT) \
--gdb $(GDB) \
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" --no-suspend \
--bin $< --test $(MULTIARCH_SRC)/gdbstub/late-attach.py, \
attaching to a running process)
else
run-gdbstub-%:
$(call skip-test, "gdbstub test $*", "need working gdb with $(patsubst -%,,$(TARGET_NAME)) support")
@ -139,7 +146,7 @@ EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \
run-gdbstub-registers run-gdbstub-prot-none \
run-gdbstub-catch-syscalls run-gdbstub-follow-fork-mode-child \
run-gdbstub-follow-fork-mode-parent \
run-gdbstub-qxfer-siginfo-read
run-gdbstub-qxfer-siginfo-read run-gdbstub-late-attach
# ARM Compatible Semi Hosting Tests
#

View file

@ -0,0 +1,28 @@
"""Test attaching GDB to a running process.
SPDX-License-Identifier: GPL-2.0-or-later
"""
from test_gdbstub import main, report
def run_test():
"""Run through the tests one by one"""
try:
phase = gdb.parse_and_eval("phase").string()
except gdb.error:
# Assume the guest did not reach main().
phase = "start"
if phase == "start":
gdb.execute("break sigwait")
gdb.execute("continue")
phase = gdb.parse_and_eval("phase").string()
report(phase == "sigwait", "{} == \"sigwait\"".format(phase))
gdb.execute("signal SIGUSR1")
exitcode = int(gdb.parse_and_eval("$_exitcode"))
report(exitcode == 0, "{} == 0".format(exitcode))
main(run_test)

View file

@ -0,0 +1,41 @@
/*
* Test attaching GDB to a running process.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static const char *phase = "start";
int main(void)
{
sigset_t set;
int sig;
assert(sigfillset(&set) == 0);
assert(sigprocmask(SIG_BLOCK, &set, NULL) == 0);
/* Let GDB know it can send SIGUSR1. */
phase = "sigwait";
if (getenv("LATE_ATTACH_PY")) {
assert(sigwait(&set, &sig) == 0);
if (sig != SIGUSR1) {
fprintf(stderr, "Unexpected signal %d\n", sig);
return EXIT_FAILURE;
}
}
/* Check that the guest does not see host_interrupt_signal. */
assert(sigpending(&set) == 0);
for (sig = 1; sig < NSIG; sig++) {
if (sigismember(&set, sig)) {
fprintf(stderr, "Unexpected signal %d\n", sig);
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}