Skip to content

Commit

Permalink
Merge tag 'pull-maintainer-final-130324-1' of https://gitlab.com/stsq…
Browse files Browse the repository at this point in the history
…uad/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>
  • Loading branch information
pm215 committed Mar 13, 2024
2 parents 6fc6931 + 6971998 commit ba49d76
Show file tree
Hide file tree
Showing 31 changed files with 149 additions and 52 deletions.
2 changes: 1 addition & 1 deletion bsd-user/main.c
Expand Up @@ -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 */
Expand Down
5 changes: 4 additions & 1 deletion bsd-user/signal.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions gdbstub/gdbstub.c
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions gdbstub/internals.h
Expand Up @@ -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 */
Expand Down
49 changes: 43 additions & 6 deletions gdbstub/user.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -764,15 +778,15 @@ 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);
}
}

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

Expand Down Expand Up @@ -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);
}
19 changes: 6 additions & 13 deletions include/gdbstub/user.h
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion linux-user/aarch64/signal.c
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion linux-user/alpha/signal.c
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion linux-user/arm/signal.c
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion linux-user/hexagon/signal.c
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion linux-user/hppa/signal.c
Expand Up @@ -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;

Expand Down
6 changes: 3 additions & 3 deletions linux-user/i386/signal.c
Expand Up @@ -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]);
}

Expand Down Expand Up @@ -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. */
Expand All @@ -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]);
}

Expand Down
2 changes: 1 addition & 1 deletion linux-user/loongarch64/signal.c
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions linux-user/m68k/signal.c
Expand Up @@ -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 */

Expand All @@ -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]);
}

Expand Down
2 changes: 1 addition & 1 deletion linux-user/main.c
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion linux-user/microblaze/signal.c
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions linux-user/mips/signal.c
Expand Up @@ -303,15 +303,15 @@ 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);
target_save_altstack(&frame->rs_uc.tuc_stack, env);

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

Expand Down
2 changes: 1 addition & 1 deletion linux-user/nios2/signal.c
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion linux-user/openrisc/signal.c
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions linux-user/ppc/signal.c
Expand Up @@ -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);
Expand All @@ -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]);
}

Expand Down
2 changes: 1 addition & 1 deletion linux-user/riscv/signal.c
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion linux-user/s390x/signal.c
Expand Up @@ -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;
Expand Down

0 comments on commit ba49d76

Please sign in to comment.