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:
Peter Maydell 2024-03-13 15:12:14 +00:00
commit ba49d760eb
31 changed files with 149 additions and 52 deletions

View File

@ -606,7 +606,7 @@ int main(int argc, char **argv)
if (gdbstub) { if (gdbstub) {
gdbserver_start(gdbstub); gdbserver_start(gdbstub);
gdb_handlesig(cpu, 0); gdb_handlesig(cpu, 0, NULL, NULL, 0);
} }
cpu_loop(env); cpu_loop(env);
/* never exits */ /* never exits */

View File

@ -27,6 +27,9 @@
#include "hw/core/tcg-cpu-ops.h" #include "hw/core/tcg-cpu-ops.h"
#include "host-signal.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 struct target_sigaction sigact_table[TARGET_NSIG];
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc); static void host_signal_handler(int host_sig, siginfo_t *info, void *puc);
static void target_to_host_sigset_internal(sigset_t *d, 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; k->pending = 0;
sig = gdb_handlesig(cpu, sig); sig = gdb_handlesig(cpu, sig, NULL, &k->info, sizeof(k->info));
if (!sig) { if (!sig) {
sa = NULL; sa = NULL;
handler = TARGET_SIG_IGN; handler = TARGET_SIG_IGN;

View File

@ -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, ";qXfer:auxv:read+");
} }
g_string_append(gdbserver_state.str_buf, ";QCatchSyscalls+"); g_string_append(gdbserver_state.str_buf, ";QCatchSyscalls+");
g_string_append(gdbserver_state.str_buf, ";qXfer:siginfo:read+");
#endif #endif
g_string_append(gdbserver_state.str_buf, ";qXfer:exec-file:read+"); g_string_append(gdbserver_state.str_buf, ";qXfer:exec-file:read+");
#endif #endif
@ -1818,6 +1820,12 @@ static const GdbCmdParseEntry gdb_gen_query_table[] = {
.cmd_startswith = 1, .cmd_startswith = 1,
.schema = "l,l0" .schema = "l,l0"
}, },
{
.handler = gdb_handle_query_xfer_siginfo,
.cmd = "Xfer:siginfo:read::",
.cmd_startswith = 1,
.schema = "l,l0"
},
#endif #endif
{ {
.handler = gdb_handle_query_xfer_exec_file, .handler = gdb_handle_query_xfer_exec_file,

View File

@ -190,6 +190,7 @@ typedef union GdbCmdVariant {
void gdb_handle_query_rcmd(GArray *params, void *user_ctx); /* softmmu */ 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_offsets(GArray *params, void *user_ctx); /* user */
void gdb_handle_query_xfer_auxv(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_open(GArray *params, void *user_ctx); /* user */
void gdb_handle_v_file_close(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 */ void gdb_handle_v_file_pread(GArray *params, void *user_ctx); /* user */

View File

@ -95,6 +95,8 @@ typedef struct {
enum GDBForkState fork_state; enum GDBForkState fork_state;
int fork_sockets[2]; int fork_sockets[2];
pid_t fork_peer_pid, fork_peer_tid; pid_t fork_peer_pid, fork_peer_tid;
uint8_t siginfo[MAX_SIGINFO_LENGTH];
unsigned long siginfo_len;
} GDBUserState; } GDBUserState;
static GDBUserState gdbserver_user_state; static GDBUserState gdbserver_user_state;
@ -190,7 +192,8 @@ void gdb_qemu_exit(int code)
exit(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]; char buf[256];
int n; int n;
@ -199,6 +202,18 @@ int gdb_handlesig_reason(CPUState *cpu, int sig, const char *reason)
return sig; 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 */ /* disable single step if it was enabled */
cpu_single_step(cpu, 0); cpu_single_step(cpu, 0);
tb_flush(cpu); tb_flush(cpu);
@ -502,6 +517,7 @@ void gdbserver_fork_end(CPUState *cpu, pid_t pid)
switch (gdbserver_user_state.fork_state) { switch (gdbserver_user_state.fork_state) {
case GDB_FORK_ENABLED: case GDB_FORK_ENABLED:
if (gdbserver_user_state.running_state) { if (gdbserver_user_state.running_state) {
close(fd);
return; return;
} }
QEMU_FALLTHROUGH; QEMU_FALLTHROUGH;
@ -527,7 +543,6 @@ void gdbserver_fork_end(CPUState *cpu, pid_t pid)
gdbserver_user_state.fork_state = GDB_FORK_ACTIVE; gdbserver_user_state.fork_state = GDB_FORK_ACTIVE;
break; break;
case GDB_FORK_ENABLE: case GDB_FORK_ENABLE:
close(fd);
gdbserver_user_state.fork_state = GDB_FORK_ENABLED; gdbserver_user_state.fork_state = GDB_FORK_ENABLED;
break; break;
case GDB_FORK_DISABLE: case GDB_FORK_DISABLE:
@ -542,7 +557,6 @@ void gdbserver_fork_end(CPUState *cpu, pid_t pid)
if (write(fd, &b, 1) != 1) { if (write(fd, &b, 1) != 1) {
goto fail; goto fail;
} }
close(fd);
gdbserver_user_state.fork_state = GDB_FORK_ENABLED; gdbserver_user_state.fork_state = GDB_FORK_ENABLED;
break; break;
case GDB_FORK_DISABLING: case GDB_FORK_DISABLING:
@ -746,7 +760,7 @@ void gdb_breakpoint_remove_all(CPUState *cs)
void gdb_syscall_handling(const char *syscall_packet) void gdb_syscall_handling(const char *syscall_packet)
{ {
gdb_put_packet(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) static bool should_catch_syscall(int num)
@ -764,7 +778,7 @@ void gdb_syscall_entry(CPUState *cs, int num)
{ {
if (should_catch_syscall(num)) { if (should_catch_syscall(num)) {
g_autofree char *reason = g_strdup_printf("syscall_entry:%x;", 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)) { if (should_catch_syscall(num)) {
g_autofree char *reason = g_strdup_printf("syscall_return:%x;", 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: err:
gdb_put_packet("E00"); 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);
}

View File

@ -9,11 +9,15 @@
#ifndef GDBSTUB_USER_H #ifndef GDBSTUB_USER_H
#define 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 * @cpu: CPU
* @sig: if non-zero, the signal number which caused us to stop * @sig: if non-zero, the signal number which caused us to stop
* @reason: stop reason for stop reply packet or NULL * @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 * 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 * 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 * or 0 if no signal should be delivered, ie the signal that caused
* us to stop should be ignored. * us to stop should be ignored.
*/ */
int gdb_handlesig_reason(CPUState *, int, const char *); int gdb_handlesig(CPUState *, int, const char *, void *, int);
/**
* 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 * gdb_signalled() - inform remote gdb of sig exit

View File

@ -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); aarch64_set_svcr(env, 0, R_SVCR_SM_MASK | R_SVCR_ZA_MASK);
if (info) { if (info) {
tswap_siginfo(&frame->info, info); frame->info = *info;
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info); env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc); env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
} }

View File

@ -173,7 +173,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
goto give_sigsegv; goto give_sigsegv;
} }
tswap_siginfo(&frame->info, info); frame->info = *info;
__put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_flags);
__put_user(0, &frame->uc.tuc_link); __put_user(0, &frame->uc.tuc_link);

View File

@ -357,7 +357,7 @@ void setup_rt_frame(int usig, struct target_sigaction *ka,
info_addr = frame_addr + offsetof(struct rt_sigframe, info); info_addr = frame_addr + offsetof(struct rt_sigframe, info);
uc_addr = frame_addr + offsetof(struct rt_sigframe, sig.uc); 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); setup_sigframe(&frame->sig.uc, set, env);

View File

@ -162,7 +162,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
} }
setup_ucontext(&frame->uc, env, set); setup_ucontext(&frame->uc, env, set);
tswap_siginfo(&frame->info, info); frame->info = *info;
/* /*
* The on-stack signal trampoline is no longer executed; * The on-stack signal trampoline is no longer executed;
* however, the libgcc signal frame unwinding code checks * however, the libgcc signal frame unwinding code checks

View File

@ -127,7 +127,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
goto give_sigsegv; goto give_sigsegv;
} }
tswap_siginfo(&frame->info, info); frame->info = *info;
frame->uc.tuc_flags = 0; frame->uc.tuc_flags = 0;
frame->uc.tuc_link = 0; frame->uc.tuc_link = 0;

View File

@ -430,7 +430,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
frame_addr + offsetof(struct sigframe, fpstate)); 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]); __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); __put_user(addr, &frame->puc);
#endif #endif
if (ka->sa_flags & TARGET_SA_SIGINFO) { if (ka->sa_flags & TARGET_SA_SIGINFO) {
tswap_siginfo(&frame->info, info); frame->info = *info;
} }
/* Create the ucontext. */ /* 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, setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate)); 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]); __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
} }

View File

@ -376,7 +376,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr); 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_flags);
__put_user(0, &frame->rs_uc.tuc_link); __put_user(0, &frame->rs_uc.tuc_link);

View File

@ -295,7 +295,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
__put_user(uc_addr, &frame->puc); __put_user(uc_addr, &frame->puc);
tswap_siginfo(&frame->info, info); frame->info = *info;
/* Create the ucontext */ /* Create the ucontext */
@ -307,7 +307,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
if (err) if (err)
goto give_sigsegv; 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]); __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
} }

View File

@ -1018,7 +1018,7 @@ int main(int argc, char **argv, char **envp)
gdbstub); gdbstub);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
gdb_handlesig(cpu, 0); gdb_handlesig(cpu, 0, NULL, NULL, 0);
} }
#ifdef CONFIG_SEMIHOSTING #ifdef CONFIG_SEMIHOSTING

View File

@ -147,7 +147,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
return; return;
} }
tswap_siginfo(&frame->info, info); frame->info = *info;
__put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_flags);
__put_user(0, &frame->uc.tuc_link); __put_user(0, &frame->uc.tuc_link);

View File

@ -303,7 +303,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
goto give_sigsegv; 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_flags);
__put_user(0, &frame->rs_uc.tuc_link); __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); 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]); __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
} }

View File

@ -157,7 +157,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
return; return;
} }
tswap_siginfo(&frame->info, info); frame->info = *info;
/* Create the ucontext. */ /* Create the ucontext. */
__put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_flags);

View File

@ -103,7 +103,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
} }
if (ka->sa_flags & SA_SIGINFO) { if (ka->sa_flags & SA_SIGINFO) {
tswap_siginfo(&frame->info, info); frame->info = *info;
} }
__put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_flags);

View File

@ -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)) if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
goto sigsegv; 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_flags);
__put_user(0, &rt_sf->uc.tuc_link); __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), __put_user(h2g (&rt_sf->uc.tuc_mcontext),
&rt_sf->uc.tuc_regs); &rt_sf->uc.tuc_regs);
#endif #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]); __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
} }

View File

@ -125,7 +125,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
} }
setup_ucontext(&frame->uc, env, set); setup_ucontext(&frame->uc, env, set);
tswap_siginfo(&frame->info, info); frame->info = *info;
env->pc = ka->_sa_handler; env->pc = ka->_sa_handler;
env->gpr[xSP] = frame_addr; env->gpr[xSP] = frame_addr;

View File

@ -267,7 +267,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
} }
/* Create siginfo on the signal stack. */ /* Create siginfo on the signal stack. */
tswap_siginfo(&frame->info, info); frame->info = *info;
/* Create ucontext on the signal stack. */ /* Create ucontext on the signal stack. */
uc_flags = 0; uc_flags = 0;

View File

@ -233,7 +233,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
goto give_sigsegv; goto give_sigsegv;
} }
tswap_siginfo(&frame->info, info); frame->info = *info;
/* Create the ucontext. */ /* Create the ucontext. */
__put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_flags);

View File

@ -43,8 +43,6 @@ void host_to_target_sigset_internal(target_sigset_t *d,
const sigset_t *s); const sigset_t *s);
void target_to_host_sigset_internal(sigset_t *d, void target_to_host_sigset_internal(sigset_t *d,
const target_sigset_t *s); 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 set_sigmask(const sigset_t *set);
void force_sig(int sig); void force_sig(int sig);
void force_sigsegv(int oldsig); void force_sigsegv(int oldsig);

View File

@ -34,6 +34,9 @@
#include "user/safe-syscall.h" #include "user/safe-syscall.h"
#include "tcg/tcg.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 struct target_sigaction sigact_table[TARGET_NSIG];
static void host_signal_handler(int host_signum, siginfo_t *info, 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); tinfo->si_code = deposit32(si_code, 16, 16, si_type);
} }
void tswap_siginfo(target_siginfo_t *tinfo, static void tswap_siginfo(target_siginfo_t *tinfo,
const target_siginfo_t *info) const target_siginfo_t *info)
{ {
int si_type = extract32(info->si_code, 16, 16); int si_type = extract32(info->si_code, 16, 16);
int si_code = sextract32(info->si_code, 0, 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 */ /* dequeue signal */
k->pending = 0; 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) { if (!sig) {
sa = NULL; sa = NULL;
handler = TARGET_SIG_IGN; handler = TARGET_SIG_IGN;

View File

@ -333,7 +333,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(0, &sf->rwin_save); /* TODO: save_rwin_state */ __put_user(0, &sf->rwin_save); /* TODO: save_rwin_state */
tswap_siginfo(&sf->info, info); sf->info = *info;
tswap_sigset(&sf->mask, set); tswap_sigset(&sf->mask, set);
target_save_altstack(&sf->stack, env); target_save_altstack(&sf->stack, env);

View File

@ -184,7 +184,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
} }
if (ka->sa_flags & SA_SIGINFO) { if (ka->sa_flags & SA_SIGINFO) {
tswap_siginfo(&frame->info, info); frame->info = *info;
} }
__put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_flags);

View File

@ -71,6 +71,13 @@ run-gdbstub-qxfer-auxv-read: sha1
--bin $< --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \ --bin $< --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \
basic gdbstub qXfer:auxv:read support) 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 run-gdbstub-proc-mappings: sha1
$(call run-test, $@, $(GDB_SCRIPT) \ $(call run-test, $@, $(GDB_SCRIPT) \
--gdb $(GDB) \ --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-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-follow-fork-mode-child \ 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 # ARM Compatible Semi Hosting Tests
# #

View 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)

View 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);
}
}

View File

@ -606,7 +606,7 @@ def parse_args(vmcls):
parser.add_argument("--build-qemu", parser.add_argument("--build-qemu",
help="build QEMU from source in guest") help="build QEMU from source in guest")
parser.add_argument("--build-target", 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, parser.add_argument("--build-path", default=None,
help="Path of build directory, "\ help="Path of build directory, "\
"for using build tree QEMU binary. ") "for using build tree QEMU binary. ")