An ergonomic, featureful, and easy-to-integrate implementation of the GDB Remote Serial Protocol in Rust, with no-compromises #![no_std] support.
gdbstub makes it easy to integrate powerful guest debugging support to your emulator / hypervisor / debugger / embedded project. By implementing just a few basic methods of the gdbstub::Target trait, you can have a rich GDB debugging session up and running in no time!
gdbstub's API makes extensive use of a technique called Inlineable Dyn Extension Traits (IDETs) to expose fine-grained, zero-cost control over enabled GDB protocol features without relying on compile-time features flags. Aside from making it effortless to toggle enabled protocol features, IDETs also ensure that any unimplemented features are guaranteed to be dead-code-eliminated in release builds!
If you're looking for a quick snippet of example code to see what a featureful gdbstub integration might look like, check out examples/armv4t/gdb/mod.rs
Why use gdbstub?
gdbstub tries to abstract as much of the raw GDB protocol details from the user.gdbstub comes with a community-curated collection of built-in architecture definitions for most popular platforms!qSupported packet response.gdbstub makes extensive use of Rust's powerful type system + generics to enforce protocol invariants at compile time, minimizing the number of tricky protocol details end users have to worry about.gdbstub enables fine-grained control over active protocol extensions without relying on clunky cargo features or the use of unsafe code!gdbstub's API is designed to be a "drop in" solution when you want to add debugging support into a project, and shouldn't require any large refactoring effort to integrate into an existing project.#![no_std] Ready & Size Optimizedgdbstub is a no_std first library, whereby all protocol features are required to be no_std compatible.gdbstub does not require any dynamic memory allocation, and can be configured to use fixed-size, pre-allocated buffers. This enables gdbstub to be used on even the most resource constrained, no-alloc platforms.gdbstub is entirely panic free in most minimal configurations*, resulting in substantially smaller and more robust code.gdbstub is transport-layer agnostic, and uses a basic Connection interface to communicate with the GDB server. As long as target has some method of performing in-order, serial, byte-wise I/O (e.g: putchar/getchar over UART), it's possible to run gdbstub on it!gdbstub's minimal configuration has an incredibly low binary size + RAM overhead, enabling it to be used on even the most resource-constrained microcontrollers.min-sized-rust, a baseline gdbstub implementation can weigh in at less than 10kb of .text + .rodata! *gdbstub revision. In mixed-language projects, cross-language LTO may be required (#101). Data was collected using the included example_no_std project compiled on x86_64.gdbstub in Production?Yes, as long as you don't mind some API churn until 1.0.0 is released.
Due to gdbstub's heavy use of Rust's type system in enforcing GDB protocol invariants at compile time, it's often been the case that implementing new GDB protocol features has required making some breaking API changes. While these changes are typically quite minor, they are nonetheless semver-breaking, and may require a code-change when moving between versions. Any particularly involved changes will typically be documented in a dedicated transition guide document.
That being said, gdbstub has already been integrated into many real-world projects since its initial 0.1 release, and empirical evidence suggests that it seems to be doing its job quite well! Thusfar, most reported issues have been caused by improperly implemented Target and/or Arch implementations, while the core gdbstub library itself has proven to be reasonably bug-free.
See the Future Plans + Roadmap to 1.0.0 for more information on what features gdbstub still needs to implement before committing to API stability with version 1.0.0.
The GDB Remote Serial Protocol is surprisingly complex, supporting advanced features such as remote file I/O, spawning new processes, "rewinding" program execution, and much, much more. Thankfully, most of these features are completely optional, and getting a basic debugging session up-and-running only requires implementing a few basic methods:
Yep, that's right! That's all it takes to get gdb connected!
Of course, most use-cases will want to support additional debugging features as well. At the moment, gdbstub implements the following GDB protocol extensions:
info mem)monitor Commandsmonitor command!ExecFile)info auxv)info threads)info sharedlibraries or info shared)load)Note: GDB features are implemented on an as-needed basis by gdbstub's contributors. If there's a missing GDB feature that you'd like gdbstub to implement, please file an issue and/or open a PR!
For a full list of GDB remote features, check out the GDB Remote Configuration Docs for a table of GDB commands + their corresponding Remote Serial Protocol packets.
Using a technique called Inlineable Dyn Extension Traits (IDETs), gdbstub is able to leverage the Rust compiler's powerful optimization passes to ensure any unused features are dead-code-eliminated in release builds without having to rely on compile-time features flags!
For example, if your target doesn't implement a custom GDB monitor command handler, the resulting binary won't include any code related to parsing / handling the underlying qRcmd packet!
If you're interested in the low-level technical details of how IDETs work, I've included a brief writeup in the documentation here.
By default, the std and alloc features are enabled.
When using gdbstub in #![no_std] contexts, make sure to set default-features = false.
allocConnection for Box<dyn Connection>.log::trace! (uses a heap-allocated output buffer).GdbStub (if none is provided via GdbStubBuilder::with_packet_buffer).ConsoleOutput.std (implies alloc)Connection for TcpStream and UnixStream.std::error::Error for gdbstub::Error.TargetError::Io variant to simplify std::io::Error handling from Target methods.paranoid_unsafeunsafe in gdbstub section below for more details.core_errorGdbStubError implement core::error::Error instead of std::error::Error.While some of these projects may use older versions of gdbstub, they can nonetheless serve as useful examples of what a typical gdbstub integration might look like.
If you end up using gdbstub in your project, consider opening a PR and adding it to this list!
gdbstub on no_std)betrusted-io/xous-core - The Xous microkernel operating systemvmware-labs/node-replicated-kernel - An (experimental) research OS kernel for x86-64 (amd64) machinespatina - A UEFI compliant pure rust DXE core$ claude mcp add gdbstub \
-- python -m otcore.mcp_server <graph>