Skip to content

Option for GdbStub to own its packet buffer #184

@lewisfm

Description

@lewisfm

I used gdbstub to create an on-device embedded debugger (in which it is working very well), but initially setting up the integration felt like I was working around the borrow-check system. The crate's packet buffer API seems to be optimized for having a function-scoped GdbStub that refers to existing data structures, whereas I need my debugger to live for the entire program with the ability to be periodically polled from any context.

Since my GdbStub instance needs to be stored globally, I need it to be 'static. However, there's no option for it to own its packet buffer; it only accepts references. Attaining such a &'static mut [u8] required me to do some unsafe shenanigans:

pub struct V5Debugger<S: Connection + ConnectionExt> {
    target: V5Target,
    gdb: Option<GdbStubStateMachine<'static, V5Target, S>>,
}

const GDB_PACKET_BUFFER_SIZE: usize = 0x2000;
static mut GDB_PACKET_BUFFER: [u8; GDB_PACKET_BUFFER_SIZE] = [0; _];
static GDB_PACKET_BUFFER_CLAIMED: AtomicBool = AtomicBool::new(false);

if GDB_PACKET_BUFFER_CLAIMED.swap(true, Ordering::Acquire) {
    panic!("Cannot create multiple debuggers");
}

// SAFETY: The mutable ownership over the buffer can only be taken once.
let gdb_buffer: &'static mut [u8] = unsafe {
    core::slice::from_raw_parts_mut(&raw mut GDB_PACKET_BUFFER[0], GDB_PACKET_BUFFER_SIZE)
};

let mut target = V5Target::new();

Self {
    gdb: {
        let stub = GdbStubBuilder::new(stream)
            .with_packet_buffer(gdb_buffer)
            .build()
            .unwrap();

        Some(stub.run_state_machine(&mut target).unwrap())
    },
    target,
}

It would be very convenient if I didn't have to worry about GDBStub's packet buffer. I'd be happy to do something like this:

const GDB_PACKET_BUFFER_SIZE: usize = 0x2000;
let mut target = V5Target::new();

Self {
    gdb: {
        let stub = StaticGdbStub::<GDB_PACKET_BUFFER_SIZE>::new(stream);
        Some(stub.run_state_machine(&mut target).unwrap())
    },
    target,
}

...or have some other API that implements the buffer as an owned array.

Metadata

Metadata

Assignees

No one assigned

    Labels

    API-ergonomicsNothing's "broken", but the API could be improvedAPI-non-breakingNon-breaking API changenew-apiAdd a new feature to the API (possibly non-breaking)

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions