[][src]Crate gdbstub

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 for Box<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 via GdbStubBuilder::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.
  • std (implies alloc)
    • Implement Connection for TcpStream and UnixStream.
    • Implement std::error::Error for gdbstub::Error.
    • Add a TargetError::Io error variant to simplify I/O Error handling from Target methods.

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!

This example is not tested
// 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 Arch for various architectures.

common

Common types and definitions.

target

Everything related to the Target trait + associated extension traits.

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 Target using the GDB Remote Serial Protocol over a given Connection.

GdbStubBuilder

Helper to construct and customize GdbStub.

Enums

DisconnectReason

Describes why the GDB session ended.

GdbStubBuilderError

An error which may occur when building a GdbStub.

GdbStubError

An error which may occur during a GDB debugging session.

Traits

Connection

A trait to perform in-order, serial, byte-wise I/O.