mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-15 14:13:31 -06:00
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:
parent
4692a86f1c
commit
131f387d74
4 changed files with 34 additions and 24 deletions
|
@ -195,6 +195,9 @@ bool gdb_handled_syscall(void);
|
||||||
void gdb_disable_syscalls(void);
|
void gdb_disable_syscalls(void);
|
||||||
void gdb_syscall_reset(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
|
* Break/Watch point support - there is an implementation for softmmu
|
||||||
* and user mode.
|
* and user mode.
|
||||||
|
|
|
@ -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)
|
static void gdb_vm_state_change(void *opaque, bool running, RunState state)
|
||||||
{
|
{
|
||||||
CPUState *cpu = gdbserver_state.c_cpu;
|
CPUState *cpu = gdbserver_state.c_cpu;
|
||||||
|
|
|
@ -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;
|
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 = &gdbserver_syscall_state.syscall_buf[0];
|
||||||
p_end = &gdbserver_syscall_state.syscall_buf[sizeof(gdbserver_syscall_state.syscall_buf)];
|
p_end = &gdbserver_syscall_state.syscall_buf[sizeof(gdbserver_syscall_state.syscall_buf)];
|
||||||
*(p++) = 'F';
|
*(p++) = 'F';
|
||||||
|
@ -142,27 +140,8 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
#ifdef CONFIG_USER_ONLY
|
|
||||||
gdb_put_packet(gdbserver_syscall_state.syscall_buf);
|
gdb_syscall_handling(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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
|
void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
|
||||||
|
|
|
@ -472,3 +472,17 @@ void gdb_breakpoint_remove_all(CPUState *cs)
|
||||||
{
|
{
|
||||||
cpu_breakpoint_remove_all(cs, BP_GDB);
|
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);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue