gdbstub: split out softmmu/user specifics for syscall handling

Most of the syscall code is config agnostic aside from the size of
target_ulong. In preparation for the next patch move the final bits
of specialisation into the appropriate user and softmmu helpers.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230302190846.2593720-26-alex.bennee@linaro.org>
Message-Id: <20230303025805.625589-26-richard.henderson@linaro.org>
This commit is contained in:
Alex Bennée 2023-03-02 18:58:01 -08:00
parent 4692a86f1c
commit 131f387d74
4 changed files with 34 additions and 24 deletions

View file

@ -195,6 +195,9 @@ bool gdb_handled_syscall(void);
void gdb_disable_syscalls(void);
void gdb_syscall_reset(void);
/* user/softmmu specific syscall handling */
void gdb_syscall_handling(const char *syscall_packet);
/*
* Break/Watch point support - there is an implementation for softmmu
* and user mode.

View file

@ -103,6 +103,20 @@ static void gdb_chr_event(void *opaque, QEMUChrEvent event)
}
}
/*
* In softmmu mode we stop the VM and wait to send the syscall packet
* until notification that the CPU has stopped. This must be done
* because if the packet is sent now the reply from the syscall
* request could be received while the CPU is still in the running
* state, which can cause packets to be dropped and state transition
* 'T' packets to be sent while the syscall is still being processed.
*/
void gdb_syscall_handling(const char *syscall_packet)
{
vm_stop(RUN_STATE_DEBUG);
qemu_cpu_kick(gdbserver_state.c_cpu);
}
static void gdb_vm_state_change(void *opaque, bool running, RunState state)
{
CPUState *cpu = gdbserver_state.c_cpu;

View file

@ -105,9 +105,7 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
}
gdbserver_syscall_state.current_syscall_cb = cb;
#ifndef CONFIG_USER_ONLY
vm_stop(RUN_STATE_DEBUG);
#endif
p = &gdbserver_syscall_state.syscall_buf[0];
p_end = &gdbserver_syscall_state.syscall_buf[sizeof(gdbserver_syscall_state.syscall_buf)];
*(p++) = 'F';
@ -142,27 +140,8 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
}
}
*p = 0;
#ifdef CONFIG_USER_ONLY
gdb_put_packet(gdbserver_syscall_state.syscall_buf);
/*
* Return control to gdb for it to process the syscall request.
* Since the protocol requires that gdb hands control back to us
* using a "here are the results" F packet, we don't need to check
* gdb_handlesig's return value (which is the signal to deliver if
* execution was resumed via a continue packet).
*/
gdb_handlesig(gdbserver_state.c_cpu, 0);
#else
/*
* In this case wait to send the syscall packet until notification that
* the CPU has stopped. This must be done because if the packet is sent
* now the reply from the syscall request could be received while the CPU
* is still in the running state, which can cause packets to be dropped
* and state transition 'T' packets to be sent while the syscall is still
* being processed.
*/
qemu_cpu_kick(gdbserver_state.c_cpu);
#endif
gdb_syscall_handling(gdbserver_syscall_state.syscall_buf);
}
void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)

View file

@ -472,3 +472,17 @@ void gdb_breakpoint_remove_all(CPUState *cs)
{
cpu_breakpoint_remove_all(cs, BP_GDB);
}
/*
* For user-mode syscall support we send the system call immediately
* and then return control to gdb for it to process the syscall request.
* Since the protocol requires that gdb hands control back to us
* using a "here are the results" F packet, we don't need to check
* gdb_handlesig's return value (which is the signal to deliver if
* execution was resumed via a continue packet).
*/
void gdb_syscall_handling(const char *syscall_packet)
{
gdb_put_packet(syscall_packet);
gdb_handlesig(gdbserver_state.c_cpu, 0);
}