debugger
debugger copied to clipboard
GDB MI Adapter for OpenOCD Embedded Debugging in Binary Ninja
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-multiarchorarm-none-eabi-gdb - OpenOCD: Running with target configuration (e.g., STM32F4x)
Typical Workflow:
- Start OpenOCD:
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg - Export DWARF file for target architecture
- Configure adapter settings in Binary Ninja. Specify desired GDB path, connection IP/port and DWARF file
- Connect to target through the debugger interface
- 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 resolutiongdb.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
Benefits for Binary Ninja Community
This implementation significantly enhances Binary Ninja's capabilities for:
- Embedded Security Research: Dynamic analysis of IoT devices, automotive systems, and industrial controllers
- Firmware Reverse Engineering: Live debugging of embedded binaries with Binary Ninja's advanced analysis features
- Hardware-Assisted Analysis: Integration with real hardware through standard debugging probes
- Educational Use: Teaching embedded systems and reverse engineering with professional tools
Implements #874 and partially covers #170
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!
- 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
"
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
@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!