Crate gdbstub[−][src]
An ergonomic and easy-to-integrate implementation of the
GDB Remote Serial Protocol
in Rust, with full #![no_std]
support.
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
.
alloc
- Implement
Connection
forBox<dyn Connection>
. - Log outgoing packets via
log::trace!
(uses a heap-allocated output buffer). - Provide built-in implementations for certain protocol features:
- Use a heap-allocated packet buffer in
GdbStub
(if none is provided viaGdbStubBuilder::with_packet_buffer
). - (Monitor Command) Use a heap-allocated output buffer in
ConsoleOutput
. - (Extended Mode) Automatically track Attached/Spawned PIDs without
implementing
ExtendedMode::query_if_attached
.
- Use a heap-allocated packet buffer in
- Implement
std
(impliesalloc
)- Implement
Connection
forTcpStream
andUnixStream
. - Implement
std::error::Error
forgdbstub::Error
. - Add a
TargetError::Io
error variant to simplify I/O Error handling fromTarget
methods.
- Implement
Getting Started
This section provides a brief overview of the key traits and types used in
gdbstub
, and walks though the basic steps required to integrate gdbstub
into a project.
It is highly recommended to take a look at some of the
examples
listed in the project README. In particular, the included
armv4t
example implements most of gdbstub
’s protocol extensions, and can be a
valuable resource when getting up-and-running with gdbstub
.
The Connection
Trait
The Connection
trait describes how gdbstub
should communicate with the
main GDB process.
Connection
is automatically implemented for common std
types such as
TcpStream
and
UnixStream
. In #![no_std]
environments, Connection
must be manually implemented using whatever
in-order, serial, byte-wise I/O the hardware has available (e.g:
putchar/getchar over UART, an embedded TCP stack, etc.).
A common way to start a remote debugging session is to wait for a GDB client to connect via TCP:
use std::net::{TcpListener, TcpStream}; fn wait_for_gdb_connection(port: u16) -> std::io::Result<TcpStream> { let sockaddr = format!("localhost:{}", port); eprintln!("Waiting for a GDB connection on {:?}...", sockaddr); let sock = TcpListener::bind(sockaddr)?; let (stream, addr) = sock.accept()?; // Blocks until a GDB client connects via TCP. // i.e: Running `target remote localhost:<port>` from the GDB prompt. eprintln!("Debugger connected from {}", addr); Ok(stream) }
The Target
Trait
The Target
trait describes how to control and modify
a system’s execution state during a GDB debugging session, and serves as the
primary bridge between gdbstub
’s generic protocol implementation and a
target’s project/platform-specific code.
For example: the Target
trait includes a method called read_registers()
,
which the GdbStub
calls whenever the GDB client queries the state of the
target’s registers.
Target
is the most important trait in gdbstub
, and must be implemented
by anyone who uses the library!
Please refer to the target
module documentation for in-depth
instructions on implementing Target
.
Starting the debugging session using GdbStub
Once a Connection
has been established and Target
has been all wired up,
all that’s left is to hand things off to GdbStub
and let it do the rest!
// Set-up a valid `Target` let mut target = MyTarget::new()?; // implements `Target` // Establish a `Connection` let connection: TcpStream = wait_for_gdb_connection(9001); // Create a new `GdbStub` using the established `Connection`. let mut debugger = GdbStub::new(connection); // Instead of taking ownership of the system, `GdbStub` takes a &mut, yielding // ownership back to the caller once the debugging session is closed. match debugger.run(&mut target) { Ok(disconnect_reason) => match disconnect_reason { DisconnectReason::Disconnect => println!("GDB client disconnected."), DisconnectReason::TargetHalted => println!("Target halted!"), DisconnectReason::Kill => println!("GDB client sent a kill command!"), } // Handle any target-specific errors Err(GdbStubError::TargetError(e)) => { println!("Target raised a fatal error: {:?}", e); // e.g: re-enter the debugging session after "freezing" a system to // conduct some post-mortem debugging debugger.run(&mut target)?; } Err(e) => return Err(e.into()) }
Modules
arch | Built-in implementations of |
common | Common types and definitions. |
target | Everything related to the |
Macros
output | Send formatted data to the GDB client console. |
outputln | Send formatted data to the GDB client console, with a newline appended. |
Structs
GdbStub | Debug a |
GdbStubBuilder | Helper to construct and customize |
Enums
DisconnectReason | Describes why the GDB session ended. |
GdbStubBuilderError | An error which may occur when building a |
GdbStubError | An error which may occur during a GDB debugging session. |
Traits
Connection | A trait to perform in-order, serial, byte-wise I/O. |