On Sun, 5 Jul 2026 at 23:44, Gilles Grimaud
<[email protected]> wrote:
>
> While working on Raspberry Pi Pico/RP2040 support, I noticed that Pico SDK
> programs deliberately execute BKPT from _exit(). On real hardware this is
> useful when a debug probe is attached: returning from main() stops the
> debugger at the program exit point.
>
> Under QEMU this currently does not behave like the debug-probe case. For
> M-profile guests, the BKPT instruction is routed through the architectural
> guest debug exception path. Without halting debug, that path should remain a
> guest-visible DebugMonitor exception when DebugMonitor is enabled, or escalate
> towards HardFault otherwise. This patch deliberately leaves that no-debugger
> architectural path unchanged.
>
> The problem addressed here is the case where GDB is connected to QEMU's
> gdbstub. In that situation, firmware that uses BKPT as a debugger stop point
> should stop in the attached debugger. Instead, the M-profile guest currently
> continues down the guest exception path and may end in HardFault/lockup rather
> than reporting a clean trap to GDB.
>
> This is not specific to the RP2040 machine model. It is a generic
> Cortex-M/gdbstub interaction: firmware that uses BKPT as a debugger stop point
> should be reported to the attached debugger, while keeping the guest
> architectural exception path when no debugger is attached.
>
> Expose a small gdbstub helper to test whether a CPU is visible to an attached
> debugger. When an M-profile BKPT instruction is executed with such a debugger
> attached, leave the translated block with EXCP_DEBUG so the existing gdbstub
> stop path reports a trap to GDB.
>
> Signed-off-by: Gilles Grimaud <[email protected]>
> ---
>  gdbstub/gdbstub.c      | 13 ++++++++++++-
>  include/exec/gdbstub.h |  6 ++++++
>  target/arm/tcg/debug.c |  9 +++++++++
>  3 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
> index c3c944e965..9f259fc005 100644
> --- a/gdbstub/gdbstub.c
> +++ b/gdbstub/gdbstub.c
> @@ -237,6 +237,18 @@ static GDBProcess *gdb_get_cpu_process(CPUState *cpu)
>      return gdb_get_process(gdb_get_cpu_pid(cpu));
>  }
>
> +bool gdb_cpu_is_attached(CPUState *cpu)
> +{
> +    GDBProcess *process;
> +
> +    if (!gdbserver_state.init || !cpu) {
> +        return false;
> +    }
> +
> +    process = gdb_get_cpu_process(cpu);
> +    return process && process->attached;
> +}

No other architecture, CPU or board in QEMU needs to do this,
so my instinct is to say that M-profile should not be special here.
Richard, Alex: how do we usually handle breakpoint insns for the
gdbstub ?

-- PMM

Reply via email to