--- name: melonds-gdb-debugger description: >- Attach to and debug Nintendo DS homebrew applications running in melonDS using arm-none-eabi-gdb. Use when diagnosing crashes, freezes, infinite loops, data aborts (__arm_excpt_dabt, __excpt_entry), stack corruption, or setting breakpoints and inspecting registers/memory on the ARM9 target. --- # melonDS GDB Debugger Access & Diagnostics This skill provides step-by-step procedures and recipes for debugging Nintendo DS homebrew applications running inside the melonDS emulator using `arm-none-eabi-gdb`. --- ## 1. Prerequisites & Target Setup - **Toolchain GDB:** `${DEVKITPRO}/devkitARM/bin/arm-none-eabi-gdb` (or system `arm-none-eabi-gdb`). - **GDB Server Port:** `localhost:3333` (configured in melonDS when GDB stub is enabled in `melonDS.ini`). - **ELF Symbol File:** [`snakePlus.elf`](../../../snakePlus.elf) or [`build-debug/snakePlus.elf`](../../../build-debug/snakePlus.elf). --- ## 2. Quick Connection & Non-Interactive Inspection To inspect a running or frozen melonDS instance without an interactive prompt: ```bash arm-none-eabi-gdb snakePlus.elf --batch \ -ex "target remote localhost:3333" \ -ex "info registers" \ -ex "detach" \ -ex "quit" ``` To run a diagnosis using the bundled helper script: ```bash bash .agents/skills/melonds-gdb-debugger/scripts/diagnose_melonds.sh snakePlus.elf ``` --- ## 3. Diagnosing Crashes, Freezes & Data Aborts ### 3.1 Exception Vectors in Calico / devkitARM When an unhandled ARM exception occurs, the hardware branches to vector handlers in ROM/BIOS or Calico runtime: - **`0x01ff8560` (`__arm_excpt_dabt`):** Data Abort exception handler. - **`0x01ff8594` (`__excpt_entry`):** Common exception entry point executing an infinite loop (`b .`). - **`0x01ff84ec` (`armWaitForIrq + 4`):** Low-power halt state while waiting for VBlank or Timer IRQ. **Normal running state.** If melonDS freezes, appears unresponsive, or outputs `attempt to restore CPSR under bad mode`, attach GDB and inspect `$pc`. If `$pc` is at `0x01ff8594`, the CPU hit a fatal exception. ### 3.2 Extracting the Faulted Instruction & SPSR In Calico's `__excpt_entry`, the exception frame is pushed to memory at `0x02fffd80`: - **Faulted PC (`lr_abt - 8`):** Stored at `0x02fffd98`. - **Faulted SPSR:** Stored at `0x02fffd90`. Run the following commands in GDB to identify the offending source line: ```gdb (gdb) target remote localhost:3333 (gdb) x/x 0x02fffd98 0x2fffd98: 0x02004284 (gdb) info line *0x02004284 Line 123 of "/path/to/source/game_input.cpp" starts at address 0x2004280 ... ``` ### 3.3 Diagnosing Stack Overflows & Stack Smash In `calico/lib/ds9.ld`, the ARM9 IRQ stack has a total budget of only 256 bytes (`__sp_irq = __sp_usr + 0x100`), growing downward into user stack (`__sp_usr`). - If an interrupt handler (such as `handle_vblank`) calls deep functions or formatting routines (`iprintf`), it clobbers `__sp_usr`. - **Symptom:** In GDB, `$sp` is corrupt or misaligned (e.g. `sp = 0x02fffd8f`, with bit 0 set), or functions crash immediately on register restore / return (`ldmia sp!`). --- ## 4. Interactive Debugging Session 1. **Launch melonDS with ROM:** ```bash melonDS snakePlus.nds ``` 2. **Attach GDB:** ```bash arm-none-eabi-gdb snakePlus.elf -ex "target remote localhost:3333" ``` 3. **Common GDB Actions:** - **Set Breakpoint:** `b update_frame` or `b source/game_input.cpp:50` - **Continue Execution:** `c` - **Step Instruction / Source:** `step` (or `next`) - **Read Memory / Registers:** `info registers`, `x/16xw $sp` - **Detach Safely (keeps emulator running):** `detach`, then `quit`