debugger icon indicating copy to clipboard operation
debugger copied to clipboard

GDB MI Adapter for OpenOCD Embedded Debugging in Binary Ninja

Open anvol opened this issue 1 month ago • 6 comments
trafficstars

Key Features:

  • OpenOCD Integration: Seamless connection to OpenOCD debug servers (default port 3333)
  • ARM Cortex-M Focus: Optimized for Cortex-M3, M4, M7, and other embedded ARM variants
  • Architecture Auto-Detection: Intelligent detection of target architecture through register analysis and GDB queries
  • Thread-Safe Design: Non-blocking UI with dedicated reader threads and command synchronization
  • Debugging: Breakpoints, stepping, memory access, register inspection, and watch variables/structs in bn views

Technical Implementation Details

Architecture:

  • GdbMiConnector: Handles low-level MI protocol communication, process management, and async event processing. Covered with miparser_test
  • GdbMiAdapter: Implements Binary Ninja's DebugAdapter interface with high-level debugging operations
  • Caching System: Performance-optimized caching for threads, registers, and stack frames
  • Cross-Platform: Proper process handling Linux, macOS, and (maybe) Windows

Key Technical Components:

  • MI protocol parser handling nested structures and complex responses
  • Variable object system for efficient watch variable tracking
  • Hardware breakpoint support for embedded targets
  • Memory access constraints for embedded memory maps

Setup and Configuration

Required Tools:

  • Host System: Linux or macOS with Binary Ninja
  • Debug Probe: ST-Link, J-Link, or other OpenOCD-compatible probe
  • GDB: gdb-multiarch or arm-none-eabi-gdb
  • OpenOCD: Running with target configuration (e.g., STM32F4x)

Typical Workflow:

  1. Start OpenOCD: openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
  2. Export DWARF file for target architecture
  3. Configure adapter settings in Binary Ninja. Specify desired GDB path, connection IP/port and DWARF file
  4. Connect to target through the debugger interface
  5. Set breakpoints, inspect memory, and step through firmware code

Adapter Settings:

  • gdb.path: Path to GDB executable (default: gdb-multiarch)
  • connect.ipAddress: OpenOCD server IP (default: 127.0.0.1)
  • connect.port: OpenOCD GDB port (default: 3333)
  • common.inputFile: Firmware file for base address resolution
  • gdb.symbolFile: ELF or DWARF debug information so gdb would know funcs boundaries and names for backtrace

Testing and Validation

Verified Platforms:

  • Debian 13 with gdb-multiarch
  • macOS 15+ (Apple Silicon) arm-none-eabi-gdb from brew
  • ARM Cortex-M targets (STM32F103 and STM32F401 extensively tested)

Validation Checklist:

  • [x] GDB process launches and terminates correctly
  • [x] Architecture auto-detection for ARM Cortex-M targets
  • [x] Successful connection to OpenOCD
  • [x] Register display and memory access
  • [x] Breakpoint setting and hitting
  • [x] Stepping and control flow
  • [x] Watch variable updates in main ui window
  • [x] Thread and stack frame information
image image image

Benefits for Binary Ninja Community

This implementation significantly enhances Binary Ninja's capabilities for:

  1. Embedded Security Research: Dynamic analysis of IoT devices, automotive systems, and industrial controllers
  2. Firmware Reverse Engineering: Live debugging of embedded binaries with Binary Ninja's advanced analysis features
  3. Hardware-Assisted Analysis: Integration with real hardware through standard debugging probes
  4. Educational Use: Teaching embedded systems and reverse engineering with professional tools

anvol avatar Oct 11 '25 12:10 anvol

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Oct 11 '25 12:10 CLAassistant

Implements #874 and partially covers #170

anvol avatar Oct 11 '25 12:10 anvol

Thanks for the contribution! I had a quick glance and it looks good, I will review it when I get time.

Also I had copilot look at it as well -- I have not gone through them yet, if they are correct, please address them; if they are wrong, please point it out!

xusheng6 avatar Oct 17 '25 08:10 xusheng6

  • buffer - confirmed, fixed that locally
  • step - confirmed
  • additionally, GetBreakpointList should be implemented as GDB MI expects it's idx from "-break-list" cmd to remove breakpoint "-break-delete "

anvol avatar Oct 17 '25 08:10 anvol

I forked your PR and created https://github.com/Vector35/debugger/tree/add_gdb_mi_adapter

I noticed that some of the things you put are embedded specific, which I hope to remove before merging. I also noted that they might still be useful for you, so I am starting on top of a new branch

xusheng6 avatar Oct 22 '25 05:10 xusheng6

@anvol I tried to make this branch into a state that can be merged into the dev branch, but I failed to do so. I met some issues when using the GDB MI to connect to a gdbserver running on Linux and getting the list of loaded modules. I know this is beyond your interest, but I believe this needs to be addressed before I can ship it because many users would try to do that anyways.

This PR/branch has missed our internal feature freeze, which means it would not be in stable 5.2. I will try to get back to this after the release!

xusheng6 avatar Oct 22 '25 14:10 xusheng6