tests/tcg: Add the syscall catchpoint gdbstub test
Check that adding/removing syscall catchpoints works. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Message-Id: <20240202152506.279476-6-iii@linux.ibm.com> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20240207163812.3231697-15-alex.bennee@linaro.org>
This commit is contained in:
parent
046f143c51
commit
86b75667e0
@ -108,13 +108,21 @@ run-gdbstub-prot-none: prot-none
|
|||||||
--bin $< --test $(MULTIARCH_SRC)/gdbstub/prot-none.py, \
|
--bin $< --test $(MULTIARCH_SRC)/gdbstub/prot-none.py, \
|
||||||
accessing PROT_NONE memory)
|
accessing PROT_NONE memory)
|
||||||
|
|
||||||
|
run-gdbstub-catch-syscalls: catch-syscalls
|
||||||
|
$(call run-test, $@, $(GDB_SCRIPT) \
|
||||||
|
--gdb $(GDB) \
|
||||||
|
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
|
||||||
|
--bin $< --test $(MULTIARCH_SRC)/gdbstub/catch-syscalls.py, \
|
||||||
|
hitting a syscall catchpoint)
|
||||||
|
|
||||||
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")
|
||||||
endif
|
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
|
||||||
|
|
||||||
# ARM Compatible Semi Hosting Tests
|
# ARM Compatible Semi Hosting Tests
|
||||||
#
|
#
|
||||||
|
51
tests/tcg/multiarch/catch-syscalls.c
Normal file
51
tests/tcg/multiarch/catch-syscalls.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Test GDB syscall catchpoints.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
const char *catch_syscalls_state = "start";
|
||||||
|
|
||||||
|
void end_of_main(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int ret = EXIT_FAILURE;
|
||||||
|
char c0 = 'A', c1;
|
||||||
|
int fd[2];
|
||||||
|
|
||||||
|
catch_syscalls_state = "pipe2";
|
||||||
|
if (pipe2(fd, 0)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch_syscalls_state = "write";
|
||||||
|
if (write(fd[1], &c0, sizeof(c0)) != sizeof(c0)) {
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch_syscalls_state = "read";
|
||||||
|
if (read(fd[0], &c1, sizeof(c1)) != sizeof(c1)) {
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch_syscalls_state = "check";
|
||||||
|
if (c0 == c1) {
|
||||||
|
ret = EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_close:
|
||||||
|
catch_syscalls_state = "close";
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
out:
|
||||||
|
catch_syscalls_state = "end";
|
||||||
|
end_of_main();
|
||||||
|
return ret;
|
||||||
|
}
|
53
tests/tcg/multiarch/gdbstub/catch-syscalls.py
Normal file
53
tests/tcg/multiarch/gdbstub/catch-syscalls.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"""Test GDB syscall catchpoints.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
"""
|
||||||
|
from test_gdbstub import main, report
|
||||||
|
|
||||||
|
|
||||||
|
def check_state(expected):
|
||||||
|
"""Check the catch_syscalls_state value"""
|
||||||
|
actual = gdb.parse_and_eval("catch_syscalls_state").string()
|
||||||
|
report(actual == expected, "{} == {}".format(actual, expected))
|
||||||
|
|
||||||
|
|
||||||
|
def run_test():
|
||||||
|
"""Run through the tests one by one"""
|
||||||
|
gdb.Breakpoint("main")
|
||||||
|
gdb.execute("continue")
|
||||||
|
|
||||||
|
# Check that GDB stops for pipe2/read calls/returns, but not for write.
|
||||||
|
gdb.execute("delete")
|
||||||
|
try:
|
||||||
|
gdb.execute("catch syscall pipe2 read")
|
||||||
|
except gdb.error as exc:
|
||||||
|
exc_str = str(exc)
|
||||||
|
if "not supported on this architecture" in exc_str:
|
||||||
|
print("SKIP: {}".format(exc_str))
|
||||||
|
return
|
||||||
|
raise
|
||||||
|
for _ in range(2):
|
||||||
|
gdb.execute("continue")
|
||||||
|
check_state("pipe2")
|
||||||
|
for _ in range(2):
|
||||||
|
gdb.execute("continue")
|
||||||
|
check_state("read")
|
||||||
|
|
||||||
|
# Check that deletion works.
|
||||||
|
gdb.execute("delete")
|
||||||
|
gdb.Breakpoint("end_of_main")
|
||||||
|
gdb.execute("continue")
|
||||||
|
check_state("end")
|
||||||
|
|
||||||
|
# Check that catch-all works (libc should at least call exit).
|
||||||
|
gdb.execute("delete")
|
||||||
|
gdb.execute("catch syscall")
|
||||||
|
gdb.execute("continue")
|
||||||
|
gdb.execute("delete")
|
||||||
|
gdb.execute("continue")
|
||||||
|
|
||||||
|
exitcode = int(gdb.parse_and_eval("$_exitcode"))
|
||||||
|
report(exitcode == 0, "{} == 0".format(exitcode))
|
||||||
|
|
||||||
|
|
||||||
|
main(run_test)
|
Loading…
Reference in New Issue
Block a user