[lldb-dev] How to handle "O XX..." reply packets from gdb servers like openocd

Owen Shaw via lldb-dev lldb-dev at lists.llvm.org
Wed Jan 3 15:28:28 PST 2018

Hi Greg,

I've been assuming that we can't force a change to openocd's behavior,
or at least that the easier path is to handle its current behavior.  I
don't know why openocd sends O packets in response to an rCmd, but it
does and gdb is okay with it.

I'm still learning my way around the lldb code, but it looked like the
continue scenario has its own function,
SendContinuePacketAndWaitForResponse(), and with continue-specific
logic, there didn't seem to be an obvious way to leverage that code or
to have the continue commands share some new code.

I have a working option coded up, and can easily throw a patch up in
Phabricator if it'd be helpful to discuss the details.  Let me know
how you'd like to proceed.


On Wed, Jan 3, 2018 at 11:11 AM, Greg Clayton <clayborg at gmail.com> wrote:
>> On Jan 1, 2018, at 6:30 PM, Owen Shaw via lldb-dev <lldb-dev at lists.llvm.org> wrote:
>> I dug into this a bit more, and these output reply packets seem to be
>> handled already, but only if the program is running.
>> Since the relevant openocd commands are often issued when the program
>> paused, the reply packets aren't processed as expected.
>> The spec does say that reply packets can happen "any time while the
>> program is running", so perhaps openocd is abusing the protocol, but
>> gdb handles the packets just fine when stopped.
> Yes, LLDB is assuming that an "O" packet will only come during a continue command. "O" is for stdout output and it seems the rCmd assuming it will work. Why not just send back the text in response to the rCmd? Is some common code path being hit where it might send this text while running and also in response to the rCmd? I am confused by "O" packets are needed in response to the rCmd.
>> It's unclear in which other cases these packets would arrive when the
>> program is stopped, so I've put together a narrowed solution:
>> 1. Adding GDBRemoteClientBase::SendPacketHandlingOutput(), with a
>> callback argument to handle any output
>> 2. Calling SendPacketHandlingOutput() from
>> CommandObjectProcessGDBRemotePacketMonitor, providing a callback lamda
>> that uses an already-available output stream
>> It's a simpler and less intrusive solution, but will only apply to
>> "process plugin packet monitor" commands.  Perhaps that's sufficient.
>> Any thoughts still appreciated.
> If the rCmd can't be fixed to just return the text without using "O" packets, I would think a simpler solution might be to change the response packet code to take a boolean that says "handle_output". Then only the continue (c, s, vCont, etc) packets would set this to true, and the "rCmd" command could set this to true. This bool would need to be plumbed through to the SendPacketAndWaitForResponse(...) functions. We could have a default argument set to false so most code won't change, just the continue and rCmd packet senders.
> Greg
>> Thanks,
>> Owen
>> On Fri, Dec 29, 2017 at 11:37 AM, Owen Shaw <llvm at owenpshaw.net> wrote:
>>> Looking for guidance.  This seems like an lldb issue, but maybe I'm
>>> missing something.  And while I have a potential solution, I'm not
>>> familiar enough with lldb code to know if its a "good" solution.
>>> Background
>>> ----------
>>> openocd sends mutliple "O XX..." reply packets
>>> (https://sourceware.org/gdb/onlinedocs/gdb/Stop-Reply-Packets.html) in
>>> response to certain commands.  The XX... hex payload should be decoded
>>> and printed for the lldb user.
>>> For example,
>>> (lldb) process plugin packet monitor help
>>> Results in a gdb client/server packet sequence like:
>>> -> $qRcmd,68656c70#fc
>>> <- $O#4f
>>> <- $O616461707465725f6b687a#66
>>> <- $O5b6b687a5d0a#ae
>>> ... (many more $O packets)
>>> <- $OK#9a
>>> and should print in the lldb console something like:
>>> adapter [khz]
>>> ... (many more lines)
>>> The Issues
>>> ----------
>>> 1) lldb assumes the first O packet is the command response, so it
>>> thinks the command failed since O is an unknown response
>>> 2) lldb only reads the first O packet, causing subsequent commands to
>>> read the remaining O reply packets from the first command as their
>>> responses
>>> 3) lldb doesn't print the O packet payloads as expected
>>> Possible Solution
>>> -----------------
>>> I've coded up a possible solution:
>>> 1) Add StringExtractorGDBRemote::IsOutputResponse() that returns true
>>> for O packets
>>> 2) Have GDBRemoteCommunication::ReadPacket() check IsOutputResponse()
>>> as it reads
>>> 3) If ReadPacket() sees an O packet, print its payload and read
>>> another packet.  Keep looping and return the first non-O packet.
>>> 4) Add an output stream member to GDBRemoteCommunication so it can
>>> print to the lldb console
>>> Seems to work.  I see the expected command output in the lldb console,
>>> the command succeeds, and subsequent commands read the correct
>>> responses.
>>> If this is anywhere near the right track, I can look into writing test
>>> cases and submitting a patch for closer evaluation.
>>> Thanks,
>>> Owen
>> _______________________________________________
>> lldb-dev mailing list
>> lldb-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

More information about the lldb-dev mailing list