While most users of gdbstub are likely debugging over transport mechanisms that are inherently reliable (i.e: pipes, TCP, emulated serial, etc...), it would be good to nice if gdbstub also properly supported use-cases where the transport mechanism is not reliable (e.g: a noisy physical serial line).
See docs at https://sourceware.org/gdb/onlinedocs/gdb/Packet-Acknowledgment.html#Packet-Acknowledgment
gdbstub today has pretty minimal support for running in ack-mode, essentially assuming that all packets will send/recv successfully.
As such, gdbstub will currently fail if:
- The host sends a "nack" packet (i.e: requesting re-transmission of the last packet)
gdbstub will simply error-out with a "nack not supported" error
gdbstub receives a malformed packet (e.g: mismatched checksum, invalid packet format, etc...)
- instead of sending a "nack" packet to the host and waiting for a response,
gdbstub errors-out immediately
Possible Solutions
Solving 2 will likely require catching certain errors as they propagate up the call stack, and instead of bailing out, squelching them and sending a "nack" packet.
Solving 1 will be a bit tricker, as gdbstub does not currently require that outgoing packets are actually buffered anywhere (e.g: write() is allowed to write bytes directly to a UART).
One possible approach: augment the Connection trait with a fn retransmit(&mut self) -> Result<bool, Self::Error> method that downstream implementations can optionally implement? i.e: return true if supported, false if not supported (which would be the default impl).
After all - we guarantee that the flush() method is called after each packet, so it should be pretty trivial for a Connection to maintain a buffer of its last-sent packet.
I suspect that this can be done in a backwards-compatible way, without requiring a breaking API change, but I'm not 100% sure.
And of course - any solution should ideally minimize binary size impact when running over a reliable transport.
While most users of
gdbstubare likely debugging over transport mechanisms that are inherently reliable (i.e: pipes, TCP, emulated serial, etc...), it would be good to nice ifgdbstubalso properly supported use-cases where the transport mechanism is not reliable (e.g: a noisy physical serial line).See docs at https://sourceware.org/gdb/onlinedocs/gdb/Packet-Acknowledgment.html#Packet-Acknowledgment
gdbstubtoday has pretty minimal support for running in ack-mode, essentially assuming that all packets will send/recv successfully.As such,
gdbstubwill currently fail if:gdbstubwill simply error-out with a "nack not supported" errorgdbstubreceives a malformed packet (e.g: mismatched checksum, invalid packet format, etc...)gdbstuberrors-out immediatelyPossible Solutions
Solving 2 will likely require catching certain errors as they propagate up the call stack, and instead of bailing out, squelching them and sending a "nack" packet.
Solving 1 will be a bit tricker, as
gdbstubdoes not currently require that outgoing packets are actually buffered anywhere (e.g:write()is allowed to write bytes directly to a UART).One possible approach: augment the
Connectiontrait with afn retransmit(&mut self) -> Result<bool, Self::Error>method that downstream implementations can optionally implement? i.e: returntrueif supported,falseif not supported (which would be the default impl).After all - we guarantee that the
flush()method is called after each packet, so it should be pretty trivial for aConnectionto maintain a buffer of its last-sent packet.I suspect that this can be done in a backwards-compatible way, without requiring a breaking API change, but I'm not 100% sure.
And of course - any solution should ideally minimize binary size impact when running over a reliable transport.