| commit | a4a1a2293e7a4aacf1d3157aeba89c703cb7da02 | [log] [tgz] |
|---|---|---|
| author | Joel Galenson <[email protected]> | Wed Dec 15 18:06:56 2021 +0000 |
| committer | Automerger Merge Worker <[email protected]> | Wed Dec 15 18:06:56 2021 +0000 |
| tree | 42f3e36df36464bdd7d7fcba2e800e7997ef11e6 | |
| parent | d99869ac41abfdb7859df9d79d7d92852c365382 [diff] | |
| parent | 891b823ca6b2fb61d6a0ebd963bc21a70f3c07c2 [diff] |
Merge "Refresh Android.bp, cargo2android.json, TEST_MAPPING." am: 7754bf823d am: d4da537e47 am: b42acfd568 am: 891b823ca6 Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/gdbstub/+/1912523 Change-Id: I38612ca363eea5283f1ffcd2a0b76acc29e886a5
An ergonomic and easy-to-integrate implementation of the GDB Remote Serial Protocol in Rust, with full #![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!
If you're looking for a quick snippet of example code to see what a typical 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. For example: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.gdbstub‘s API is designed to be as unobtrusive as possible, and shouldn’t require any large refactoring effort to integrate into an existing project. It doesn't require taking direct ownership of any key data structures, and aims to be a “drop in” solution when you need to add debugging to a 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 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 tries to keep the binary and RAM footprint of its minimal configuration to a bare minimum, enabling it to be used on even the most resource-constrained microcontrollers.min-sized-rust, a baseline gdbstub implementation weighs in at roughly 10kb of .text and negligible .rodata! *gdbstub revision. 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 Trait/Type 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, there haven't been any reported issues related to core GDB debugging functionality, with most issues being caused by faulty Target and/or Arch implementations.
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:
Of course, most use-cases will want to support additional debugging features as well. At the moment, gdbstub implements the following GDB protocol extensions:
monitor Commandsmonitor commandNote: 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.memflow-cli) (64)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!
These examples are built as part of the CI, and are guaranteed to be kept up to date with the latest version of gdbstub's API.
armv4t - ./examples/armv4t/gdbstub support.target::ext features. This makes it a great resource when first implementing a new protocol extension!armv4t_multicore - ./examples/armv4t_multicore/armv4t example.gdbstub's multithread extensions API, but not much else.example_no_std - ./example_no_stdgdbstub can be used in a #![no_std] project.armv4t/armv4t_multicore examples, this project does not include a working emulator, and simply stubs all gdbstub functions.gdbstub's approximate binary footprint (via the check_size.sh script), and validating certain dead-code-elimination optimizations.gdbstub on bare-metal hardwareQuite 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 gdbstubgdbstub limits its use of unsafe to a bare minimum, with all uses of unsafe required to have a corresponding // SAFETY comment as justification. The following list exhaustively documents all uses of unsafe in gdbstub.
NonZeroUsize::new_unchecked() when defining internal constants.std feature is enabled:UnixStream::peek which uses libc::recv. This manual implementation will be removed once rust-lang/rust#76923 is stabilized.1.0.0While the vast majority of GDB protocol features (e.g: remote filesystem support, tracepoint packets, most query packets, etc...) should not require breaking API changes, there are still several key protocol features that'll need breaking API changes to be implemented.
The following features are most likely to require breaking API changes, and should therefore be implemented prior to 1.0.0. Not that this is not an exhaustive list, and is subject to change.
Arch traittarget::ext::base::multiprocess API.gdbstub already implements multiprocess extensions “under-the-hood”, and just hard-codes a fake PID, so this is mostly a matter of “putting in the work”.target extended-remote)gdbstub running in a “bare-metal” #![no_std] environment (e.g: debugging a hobby OS via serial).Additionally, while not strict “blockers” to 1.0.0, it would be good to explore these features as well:
gdbstub commit to a MSRV?async/await interfaces (particularly wrt. handling GDB client interrupts) (#36)