> ## Documentation Index
> Fetch the complete documentation index at: https://docs.embedder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# GDB

> Ask Embedder to drive GDB over J-Link or OpenOCD to set breakpoints, inspect registers, and snapshot a running target

In debug mode, Embedder can drive GDB on your behalf to set breakpoints, inspect registers, walk an RTOS task list, or snapshot a live target. You don't need to write `.gdbinit` files or pick a backend — describe the symptom and the agent picks the right approach.

## Prerequisites

<Steps>
  <Step title="Be in debug mode">
    Run `/debug` or click the Debug button. GDB tools are unavailable in act and plan modes.
  </Step>

  <Step title="Connect a probe">
    Embedder supports J-Link (Segger) and OpenOCD (ST-Link, CMSIS-DAP, DAPLink, NXP LPC-Link2 / MCU-Link).
  </Step>

  <Step title="Set the debug interface">
    Add this line to your project's `EMBEDDER.md`:

    ```md EMBEDDER.md theme={"system"}
    Debug Interface = jlink
    ```

    Valid values: `jlink`, `st-link`, `cmsis-dap`, `serial`. If missing, Embedder uses whichever probe it detects first.
  </Step>

  <Step title="Build the firmware">
    Embedder needs an ELF file. Make sure your build is up to date — most prompts implicitly assume `build/firmware.elf` (or whatever path your `EMBEDDER.md` `build_command` produces).
  </Step>
</Steps>

<Note>
  On first use, Embedder downloads a managed `arm-none-eabi-gdb-py3` toolchain to `~/.embedder/tools/gdb/`. If `hardware_status` reports `managedGdb.state` as `installing`, wait for it to finish before prompting for GDB.
</Note>

## Example prompts

**The device hangs and you don't know where:**

```txt embedder theme={"system"}
> the device isn't logging anything — use gdb to figure out where it's hanging
```

The agent attaches non-intrusively, reads the program counter, walks the call stack, and tells you which function it stopped in.

<Frame caption="Prompting Embedder in debug mode">
  <img src="https://mintcdn.com/embedder/nSMaECJmg2LXNFbW/images/gdb-prompt.gif?s=3273b192df64c0a5c1ddbd4cd4d8c8dc" alt="Typing a debug-mode prompt in the Embedder composer" width="532" height="180" data-path="images/gdb-prompt.gif" />
</Frame>

<Frame caption="Embedder driving GDB to find the hang">
  <img src="https://mintcdn.com/embedder/nSMaECJmg2LXNFbW/images/gdb-debugging.gif?s=6e0176ceae741971120bf4ea9ed8e34e" alt="Embedder running a hardware script that attaches via GDB and reports the stopped frame" width="800" height="533" data-path="images/gdb-debugging.gif" />
</Frame>

**Inspect a specific function:**

```txt embedder theme={"system"}
> set a breakpoint at uart_init, run, and dump the registers when it hits
```

**Diagnose a hard fault:**

```txt embedder theme={"system"}
> the chip is hard-faulting on boot — read CFSR, HFSR, and the stacked PC
```

The agent reads the System Control Block fault registers and decodes which fault fired (UsageFault, BusFault, etc.) plus the offending instruction's address.

**Walk an RTOS task list:**

```txt embedder theme={"system"}
> list all FreeRTOS tasks and show me which one is blocked
```

Works for FreeRTOS and Zephyr — the agent surfaces task names and the function each one is currently in.

**Snapshot a running target without resetting it:**

```txt embedder theme={"system"}
> attach to the chip without resetting it, read g_uptime_ms and g_last_fault_code
```

This is the "non-intrusive attach" pattern — useful for inspecting a long-running device, motor state mid-run, or fault registers after a hang. The chip keeps running.

**Read a memory-mapped peripheral register:**

```txt embedder theme={"system"}
> read RCC->CR (0x40023800) and tell me which clock sources are running
```

## What the agent does for you

When you prompt for GDB in debug mode, Embedder writes a Python script under `.embedder/hardware/` that connects via J-Link or OpenOCD, performs the inspection, and returns structured results to the chat. You'll see the script in the tool call before it runs — you can stop or edit it if needed.

By default it does **not** flash, reset, or erase the chip unless you explicitly ask. If you need a fresh start, say "flash the firmware first" or "reset the chip and break at main".

## Common gotchas

<AccordionGroup>
  <Accordion title="J-Link not detected">
    Make sure J-Link software is installed (Embedder offers to install it on debug mode entry if missing). On macOS, plug the probe in *before* starting Embedder so USB enumeration completes.
  </Accordion>

  <Accordion title="Wrong device name">
    J-Link wants device names like `nRF52840_xxAA`. If the agent picks the wrong one, set it explicitly in your prompt: "use device nRF52840\_xxAA" or list it in `EMBEDDER.md` under `Target MCU`.
  </Accordion>

  <Accordion title="OpenOCD can't find a target config">
    Set `Target MCU = stm32f407vg` (or the closest match) in `EMBEDDER.md`. Embedder uses this to pick the OpenOCD target file. If your chip isn't a stock OpenOCD target, you may need to provide your own `target.cfg` and reference it in `EMBEDDER.md`.
  </Accordion>

  <Accordion title="Variables show as <optimized out>">
    Build with `-Og` or `-O0` for the parts you're inspecting. With `-O2` / `-Os`, GDB often can't recover local variables.
  </Accordion>

  <Accordion title="Agent wants to flash and reset; you don't">
    Say "attach without resetting" or "non-intrusive attach". Combine it with "no halt" if you want the chip to keep running while the agent reads state.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Combined workflows" icon="diagram-project" href="/debug-mode/combined-workflows">
    Pair GDB with logic captures and power profiling.
  </Card>

  <Card title="Debug mode overview" icon="bug" href="/debug-mode/overview">
    Back to the OHPV loop and other instruments.
  </Card>
</CardGroup>
