gdbstub

An ergonomic and easy-to-integrate implementation of the GDB Remote Serial Protocol in Rust, with full #![no_std] support.

Why gdbstub?

* Exact numbers vary by target platform, compiler version, and gdbstub revision. Data was collected using the included example_no_std project compiled on x86_64.

gdbstub is particularly well suited for emulation, making it easy to add powerful, non-intrusive debugging support to an emulated system. Just provide an implementation of the Target trait for your target platform, and you're ready to start debugging!

Can I Use gdsbtub in Production?

Yes, as long as you don't mind some API churn until 1.0.0 is released.

In terms of correctness, gdbstub has been integrated into several projects since its initial 0.1.0 release, and thusfar, no major bugs have been reported. Reported issues have typically been the result of faulty Target implementations (e.g: forgetting to adjust the PC after a breakpoint is hit), or were related to certain unimplemented GDB protocol features.

That being said, 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 Trait/Type changes (e.g: adding the RegId associated type to Arch to support addressing individual registers). While these changes are typically quite minor, they are nonetheless breaking, and may require a code-change when moving between versions.

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.

Debugging Features

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:

Of course, most use-cases will want to support additional debugging features as well. At the moment, gdbstub implements the following GDB protocol extensions:

Note: Which GDB features are implemented are decided 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 / open a PR! Check out the GDB Remote Configuration Docs for a table of GDB commands + their corresponding Remote Serial Protocol packets.

Zero-overhead Protocol Extensions

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.

Feature flags

By default, the std and alloc features are enabled.

When using gdbstub in #![no_std] contexts, make sure to set default-features = false.

Examples

armv4t

The armv4t example shows how gdbstub can be used to add gdb debugging support to an (incredibly simple) ARMv4T-based emulator.

This example implements a "grab bag" of miscellaneous target_ext features, and can serve as a useful reference when implementing a new target extension.

See examples/armv4t/README.md for details.

armv4t_multicore

A dual-core variation of the armv4t example. Implements gdbstub's multithread extensions to enable per-core debugging.

This example shows off the multithreaded base operations API, but not much else.

See examples/armv4t_multicore/README.md for details.

Real-World Examples

Several projects are already using gdbstub. While some of these libraries may be using older versions of gdbstub, they are nonetheless useful sources of inspiration.

If you end up using gdbstub in your project, feel free to open a PR and add it to this list!

Using gdbstub on bare-metal hardware

Quite a bit of work has gone into making gdbstub optimized for #![no_std], which means it should be entirely possible to implement a Target which uses low-level trap instructions + context switching to debug bare-metal code.

If you happen to stumble across this crate and end up using it to debug some bare-metal code, please let me know! I'd love to link to your project, and/or create a simplified example based off your code!

unsafe in gdbstub

gdbstub "core" only has 2 instances of unsafe code:

With the std feature enabled, there is one additional instance of unsafe code:

Future Plans + Roadmap to 1.0.0

Before gdbstub can comfortably commit to a stable 1.0.0 API, there are several outstanding features that should be implemented and questions that need to be addressed. Due to gdbstub's heavy reliance on the Rust type system to enforce GDB protocol invariants, it's likely that a certain subset of yet-unimplemented protocol features may require breaking API changes.

The following features are most likely to require breaking API changes, and should therefore be implemented prior to 1.0.0.

Notably, it the vast majority of GDB protocol features (e.g: remote filesystem support, tracepoint packets, most query packets, etc...) should not require breaking API changes, and could most likely be implemented using the standard backwards-compatible protocol extension approach.

Additionally, while not strictly "blockers" to 1.0.0, it would be good to explore these features as well: