final updates for 9.0 (testing, gdbstub):
- fix the over rebuilding of test VMs - support Xfer:siginfo:read in gdbstub - fix double close() in gdbstub -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmXxkb0ACgkQ+9DbCVqe KkSw9wf+K+3kJYaZ2unEFku3Y6f4Z9XkrZCsFQFVNIJQgpYVc6peQyLUB1pZwzZc yoQhmTIgej16iRZc7gEcJhFl2zlX2vulE/m+wiaR0Chv3E2r510AGn4aWl+GLB9+ /WduHaz1NobPW4JWaarxespa84Re8QZQgqkHX4nwYd++FW63E4uxydL4F1nmSNca eTA6RwS48h4wqPzHBX72hYTRUnYrDUSSGCGUDzK3NHumuPi+AQ77GLRMO0MTYFfy hWriapogCmghY+Xtn++eUIwDyh1CCnUT6Ntf5Qj06bZ+f6eaTwINM8QWhj9mxYX+ 5/F5Q4JJDqRPYw/hF4wYXRsiZxTYFw== =BOWW -----END PGP SIGNATURE----- Merge tag 'pull-maintainer-final-130324-1' of https://gitlab.com/stsquad/qemu into staging final updates for 9.0 (testing, gdbstub): - fix the over rebuilding of test VMs - support Xfer:siginfo:read in gdbstub - fix double close() in gdbstub # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmXxkb0ACgkQ+9DbCVqe # KkSw9wf+K+3kJYaZ2unEFku3Y6f4Z9XkrZCsFQFVNIJQgpYVc6peQyLUB1pZwzZc # yoQhmTIgej16iRZc7gEcJhFl2zlX2vulE/m+wiaR0Chv3E2r510AGn4aWl+GLB9+ # /WduHaz1NobPW4JWaarxespa84Re8QZQgqkHX4nwYd++FW63E4uxydL4F1nmSNca # eTA6RwS48h4wqPzHBX72hYTRUnYrDUSSGCGUDzK3NHumuPi+AQ77GLRMO0MTYFfy # hWriapogCmghY+Xtn++eUIwDyh1CCnUT6Ntf5Qj06bZ+f6eaTwINM8QWhj9mxYX+ # 5/F5Q4JJDqRPYw/hF4wYXRsiZxTYFw== # =BOWW # -----END PGP SIGNATURE----- # gpg: Signature made Wed 13 Mar 2024 11:45:01 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-final-130324-1' of https://gitlab.com/stsquad/qemu: gdbstub: Fix double close() of the follow-fork-mode socket tests/tcg: Add multiarch test for Xfer:siginfo:read stub gdbstub: Add Xfer:siginfo:read stub gdbstub: Save target's siginfo linux-user: Move tswap_siginfo out of target code gdbstub: Rename back gdb_handlesig tests/vm: ensure we build everything by default Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
ba49d760eb
@ -606,7 +606,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (gdbstub) {
|
||||
gdbserver_start(gdbstub);
|
||||
gdb_handlesig(cpu, 0);
|
||||
gdb_handlesig(cpu, 0, NULL, NULL, 0);
|
||||
}
|
||||
cpu_loop(env);
|
||||
/* never exits */
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
#include "host-signal.h"
|
||||
|
||||
/* target_siginfo_t must fit in gdbstub's siginfo save area. */
|
||||
QEMU_BUILD_BUG_ON(sizeof(target_siginfo_t) > MAX_SIGINFO_LENGTH);
|
||||
|
||||
static struct target_sigaction sigact_table[TARGET_NSIG];
|
||||
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc);
|
||||
static void target_to_host_sigset_internal(sigset_t *d,
|
||||
@ -889,7 +892,7 @@ static void handle_pending_signal(CPUArchState *env, int sig,
|
||||
|
||||
k->pending = 0;
|
||||
|
||||
sig = gdb_handlesig(cpu, sig);
|
||||
sig = gdb_handlesig(cpu, sig, NULL, &k->info, sizeof(k->info));
|
||||
if (!sig) {
|
||||
sa = NULL;
|
||||
handler = TARGET_SIG_IGN;
|
||||
|
@ -1664,6 +1664,8 @@ static void handle_query_supported(GArray *params, void *user_ctx)
|
||||
g_string_append(gdbserver_state.str_buf, ";qXfer:auxv:read+");
|
||||
}
|
||||
g_string_append(gdbserver_state.str_buf, ";QCatchSyscalls+");
|
||||
|
||||
g_string_append(gdbserver_state.str_buf, ";qXfer:siginfo:read+");
|
||||
#endif
|
||||
g_string_append(gdbserver_state.str_buf, ";qXfer:exec-file:read+");
|
||||
#endif
|
||||
@ -1818,6 +1820,12 @@ static const GdbCmdParseEntry gdb_gen_query_table[] = {
|
||||
.cmd_startswith = 1,
|
||||
.schema = "l,l0"
|
||||
},
|
||||
{
|
||||
.handler = gdb_handle_query_xfer_siginfo,
|
||||
.cmd = "Xfer:siginfo:read::",
|
||||
.cmd_startswith = 1,
|
||||
.schema = "l,l0"
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.handler = gdb_handle_query_xfer_exec_file,
|
||||
|
@ -190,6 +190,7 @@ typedef union GdbCmdVariant {
|
||||
void gdb_handle_query_rcmd(GArray *params, void *user_ctx); /* softmmu */
|
||||
void gdb_handle_query_offsets(GArray *params, void *user_ctx); /* user */
|
||||
void gdb_handle_query_xfer_auxv(GArray *params, void *user_ctx); /*user */
|
||||
void gdb_handle_query_xfer_siginfo(GArray *params, void *user_ctx); /*user */
|
||||
void gdb_handle_v_file_open(GArray *params, void *user_ctx); /* user */
|
||||
void gdb_handle_v_file_close(GArray *params, void *user_ctx); /* user */
|
||||
void gdb_handle_v_file_pread(GArray *params, void *user_ctx); /* user */
|
||||
|
@ -95,6 +95,8 @@ typedef struct {
|
||||
enum GDBForkState fork_state;
|
||||
int fork_sockets[2];
|
||||
pid_t fork_peer_pid, fork_peer_tid;
|
||||
uint8_t siginfo[MAX_SIGINFO_LENGTH];
|
||||
unsigned long siginfo_len;
|
||||
} GDBUserState;
|
||||
|
||||
static GDBUserState gdbserver_user_state;
|
||||
@ -190,7 +192,8 @@ void gdb_qemu_exit(int code)
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int gdb_handlesig_reason(CPUState *cpu, int sig, const char *reason)
|
||||
int gdb_handlesig(CPUState *cpu, int sig, const char *reason, void *siginfo,
|
||||
int siginfo_len)
|
||||
{
|
||||
char buf[256];
|
||||
int n;
|
||||
@ -199,6 +202,18 @@ int gdb_handlesig_reason(CPUState *cpu, int sig, const char *reason)
|
||||
return sig;
|
||||
}
|
||||
|
||||
if (siginfo) {
|
||||
/*
|
||||
* Save target-specific siginfo.
|
||||
*
|
||||
* siginfo size, i.e. siginfo_len, is asserted at compile-time to fit in
|
||||
* gdbserver_user_state.siginfo, usually in the source file calling
|
||||
* gdb_handlesig. See, for instance, {linux,bsd}-user/signal.c.
|
||||
*/
|
||||
memcpy(gdbserver_user_state.siginfo, siginfo, siginfo_len);
|
||||
gdbserver_user_state.siginfo_len = siginfo_len;
|
||||
}
|
||||
|
||||
/* disable single step if it was enabled */
|
||||
cpu_single_step(cpu, 0);
|
||||
tb_flush(cpu);
|
||||
@ -502,6 +517,7 @@ void gdbserver_fork_end(CPUState *cpu, pid_t pid)
|
||||
switch (gdbserver_user_state.fork_state) {
|
||||
case GDB_FORK_ENABLED:
|
||||
if (gdbserver_user_state.running_state) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
QEMU_FALLTHROUGH;
|
||||
@ -527,7 +543,6 @@ void gdbserver_fork_end(CPUState *cpu, pid_t pid)
|
||||
gdbserver_user_state.fork_state = GDB_FORK_ACTIVE;
|
||||
break;
|
||||
case GDB_FORK_ENABLE:
|
||||
close(fd);
|
||||
gdbserver_user_state.fork_state = GDB_FORK_ENABLED;
|
||||
break;
|
||||
case GDB_FORK_DISABLE:
|
||||
@ -542,7 +557,6 @@ void gdbserver_fork_end(CPUState *cpu, pid_t pid)
|
||||
if (write(fd, &b, 1) != 1) {
|
||||
goto fail;
|
||||
}
|
||||
close(fd);
|
||||
gdbserver_user_state.fork_state = GDB_FORK_ENABLED;
|
||||
break;
|
||||
case GDB_FORK_DISABLING:
|
||||
@ -746,7 +760,7 @@ void gdb_breakpoint_remove_all(CPUState *cs)
|
||||
void gdb_syscall_handling(const char *syscall_packet)
|
||||
{
|
||||
gdb_put_packet(syscall_packet);
|
||||
gdb_handlesig(gdbserver_state.c_cpu, 0);
|
||||
gdb_handlesig(gdbserver_state.c_cpu, 0, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static bool should_catch_syscall(int num)
|
||||
@ -764,7 +778,7 @@ 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);
|
||||
gdb_handlesig(cs, gdb_target_sigtrap(), reason, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -772,7 +786,7 @@ 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);
|
||||
gdb_handlesig(cs, gdb_target_sigtrap(), reason, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -837,3 +851,26 @@ void gdb_handle_set_catch_syscalls(GArray *params, void *user_ctx)
|
||||
err:
|
||||
gdb_put_packet("E00");
|
||||
}
|
||||
|
||||
void gdb_handle_query_xfer_siginfo(GArray *params, void *user_ctx)
|
||||
{
|
||||
unsigned long offset, len;
|
||||
uint8_t *siginfo_offset;
|
||||
|
||||
offset = get_param(params, 0)->val_ul;
|
||||
len = get_param(params, 1)->val_ul;
|
||||
|
||||
if (offset + len > gdbserver_user_state.siginfo_len) {
|
||||
/* Invalid offset and/or requested length. */
|
||||
gdb_put_packet("E01");
|
||||
return;
|
||||
}
|
||||
|
||||
siginfo_offset = (uint8_t *)gdbserver_user_state.siginfo + offset;
|
||||
|
||||
/* Reply */
|
||||
g_string_assign(gdbserver_state.str_buf, "l");
|
||||
gdb_memtox(gdbserver_state.str_buf, (const char *)siginfo_offset, len);
|
||||
gdb_put_packet_binary(gdbserver_state.str_buf->str,
|
||||
gdbserver_state.str_buf->len, true);
|
||||
}
|
||||
|
@ -9,11 +9,15 @@
|
||||
#ifndef GDBSTUB_USER_H
|
||||
#define GDBSTUB_USER_H
|
||||
|
||||
#define MAX_SIGINFO_LENGTH 128
|
||||
|
||||
/**
|
||||
* gdb_handlesig_reason() - yield control to gdb
|
||||
* gdb_handlesig() - 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
|
||||
* @siginfo: target-specific siginfo struct
|
||||
* @siginfo_len: target-specific siginfo struct length
|
||||
*
|
||||
* 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
|
||||
@ -25,18 +29,7 @@
|
||||
* or 0 if no signal should be delivered, ie the signal that caused
|
||||
* us to stop should be ignored.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
int gdb_handlesig(CPUState *, int, const char *, void *, int);
|
||||
|
||||
/**
|
||||
* gdb_signalled() - inform remote gdb of sig exit
|
||||
|
@ -670,7 +670,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
|
||||
aarch64_set_svcr(env, 0, R_SVCR_SM_MASK | R_SVCR_ZA_MASK);
|
||||
|
||||
if (info) {
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
|
||||
env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
goto give_sigsegv;
|
||||
}
|
||||
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
|
||||
__put_user(0, &frame->uc.tuc_flags);
|
||||
__put_user(0, &frame->uc.tuc_link);
|
||||
|
@ -357,7 +357,7 @@ void setup_rt_frame(int usig, struct target_sigaction *ka,
|
||||
|
||||
info_addr = frame_addr + offsetof(struct rt_sigframe, info);
|
||||
uc_addr = frame_addr + offsetof(struct rt_sigframe, sig.uc);
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
|
||||
setup_sigframe(&frame->sig.uc, set, env);
|
||||
|
||||
|
@ -162,7 +162,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
}
|
||||
|
||||
setup_ucontext(&frame->uc, env, set);
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
/*
|
||||
* The on-stack signal trampoline is no longer executed;
|
||||
* however, the libgcc signal frame unwinding code checks
|
||||
|
@ -127,7 +127,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
goto give_sigsegv;
|
||||
}
|
||||
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
frame->uc.tuc_flags = 0;
|
||||
frame->uc.tuc_link = 0;
|
||||
|
||||
|
@ -430,7 +430,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
|
||||
setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
|
||||
frame_addr + offsetof(struct sigframe, fpstate));
|
||||
|
||||
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
|
||||
for (i = 1; i < TARGET_NSIG_WORDS; i++) {
|
||||
__put_user(set->sig[i], &frame->extramask[i - 1]);
|
||||
}
|
||||
|
||||
@ -490,7 +490,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
__put_user(addr, &frame->puc);
|
||||
#endif
|
||||
if (ka->sa_flags & TARGET_SA_SIGINFO) {
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
}
|
||||
|
||||
/* Create the ucontext. */
|
||||
@ -504,7 +504,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
|
||||
set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
|
||||
|
||||
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
|
||||
}
|
||||
|
||||
|
@ -376,7 +376,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr);
|
||||
}
|
||||
|
||||
tswap_siginfo(&frame->rs_info, info);
|
||||
frame->rs_info = *info;
|
||||
|
||||
__put_user(0, &frame->rs_uc.tuc_flags);
|
||||
__put_user(0, &frame->rs_uc.tuc_link);
|
||||
|
@ -295,7 +295,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
|
||||
__put_user(uc_addr, &frame->puc);
|
||||
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
|
||||
/* Create the ucontext */
|
||||
|
||||
@ -307,7 +307,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
|
||||
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
|
||||
}
|
||||
|
||||
|
@ -1018,7 +1018,7 @@ int main(int argc, char **argv, char **envp)
|
||||
gdbstub);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
gdb_handlesig(cpu, 0);
|
||||
gdb_handlesig(cpu, 0, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SEMIHOSTING
|
||||
|
@ -147,7 +147,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
return;
|
||||
}
|
||||
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
|
||||
__put_user(0, &frame->uc.tuc_flags);
|
||||
__put_user(0, &frame->uc.tuc_link);
|
||||
|
@ -303,7 +303,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
goto give_sigsegv;
|
||||
}
|
||||
|
||||
tswap_siginfo(&frame->rs_info, info);
|
||||
frame->rs_info = *info;
|
||||
|
||||
__put_user(0, &frame->rs_uc.tuc_flags);
|
||||
__put_user(0, &frame->rs_uc.tuc_link);
|
||||
@ -311,7 +311,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
|
||||
setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
|
||||
|
||||
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
__put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
return;
|
||||
}
|
||||
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
|
||||
/* Create the ucontext. */
|
||||
__put_user(0, &frame->uc.tuc_flags);
|
||||
|
@ -103,7 +103,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
}
|
||||
|
||||
if (ka->sa_flags & SA_SIGINFO) {
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
}
|
||||
|
||||
__put_user(0, &frame->uc.tuc_flags);
|
||||
|
@ -493,7 +493,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
|
||||
goto sigsegv;
|
||||
|
||||
tswap_siginfo(&rt_sf->info, info);
|
||||
rt_sf->info = *info;
|
||||
|
||||
__put_user(0, &rt_sf->uc.tuc_flags);
|
||||
__put_user(0, &rt_sf->uc.tuc_link);
|
||||
@ -502,7 +502,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
__put_user(h2g (&rt_sf->uc.tuc_mcontext),
|
||||
&rt_sf->uc.tuc_regs);
|
||||
#endif
|
||||
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
__put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
}
|
||||
|
||||
setup_ucontext(&frame->uc, env, set);
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
|
||||
env->pc = ka->_sa_handler;
|
||||
env->gpr[xSP] = frame_addr;
|
||||
|
@ -267,7 +267,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
}
|
||||
|
||||
/* Create siginfo on the signal stack. */
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
|
||||
/* Create ucontext on the signal stack. */
|
||||
uc_flags = 0;
|
||||
|
@ -233,7 +233,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
goto give_sigsegv;
|
||||
}
|
||||
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
|
||||
/* Create the ucontext. */
|
||||
__put_user(0, &frame->uc.tuc_flags);
|
||||
|
@ -43,8 +43,6 @@ void host_to_target_sigset_internal(target_sigset_t *d,
|
||||
const sigset_t *s);
|
||||
void target_to_host_sigset_internal(sigset_t *d,
|
||||
const target_sigset_t *s);
|
||||
void tswap_siginfo(target_siginfo_t *tinfo,
|
||||
const target_siginfo_t *info);
|
||||
void set_sigmask(const sigset_t *set);
|
||||
void force_sig(int sig);
|
||||
void force_sigsegv(int oldsig);
|
||||
|
@ -34,6 +34,9 @@
|
||||
#include "user/safe-syscall.h"
|
||||
#include "tcg/tcg.h"
|
||||
|
||||
/* target_siginfo_t must fit in gdbstub's siginfo save area. */
|
||||
QEMU_BUILD_BUG_ON(sizeof(target_siginfo_t) > MAX_SIGINFO_LENGTH);
|
||||
|
||||
static struct target_sigaction sigact_table[TARGET_NSIG];
|
||||
|
||||
static void host_signal_handler(int host_signum, siginfo_t *info,
|
||||
@ -409,8 +412,8 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
|
||||
tinfo->si_code = deposit32(si_code, 16, 16, si_type);
|
||||
}
|
||||
|
||||
void tswap_siginfo(target_siginfo_t *tinfo,
|
||||
const target_siginfo_t *info)
|
||||
static void tswap_siginfo(target_siginfo_t *tinfo,
|
||||
const target_siginfo_t *info)
|
||||
{
|
||||
int si_type = extract32(info->si_code, 16, 16);
|
||||
int si_code = sextract32(info->si_code, 0, 16);
|
||||
@ -1178,7 +1181,13 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
|
||||
/* dequeue signal */
|
||||
k->pending = 0;
|
||||
|
||||
sig = gdb_handlesig(cpu, sig);
|
||||
/*
|
||||
* Writes out siginfo values byteswapped, accordingly to the target. It also
|
||||
* cleans the si_type from si_code making it correct for the target.
|
||||
*/
|
||||
tswap_siginfo(&k->info, &k->info);
|
||||
|
||||
sig = gdb_handlesig(cpu, sig, NULL, &k->info, sizeof(k->info));
|
||||
if (!sig) {
|
||||
sa = NULL;
|
||||
handler = TARGET_SIG_IGN;
|
||||
|
@ -333,7 +333,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
|
||||
__put_user(0, &sf->rwin_save); /* TODO: save_rwin_state */
|
||||
|
||||
tswap_siginfo(&sf->info, info);
|
||||
sf->info = *info;
|
||||
tswap_sigset(&sf->mask, set);
|
||||
target_save_altstack(&sf->stack, env);
|
||||
|
||||
|
@ -184,7 +184,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
}
|
||||
|
||||
if (ka->sa_flags & SA_SIGINFO) {
|
||||
tswap_siginfo(&frame->info, info);
|
||||
frame->info = *info;
|
||||
}
|
||||
|
||||
__put_user(0, &frame->uc.tuc_flags);
|
||||
|
@ -71,6 +71,13 @@ run-gdbstub-qxfer-auxv-read: sha1
|
||||
--bin $< --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \
|
||||
basic gdbstub qXfer:auxv:read support)
|
||||
|
||||
run-gdbstub-qxfer-siginfo-read: segfault
|
||||
$(call run-test, $@, $(GDB_SCRIPT) \
|
||||
--gdb $(GDB) \
|
||||
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
|
||||
--bin "$< -s" --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-siginfo-read.py, \
|
||||
basic gdbstub qXfer:siginfo:read support)
|
||||
|
||||
run-gdbstub-proc-mappings: sha1
|
||||
$(call run-test, $@, $(GDB_SCRIPT) \
|
||||
--gdb $(GDB) \
|
||||
@ -128,7 +135,8 @@ 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-catch-syscalls run-gdbstub-follow-fork-mode-child \
|
||||
run-gdbstub-follow-fork-mode-parent
|
||||
run-gdbstub-follow-fork-mode-parent \
|
||||
run-gdbstub-qxfer-siginfo-read
|
||||
|
||||
# ARM Compatible Semi Hosting Tests
|
||||
#
|
||||
|
26
tests/tcg/multiarch/gdbstub/test-qxfer-siginfo-read.py
Normal file
26
tests/tcg/multiarch/gdbstub/test-qxfer-siginfo-read.py
Normal file
@ -0,0 +1,26 @@
|
||||
from __future__ import print_function
|
||||
#
|
||||
# Test gdbstub Xfer:siginfo:read stub.
|
||||
#
|
||||
# The test runs a binary that causes a SIGSEGV and then looks for additional
|
||||
# info about the signal through printing GDB's '$_siginfo' special variable,
|
||||
# which sends a Xfer:siginfo:read query to the gdbstub.
|
||||
#
|
||||
# The binary causes a SIGSEGV at dereferencing a pointer with value 0xdeadbeef,
|
||||
# so the test looks for and checks if this address is correctly reported by the
|
||||
# gdbstub.
|
||||
#
|
||||
# This is launched via tests/guest-debug/run-test.py
|
||||
#
|
||||
|
||||
import gdb
|
||||
from test_gdbstub import main, report
|
||||
|
||||
def run_test():
|
||||
"Run through the test"
|
||||
|
||||
gdb.execute("continue", False, True)
|
||||
resp = gdb.execute("print/x $_siginfo", False, True)
|
||||
report(resp.find("si_addr = 0xdeadbeef"), "Found fault address.")
|
||||
|
||||
main(run_test)
|
14
tests/tcg/multiarch/segfault.c
Normal file
14
tests/tcg/multiarch/segfault.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Cause a segfault for testing purposes. */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int *ptr = (void *)0xdeadbeef;
|
||||
|
||||
if (argc == 2 && strcmp(argv[1], "-s") == 0) {
|
||||
/* Cause segfault. */
|
||||
printf("%d\n", *ptr);
|
||||
}
|
||||
}
|
@ -606,7 +606,7 @@ def parse_args(vmcls):
|
||||
parser.add_argument("--build-qemu",
|
||||
help="build QEMU from source in guest")
|
||||
parser.add_argument("--build-target",
|
||||
help="QEMU build target", default="check")
|
||||
help="QEMU build target", default="all check")
|
||||
parser.add_argument("--build-path", default=None,
|
||||
help="Path of build directory, "\
|
||||
"for using build tree QEMU binary. ")
|
||||
|
Loading…
Reference in New Issue
Block a user