mirror of https://github.com/xemu-project/xemu.git
testing, doc and gdbstub updates:
- add sqlite3 to openSUSE image - mark CRIS as deprecated - re-enable the TCG plugin tests - use select for semihosting - implement syscall catching in gdbstub -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmXGZtQACgkQ+9DbCVqe KkTegAgAg7Kkd0Pa2cgkPfNPYR5yT4hYurjVSfi/69cOpj/Vadsav4WWFsuUiQMI FfKWCNDo5lmNcWIPKgC0oeWVwxal4IhqhO8f9lRIYqg9z4bRkZbdsrvh8J52Q6Xh Bu9UAEk5KBGrMfEdsAwHnVDg435c7IGdJZnE/iKBK1aKljS5LOiX1J6ZxrqUoMsJ keTAcdXyvs/BIz68c87AHrW/HKO9KKLgHA2n7T/l2N5KJdoa3p8La9py+v1SGUh8 6JlDRYR1H16mITS8tm6ZffPqcOpfHXp7DRquu7obVS5+CVTJ2H9w8TICw56rqMg7 cVnysNLhdS18cMNKD2Jx3zgd5Nq/cg== =deHm -----END PGP SIGNATURE----- Merge tag 'pull-maintainer-updates-090224-1' of https://gitlab.com/stsquad/qemu into staging testing, doc and gdbstub updates: - add sqlite3 to openSUSE image - mark CRIS as deprecated - re-enable the TCG plugin tests - use select for semihosting - implement syscall catching in gdbstub # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmXGZtQACgkQ+9DbCVqe # KkTegAgAg7Kkd0Pa2cgkPfNPYR5yT4hYurjVSfi/69cOpj/Vadsav4WWFsuUiQMI # FfKWCNDo5lmNcWIPKgC0oeWVwxal4IhqhO8f9lRIYqg9z4bRkZbdsrvh8J52Q6Xh # Bu9UAEk5KBGrMfEdsAwHnVDg435c7IGdJZnE/iKBK1aKljS5LOiX1J6ZxrqUoMsJ # keTAcdXyvs/BIz68c87AHrW/HKO9KKLgHA2n7T/l2N5KJdoa3p8La9py+v1SGUh8 # 6JlDRYR1H16mITS8tm6ZffPqcOpfHXp7DRquu7obVS5+CVTJ2H9w8TICw56rqMg7 # cVnysNLhdS18cMNKD2Jx3zgd5Nq/cg== # =deHm # -----END PGP SIGNATURE----- # gpg: Signature made Fri 09 Feb 2024 17:54:28 GMT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * tag 'pull-maintainer-updates-090224-1' of https://gitlab.com/stsquad/qemu: tests/tcg: Add the syscall catchpoint gdbstub test gdbstub: Implement catching syscalls gdbstub: Add syscall entry/return hooks gdbstub: Allow specifying a reason in stop packets gdbstub: Expose TARGET_SIGTRAP in a target-agnostic way kconfig: use "select" to enable semihosting Revert "hw/elf_ops: Ignore loadable segments with zero size" configure: run plugin TCG tests again docs: mark CRIS support as deprecated tests/docker: Add sqlite3 module to openSUSE Leap container Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5005aed8a7
|
@ -1,7 +1,5 @@
|
|||
# Default configuration for m68k-softmmu
|
||||
|
||||
CONFIG_SEMIHOSTING=y
|
||||
|
||||
# Boards:
|
||||
#
|
||||
CONFIG_AN5206=y
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
# Common mips*-softmmu CONFIG defines
|
||||
|
||||
# CONFIG_SEMIHOSTING is always required on this architecture
|
||||
CONFIG_SEMIHOSTING=y
|
||||
|
||||
CONFIG_ISA_BUS=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DEVICES=y
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# Default configuration for nios2-softmmu
|
||||
|
||||
CONFIG_SEMIHOSTING=y
|
||||
|
||||
# Boards:
|
||||
#
|
||||
CONFIG_NIOS2_10M50=y
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
# Uncomment the following lines to disable these optional devices:
|
||||
#
|
||||
#CONFIG_PCI_DEVICES=n
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
||||
# Boards:
|
||||
#
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
# Uncomment the following lines to disable these optional devices:
|
||||
#
|
||||
#CONFIG_PCI_DEVICES=n
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
||||
# Boards:
|
||||
#
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# Default configuration for Xtensa
|
||||
|
||||
CONFIG_SEMIHOSTING=y
|
||||
|
||||
# Boards:
|
||||
#
|
||||
CONFIG_XTENSA_SIM=y
|
||||
|
|
|
@ -1644,6 +1644,9 @@ fi
|
|||
mkdir -p tests/tcg
|
||||
echo "# Automatically generated by configure - do not modify" > tests/tcg/$config_host_mak
|
||||
echo "SRC_PATH=$source_path" >> tests/tcg/$config_host_mak
|
||||
if test "$plugins" = "yes" ; then
|
||||
echo "CONFIG_PLUGIN=y" >> tests/tcg/$config_host_mak
|
||||
fi
|
||||
|
||||
tcg_tests_targets=
|
||||
for target in $target_list; do
|
||||
|
|
|
@ -192,6 +192,13 @@ in the QEMU object model anymore. ``power5+``, ``power5+_v2.1``,
|
|||
an alias, but for consistency these will get removed in a future
|
||||
release, too. Use ``power5p_v2.1`` and ``power7p_v2.1`` instead.
|
||||
|
||||
CRIS CPU architecture (since 9.0)
|
||||
'''''''''''''''''''''''''''''''''
|
||||
|
||||
The CRIS architecture was pulled from Linux in 4.17 and the compiler
|
||||
is no longer packaged in any distro making it harder to run the
|
||||
``check-tcg`` tests. Unless we can improve the testing situation there
|
||||
is a chance the code will bitrot without anyone noticing.
|
||||
|
||||
System emulator machines
|
||||
------------------------
|
||||
|
|
|
@ -1617,6 +1617,7 @@ static void handle_query_supported(GArray *params, void *user_ctx)
|
|||
if (gdbserver_state.c_cpu->opaque) {
|
||||
g_string_append(gdbserver_state.str_buf, ";qXfer:auxv:read+");
|
||||
}
|
||||
g_string_append(gdbserver_state.str_buf, ";QCatchSyscalls+");
|
||||
#endif
|
||||
g_string_append(gdbserver_state.str_buf, ";qXfer:exec-file:read+");
|
||||
#endif
|
||||
|
@ -1810,6 +1811,14 @@ static const GdbCmdParseEntry gdb_gen_set_table[] = {
|
|||
.schema = "l0"
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
{
|
||||
.handler = gdb_handle_set_catch_syscalls,
|
||||
.cmd = "CatchSyscalls:",
|
||||
.cmd_startswith = 1,
|
||||
.schema = "s0",
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static void handle_gen_query(GArray *params, void *user_ctx)
|
||||
|
|
|
@ -136,6 +136,7 @@ void gdb_append_thread_id(CPUState *cpu, GString *buf);
|
|||
int gdb_get_cpu_index(CPUState *cpu);
|
||||
unsigned int gdb_get_max_cpus(void); /* both */
|
||||
bool gdb_can_reverse(void); /* softmmu, stub for user */
|
||||
int gdb_target_sigtrap(void); /* user */
|
||||
|
||||
void gdb_create_default_process(GDBState *s);
|
||||
|
||||
|
@ -194,6 +195,7 @@ void gdb_handle_v_file_close(GArray *params, void *user_ctx); /* user */
|
|||
void gdb_handle_v_file_pread(GArray *params, void *user_ctx); /* user */
|
||||
void gdb_handle_v_file_readlink(GArray *params, void *user_ctx); /* user */
|
||||
void gdb_handle_query_xfer_exec_file(GArray *params, void *user_ctx); /* user */
|
||||
void gdb_handle_set_catch_syscalls(GArray *params, void *user_ctx); /* user */
|
||||
|
||||
void gdb_handle_query_attached(GArray *params, void *user_ctx); /* both */
|
||||
|
||||
|
|
|
@ -418,3 +418,8 @@ void gdb_handle_query_xfer_exec_file(GArray *params, void *user_ctx)
|
|||
ts->bprm->filename + offset);
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
int gdb_target_sigtrap(void)
|
||||
{
|
||||
return TARGET_SIGTRAP;
|
||||
}
|
||||
|
|
104
gdbstub/user.c
104
gdbstub/user.c
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "exec/hwaddr.h"
|
||||
|
@ -21,11 +22,20 @@
|
|||
#include "trace.h"
|
||||
#include "internals.h"
|
||||
|
||||
#define GDB_NR_SYSCALLS 1024
|
||||
typedef unsigned long GDBSyscallsMask[BITS_TO_LONGS(GDB_NR_SYSCALLS)];
|
||||
|
||||
/* User-mode specific state */
|
||||
typedef struct {
|
||||
int fd;
|
||||
char *socket_path;
|
||||
int running_state;
|
||||
/*
|
||||
* Store syscalls mask without memory allocation in order to avoid
|
||||
* implementing synchronization.
|
||||
*/
|
||||
bool catch_all_syscalls;
|
||||
GDBSyscallsMask catch_syscalls_mask;
|
||||
} GDBUserState;
|
||||
|
||||
static GDBUserState gdbserver_user_state;
|
||||
|
@ -121,7 +131,7 @@ void gdb_qemu_exit(int code)
|
|||
exit(code);
|
||||
}
|
||||
|
||||
int gdb_handlesig(CPUState *cpu, int sig)
|
||||
int gdb_handlesig_reason(CPUState *cpu, int sig, const char *reason)
|
||||
{
|
||||
char buf[256];
|
||||
int n;
|
||||
|
@ -141,6 +151,9 @@ int gdb_handlesig(CPUState *cpu, int sig)
|
|||
"T%02xthread:", gdb_target_signal_to_gdb(sig));
|
||||
gdb_append_thread_id(cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
if (reason) {
|
||||
g_string_append(gdbserver_state.str_buf, reason);
|
||||
}
|
||||
gdb_put_strbuf();
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
}
|
||||
|
@ -499,3 +512,92 @@ void gdb_syscall_handling(const char *syscall_packet)
|
|||
gdb_put_packet(syscall_packet);
|
||||
gdb_handlesig(gdbserver_state.c_cpu, 0);
|
||||
}
|
||||
|
||||
static bool should_catch_syscall(int num)
|
||||
{
|
||||
if (gdbserver_user_state.catch_all_syscalls) {
|
||||
return true;
|
||||
}
|
||||
if (num < 0 || num >= GDB_NR_SYSCALLS) {
|
||||
return false;
|
||||
}
|
||||
return test_bit(num, gdbserver_user_state.catch_syscalls_mask);
|
||||
}
|
||||
|
||||
void gdb_syscall_entry(CPUState *cs, int num)
|
||||
{
|
||||
if (should_catch_syscall(num)) {
|
||||
g_autofree char *reason = g_strdup_printf("syscall_entry:%x;", num);
|
||||
gdb_handlesig_reason(cs, gdb_target_sigtrap(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
void gdb_syscall_return(CPUState *cs, int num)
|
||||
{
|
||||
if (should_catch_syscall(num)) {
|
||||
g_autofree char *reason = g_strdup_printf("syscall_return:%x;", num);
|
||||
gdb_handlesig_reason(cs, gdb_target_sigtrap(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
void gdb_handle_set_catch_syscalls(GArray *params, void *user_ctx)
|
||||
{
|
||||
const char *param = get_param(params, 0)->data;
|
||||
GDBSyscallsMask catch_syscalls_mask;
|
||||
bool catch_all_syscalls;
|
||||
unsigned int num;
|
||||
const char *p;
|
||||
|
||||
/* "0" means not catching any syscalls. */
|
||||
if (strcmp(param, "0") == 0) {
|
||||
gdbserver_user_state.catch_all_syscalls = false;
|
||||
memset(gdbserver_user_state.catch_syscalls_mask, 0,
|
||||
sizeof(gdbserver_user_state.catch_syscalls_mask));
|
||||
gdb_put_packet("OK");
|
||||
return;
|
||||
}
|
||||
|
||||
/* "1" means catching all syscalls. */
|
||||
if (strcmp(param, "1") == 0) {
|
||||
gdbserver_user_state.catch_all_syscalls = true;
|
||||
gdb_put_packet("OK");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* "1;..." means catching only the specified syscalls.
|
||||
* The syscall list must not be empty.
|
||||
*/
|
||||
if (param[0] == '1' && param[1] == ';') {
|
||||
catch_all_syscalls = false;
|
||||
memset(catch_syscalls_mask, 0, sizeof(catch_syscalls_mask));
|
||||
for (p = ¶m[2];; p++) {
|
||||
if (qemu_strtoui(p, &p, 16, &num) || (*p && *p != ';')) {
|
||||
goto err;
|
||||
}
|
||||
if (num >= GDB_NR_SYSCALLS) {
|
||||
/*
|
||||
* Fall back to reporting all syscalls. Reporting extra
|
||||
* syscalls is inefficient, but the spec explicitly allows it.
|
||||
* Keep parsing in case there is a syntax error ahead.
|
||||
*/
|
||||
catch_all_syscalls = true;
|
||||
} else {
|
||||
set_bit(num, catch_syscalls_mask);
|
||||
}
|
||||
if (!*p) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
gdbserver_user_state.catch_all_syscalls = catch_all_syscalls;
|
||||
if (!catch_all_syscalls) {
|
||||
memcpy(gdbserver_user_state.catch_syscalls_mask,
|
||||
catch_syscalls_mask, sizeof(catch_syscalls_mask));
|
||||
}
|
||||
gdb_put_packet("OK");
|
||||
return;
|
||||
}
|
||||
|
||||
err:
|
||||
gdb_put_packet("E00");
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
#define GDBSTUB_USER_H
|
||||
|
||||
/**
|
||||
* gdb_handlesig() - yield control to gdb
|
||||
* gdb_handlesig_reason() - yield control to gdb
|
||||
* @cpu: CPU
|
||||
* @sig: if non-zero, the signal number which caused us to stop
|
||||
* @reason: stop reason for stop reply packet or NULL
|
||||
*
|
||||
* This function yields control to gdb, when a user-mode-only target
|
||||
* needs to stop execution. If @sig is non-zero, then we will send a
|
||||
|
@ -24,7 +25,18 @@
|
|||
* or 0 if no signal should be delivered, ie the signal that caused
|
||||
* us to stop should be ignored.
|
||||
*/
|
||||
int gdb_handlesig(CPUState *, int);
|
||||
int gdb_handlesig_reason(CPUState *, int, const char *);
|
||||
|
||||
/**
|
||||
* gdb_handlesig() - yield control to gdb
|
||||
* @cpu CPU
|
||||
* @sig: if non-zero, the signal number which caused us to stop
|
||||
* @see gdb_handlesig_reason()
|
||||
*/
|
||||
static inline int gdb_handlesig(CPUState *cpu, int sig)
|
||||
{
|
||||
return gdb_handlesig_reason(cpu, sig, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdb_signalled() - inform remote gdb of sig exit
|
||||
|
@ -39,5 +51,18 @@ void gdb_signalled(CPUArchState *as, int sig);
|
|||
*/
|
||||
void gdbserver_fork(CPUState *cs);
|
||||
|
||||
/**
|
||||
* gdb_syscall_entry() - inform gdb of syscall entry and yield control to it
|
||||
* @cs: CPU
|
||||
* @num: syscall number
|
||||
*/
|
||||
void gdb_syscall_entry(CPUState *cs, int num);
|
||||
|
||||
/**
|
||||
* gdb_syscall_entry() - inform gdb of syscall return and yield control to it
|
||||
* @cs: CPU
|
||||
* @num: syscall number
|
||||
*/
|
||||
void gdb_syscall_return(CPUState *cs, int num);
|
||||
|
||||
#endif /* GDBSTUB_USER_H */
|
||||
|
|
|
@ -427,16 +427,6 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
|
|||
file_size = ph->p_filesz; /* Size of the allocated data */
|
||||
data_offset = ph->p_offset; /* Offset where the data is located */
|
||||
|
||||
/*
|
||||
* Some ELF files really do have segments of zero size;
|
||||
* just ignore them rather than trying to set the wrong addr,
|
||||
* or create empty ROM blobs, because the zero-length blob can
|
||||
* falsely trigger the overlapping-ROM-blobs check.
|
||||
*/
|
||||
if (mem_size == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file_size > 0) {
|
||||
if (g_mapped_file_get_length(mapped_file) <
|
||||
file_size + data_offset) {
|
||||
|
@ -540,38 +530,45 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
|
|||
*pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr;
|
||||
}
|
||||
|
||||
if (load_rom) {
|
||||
g_autofree char *label =
|
||||
g_strdup_printf("%s ELF program header segment %d",
|
||||
name, i);
|
||||
/* Some ELF files really do have segments of zero size;
|
||||
* just ignore them rather than trying to create empty
|
||||
* ROM blobs, because the zero-length blob can falsely
|
||||
* trigger the overlapping-ROM-blobs check.
|
||||
*/
|
||||
if (mem_size != 0) {
|
||||
if (load_rom) {
|
||||
g_autofree char *label =
|
||||
g_strdup_printf("%s ELF program header segment %d",
|
||||
name, i);
|
||||
|
||||
/*
|
||||
* rom_add_elf_program() takes its own reference to
|
||||
* 'mapped_file'.
|
||||
*/
|
||||
rom_add_elf_program(label, mapped_file, data, file_size,
|
||||
mem_size, addr, as);
|
||||
} else {
|
||||
MemTxResult res;
|
||||
/*
|
||||
* rom_add_elf_program() takes its own reference to
|
||||
* 'mapped_file'.
|
||||
*/
|
||||
rom_add_elf_program(label, mapped_file, data, file_size,
|
||||
mem_size, addr, as);
|
||||
} else {
|
||||
MemTxResult res;
|
||||
|
||||
res = address_space_write(as ? as : &address_space_memory,
|
||||
addr, MEMTXATTRS_UNSPECIFIED,
|
||||
data, file_size);
|
||||
if (res != MEMTX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
/*
|
||||
* We need to zero'ify the space that is not copied
|
||||
* from file
|
||||
*/
|
||||
if (file_size < mem_size) {
|
||||
res = address_space_set(as ? as : &address_space_memory,
|
||||
addr + file_size, 0,
|
||||
mem_size - file_size,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
res = address_space_write(as ? as : &address_space_memory,
|
||||
addr, MEMTXATTRS_UNSPECIFIED,
|
||||
data, file_size);
|
||||
if (res != MEMTX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
/*
|
||||
* We need to zero'ify the space that is not copied
|
||||
* from file
|
||||
*/
|
||||
if (file_size < mem_size) {
|
||||
res = address_space_set(as ? as : &address_space_memory,
|
||||
addr + file_size, 0,
|
||||
mem_size - file_size,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
if (res != MEMTX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define SYSCALL_TRACE_H
|
||||
|
||||
#include "exec/user/abitypes.h"
|
||||
#include "gdbstub/user.h"
|
||||
#include "qemu/plugin.h"
|
||||
#include "trace/trace-root.h"
|
||||
|
||||
|
@ -20,7 +21,7 @@
|
|||
* could potentially unify the -strace code here as well.
|
||||
*/
|
||||
|
||||
static inline void record_syscall_start(void *cpu, int num,
|
||||
static inline void record_syscall_start(CPUState *cpu, int num,
|
||||
abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4,
|
||||
abi_long arg5, abi_long arg6,
|
||||
|
@ -29,11 +30,13 @@ static inline void record_syscall_start(void *cpu, int num,
|
|||
qemu_plugin_vcpu_syscall(cpu, num,
|
||||
arg1, arg2, arg3, arg4,
|
||||
arg5, arg6, arg7, arg8);
|
||||
gdb_syscall_entry(cpu, num);
|
||||
}
|
||||
|
||||
static inline void record_syscall_return(void *cpu, int num, abi_long ret)
|
||||
static inline void record_syscall_return(CPUState *cpu, int num, abi_long ret)
|
||||
{
|
||||
qemu_plugin_vcpu_syscall_ret(cpu, num, ret);
|
||||
gdb_syscall_return(cpu, num);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
config M68K
|
||||
bool
|
||||
select SEMIHOSTING
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
config MIPS
|
||||
bool
|
||||
select SEMIHOSTING
|
||||
|
||||
config MIPS64
|
||||
bool
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
config NIOS2
|
||||
bool
|
||||
select SEMIHOSTING
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
config RISCV32
|
||||
bool
|
||||
select ARM_COMPATIBLE_SEMIHOSTING # for do_common_semihosting()
|
||||
|
||||
config RISCV64
|
||||
bool
|
||||
select ARM_COMPATIBLE_SEMIHOSTING # for do_common_semihosting()
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
config XTENSA
|
||||
bool
|
||||
select SEMIHOSTING
|
||||
|
|
|
@ -90,6 +90,7 @@ RUN zypper update -y && \
|
|||
pcre-devel-static \
|
||||
pipewire-devel \
|
||||
pkgconfig \
|
||||
python311 \
|
||||
python311-base \
|
||||
python311-pip \
|
||||
python311-setuptools \
|
||||
|
|
|
@ -59,6 +59,10 @@ mappings:
|
|||
CentOSStream8:
|
||||
OpenSUSELeap15:
|
||||
|
||||
python3-sqlite3:
|
||||
CentOSStream8: python38
|
||||
OpenSUSELeap15: python311
|
||||
|
||||
python3-tomli:
|
||||
# test using tomllib
|
||||
apk:
|
||||
|
|
|
@ -97,6 +97,7 @@ packages:
|
|||
- python3-pip
|
||||
- python3-sphinx
|
||||
- python3-sphinx-rtd-theme
|
||||
- python3-sqlite3
|
||||
- python3-tomli
|
||||
- python3-venv
|
||||
- rpm2cpio
|
||||
|
|
|
@ -108,13 +108,21 @@ run-gdbstub-prot-none: prot-none
|
|||
--bin $< --test $(MULTIARCH_SRC)/gdbstub/prot-none.py, \
|
||||
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
|
||||
run-gdbstub-%:
|
||||
$(call skip-test, "gdbstub test $*", "need working gdb with $(patsubst -%,,$(TARGET_NAME)) support")
|
||||
endif
|
||||
EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \
|
||||
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
|
||||
#
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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