mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 18:23:57 -06:00
tests/tcg: Add two follow-fork-mode tests
Add follow-fork-mode child and and follow-fork-mode parent tests. Check for the obvious pitfalls, such as lingering breakpoints, catchpoints, and single-step mode. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Message-Id: <20240219141628.246823-13-iii@linux.ibm.com> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20240305121005.3528075-14-alex.bennee@linaro.org>
This commit is contained in:
parent
d547e711a8
commit
b9504c9ad9
4 changed files with 128 additions and 1 deletions
|
@ -106,6 +106,20 @@ run-gdbstub-catch-syscalls: catch-syscalls
|
||||||
--bin $< --test $(MULTIARCH_SRC)/gdbstub/catch-syscalls.py, \
|
--bin $< --test $(MULTIARCH_SRC)/gdbstub/catch-syscalls.py, \
|
||||||
hitting a syscall catchpoint)
|
hitting a syscall catchpoint)
|
||||||
|
|
||||||
|
run-gdbstub-follow-fork-mode-child: follow-fork-mode
|
||||||
|
$(call run-test, $@, $(GDB_SCRIPT) \
|
||||||
|
--gdb $(GDB) \
|
||||||
|
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
|
||||||
|
--bin $< --test $(MULTIARCH_SRC)/gdbstub/follow-fork-mode-child.py, \
|
||||||
|
following children on fork)
|
||||||
|
|
||||||
|
run-gdbstub-follow-fork-mode-parent: follow-fork-mode
|
||||||
|
$(call run-test, $@, $(GDB_SCRIPT) \
|
||||||
|
--gdb $(GDB) \
|
||||||
|
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
|
||||||
|
--bin $< --test $(MULTIARCH_SRC)/gdbstub/follow-fork-mode-parent.py, \
|
||||||
|
following parents on fork)
|
||||||
|
|
||||||
else
|
else
|
||||||
run-gdbstub-%:
|
run-gdbstub-%:
|
||||||
$(call skip-test, "gdbstub test $*", "need working gdb with $(patsubst -%,,$(TARGET_NAME)) support")
|
$(call skip-test, "gdbstub test $*", "need working gdb with $(patsubst -%,,$(TARGET_NAME)) support")
|
||||||
|
@ -113,7 +127,8 @@ endif
|
||||||
EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \
|
EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \
|
||||||
run-gdbstub-proc-mappings run-gdbstub-thread-breakpoint \
|
run-gdbstub-proc-mappings run-gdbstub-thread-breakpoint \
|
||||||
run-gdbstub-registers run-gdbstub-prot-none \
|
run-gdbstub-registers run-gdbstub-prot-none \
|
||||||
run-gdbstub-catch-syscalls
|
run-gdbstub-catch-syscalls run-gdbstub-follow-fork-mode-child \
|
||||||
|
run-gdbstub-follow-fork-mode-parent
|
||||||
|
|
||||||
# ARM Compatible Semi Hosting Tests
|
# ARM Compatible Semi Hosting Tests
|
||||||
#
|
#
|
||||||
|
|
56
tests/tcg/multiarch/follow-fork-mode.c
Normal file
56
tests/tcg/multiarch/follow-fork-mode.c
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Test GDB's follow-fork-mode.
|
||||||
|
*
|
||||||
|
* fork() a chain of processes.
|
||||||
|
* Parents sends one byte to their children, and children return their
|
||||||
|
* position in the chain, in order to prove that they survived GDB's fork()
|
||||||
|
* handling.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void break_after_fork(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int depth = 42, err, i, fd[2], status;
|
||||||
|
pid_t child, pid;
|
||||||
|
ssize_t n;
|
||||||
|
char b;
|
||||||
|
|
||||||
|
for (i = 0; i < depth; i++) {
|
||||||
|
err = pipe(fd);
|
||||||
|
assert(err == 0);
|
||||||
|
child = fork();
|
||||||
|
break_after_fork();
|
||||||
|
assert(child != -1);
|
||||||
|
if (child == 0) {
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
n = read(fd[0], &b, 1);
|
||||||
|
close(fd[0]);
|
||||||
|
assert(n == 1);
|
||||||
|
assert(b == (char)i);
|
||||||
|
} else {
|
||||||
|
close(fd[0]);
|
||||||
|
|
||||||
|
b = (char)i;
|
||||||
|
n = write(fd[1], &b, 1);
|
||||||
|
close(fd[1]);
|
||||||
|
assert(n == 1);
|
||||||
|
|
||||||
|
pid = waitpid(child, &status, 0);
|
||||||
|
assert(pid == child);
|
||||||
|
assert(WIFEXITED(status));
|
||||||
|
return WEXITSTATUS(status) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return depth;
|
||||||
|
}
|
40
tests/tcg/multiarch/gdbstub/follow-fork-mode-child.py
Normal file
40
tests/tcg/multiarch/gdbstub/follow-fork-mode-child.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
"""Test GDB's follow-fork-mode child.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
"""
|
||||||
|
from test_gdbstub import main, report
|
||||||
|
|
||||||
|
|
||||||
|
def run_test():
|
||||||
|
"""Run through the tests one by one"""
|
||||||
|
gdb.execute("set follow-fork-mode child")
|
||||||
|
# Check that the parent breakpoints are unset.
|
||||||
|
gdb.execute("break break_after_fork")
|
||||||
|
# Check that the parent syscall catchpoints are unset.
|
||||||
|
# Skip this check on the architectures that don't have them.
|
||||||
|
have_fork_syscall = False
|
||||||
|
for fork_syscall in ("fork", "clone", "clone2", "clone3"):
|
||||||
|
try:
|
||||||
|
gdb.execute("catch syscall {}".format(fork_syscall))
|
||||||
|
except gdb.error:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
have_fork_syscall = True
|
||||||
|
gdb.execute("continue")
|
||||||
|
for i in range(42):
|
||||||
|
if have_fork_syscall:
|
||||||
|
# syscall entry.
|
||||||
|
if i % 2 == 0:
|
||||||
|
# Check that the parent single-stepping is turned off.
|
||||||
|
gdb.execute("si")
|
||||||
|
else:
|
||||||
|
gdb.execute("continue")
|
||||||
|
# syscall exit.
|
||||||
|
gdb.execute("continue")
|
||||||
|
# break_after_fork()
|
||||||
|
gdb.execute("continue")
|
||||||
|
exitcode = int(gdb.parse_and_eval("$_exitcode"))
|
||||||
|
report(exitcode == 42, "{} == 42".format(exitcode))
|
||||||
|
|
||||||
|
|
||||||
|
main(run_test)
|
16
tests/tcg/multiarch/gdbstub/follow-fork-mode-parent.py
Normal file
16
tests/tcg/multiarch/gdbstub/follow-fork-mode-parent.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
"""Test GDB's follow-fork-mode parent.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
"""
|
||||||
|
from test_gdbstub import main, report
|
||||||
|
|
||||||
|
|
||||||
|
def run_test():
|
||||||
|
"""Run through the tests one by one"""
|
||||||
|
gdb.execute("set follow-fork-mode parent")
|
||||||
|
gdb.execute("continue")
|
||||||
|
exitcode = int(gdb.parse_and_eval("$_exitcode"))
|
||||||
|
report(exitcode == 0, "{} == 0".format(exitcode))
|
||||||
|
|
||||||
|
|
||||||
|
main(run_test)
|
Loading…
Add table
Add a link
Reference in a new issue