lldb remote protocol

I am developing an emulator program and I would like to implement a debugger stub (over TCP) to which I could connect using the remote debugging features of lldb to assist me. GDB documents its communication protocol, but I'm not a fan of how every concern happens at the same level (especially reliability), so I was hoping the LLDB protocol could be more modern.

Is there documentation for it? The commands seem to be declared in tools/debugserver/source/RNBRemote.h, but I don't expect to implement all of it and I'm not sure what's absolutely necessary and what's not so necessary, and I'm not sure how packets are formed.

Is this documented anywhere, or is the best way to grab the source and check for myself?

Félix

There is a text file in the doc/ directory that explains the LLDB enhancements to the GDB remote protocol.

Good luck,
Dan

Got it, working on that.

Does QStartNoAckMode also disable checksums? In every example in the file, checksums are #00 (and indeed lldb sends me packets with that same checksum), but there's no mention of that in the document.

Félix

Well, it didn’t take too long to run into issues:

← qHostInfo
→ cputype:18;cpusubtype:9;ostype:unknown;vendor:fclout;endian:big;ptrsize:4

Assertion failed: (byte_order == m_host_arch.GetByteOrder()), function GetHostInfo, file /Users/felix/Projets/oss/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp, line 1235.
Abort trap: 6

Is that something no one did because it’s gonna be hard and deep-reaching or because nobody had a use case for it?

Also, pretty early (shortly after receiving no information for qProcessInfo and qShlibInfoAddr), lldb asks for the 512 bytes located at 0xffff0000. What is it trying to accomplish?

That’s where I stopped today. I might bug you guys again tomorrow :slight_smile:

Félix

Yes it does disable checksums as the protocol is considered reliable enough to disable acks/nacks, so it is assumed to not require checksums.

Bug in LLDB. Fixed:

% svn commit
Sending source/Core/ArchSpec.cpp
Transmitting file data .
Committed revision 188189.

PowerPC had little endian marked as its default byte order, which was fixed above. The assert is there to ensure that our tables were correct and it found the bug for us.

Greg

Well, it didn't take too long to run into issues:

<- qHostInfo
-> cputype:18;cpusubtype:9;ostype:unknown;vendor:fclout;endian:big;ptrsize:4

Assertion failed: (byte_order == m_host_arch.GetByteOrder()), function GetHostInfo, file /Users/felix/Projets/oss/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp, line 1235.
Abort trap: 6

This is now fixed with:

% svn commit
Sending source/Core/ArchSpec.cpp
Transmitting file data .
Committed revision 188189.

Is that something no one did because it's gonna be hard and deep-reaching or because nobody had a use case for it?

No one has down PowerPC debugging yet.

Also, pretty early (shortly after receiving no information for qProcessInfo and qShlibInfoAddr), lldb asks for the 512 bytes located at 0xffff0000. What is it trying to accomplish?

Not sure, enable packet logging with stack traces and you will see who is trying to read this memory. Add the following line to your ~/.lldbinit file:

log enable --file /tmp/packets.txt --stack gdb-remote packets

My stub sends an empty reply to qThreadStopInfo and it crashes lldb. (I understand it's an important command to implement, it's just that I decide if I want to implement them as lldb sends them.)

< 20> send packet: $qThreadStopInfo1#00
1 LLDB 0x0000000101579a43 _ZN12lldb_private3Log21PrintfWithFlagsVarArgEjPKcP13__va_list_tag + 1475
2 LLDB 0x0000000101579c4e _ZN12lldb_private3Log6PrintfEPKcz + 366
3 LLDB 0x00000001017e6f39 _ZN22GDBRemoteCommunication16SendPacketNoLockEPKcm + 649
4 LLDB 0x0000000101b02308 _ZN28GDBRemoteCommunicationClient28SendPacketAndWaitForResponseEPKcmR24StringExtractorGDBRemoteb + 200
5 LLDB 0x0000000101b1374d _ZN28GDBRemoteCommunicationClient17GetThreadStopInfoEyR24StringExtractorGDBRemote + 221
6 LLDB 0x000000010181a368 _ZN15ThreadGDBRemote17CalculateStopInfoEv + 184
7 LLDB 0x0000000101aa8815 _ZN12lldb_private6Thread18GetPrivateStopInfoEv + 997
8 LLDB 0x0000000101aa7cec _ZN12lldb_private6Thread11GetStopInfoEv + 892
9 LLDB 0x0000000101abdde0 _ZN12lldb_private10ThreadList10ShouldStopEPNS_5EventE + 1296
10 LLDB 0x0000000101a2a492 _ZN12lldb_private7Process20ShouldBroadcastEventEPNS_5EventE + 418
11 LLDB 0x0000000101a25b6d _ZN12lldb_private7Process18HandlePrivateEventERNSt3__110shared_ptrINS_5EventEEE + 637
12 LLDB 0x0000000101a2931d _ZN12lldb_private7Process13ConnectRemoteEPNS_6StreamEPKc + 893
13 LLDB 0x000000010148b64c _ZN27CommandObjectProcessConnect9DoExecuteERN12lldb_private4ArgsERNS0_19CommandReturnObjectE + 1788
14 LLDB 0x000000010175c4db _ZN12lldb_private19CommandObjectParsed7ExecuteEPKcRNS_19CommandReturnObjectE + 715
15 LLDB 0x00000001017359a4 _ZN12lldb_private18CommandInterpreter13HandleCommandEPKcNS_8LazyBoolERNS_19CommandReturnObjectEPNS_16ExecutionContextEbb + 21492
16 LLDB 0x00000001017637b8 _ZN12lldb_private25CommandObjectRegexCommand9DoExecuteEPKcRNS_19CommandReturnObjectE + 2984
17 LLDB 0x000000010175c875 _ZN12lldb_private16CommandObjectRaw7ExecuteEPKcRNS_19CommandReturnObjectE + 789
18 LLDB 0x00000001017359a4 _ZN12lldb_private18CommandInterpreter13HandleCommandEPKcNS_8LazyBoolERNS_19CommandReturnObjectEPNS_16ExecutionContextEbb + 21492
19 LLDB 0x00000001000c8584 _ZN4lldb20SBCommandInterpreter13HandleCommandEPKcRNS_21SBCommandReturnObjectEb + 292
20 lldb 0x0000000100007b87 _ZN6Driver13HandleIOEventERKN4lldb7SBEventE + 183
21 lldb 0x000000010000af16 _ZN6Driver8MainLoopEv + 11062
22 lldb 0x000000010000b9d3 main + 467
23 lldb 0x0000000100000fd4 start + 52
24 ??? 0x0000000000000001 0x0 + 1

Stack trace when the crash happens:

#0 lldb_private::Mutex::Locker::Lock(lldb_private::Mutex&) at /lldb/source/Host/common/Mutex.cpp:152
#1 lldb_private::Mutex::Locker::Locker(lldb_private::Mutex&) at /lldb/source/Host/common/Mutex.cpp:112
#2 lldb_private::Mutex::Locker::Locker(lldb_private::Mutex&) at /lldb/source/Host/common/Mutex.cpp:113
#3 lldb_private::Unwind::GetFrameInfoAtIndex(unsigned int, unsigned long long&, unsigned long long&) at /lldb/include/lldb/Target/Unwind.h:77
#4 lldb_private::StackFrameList::GetFramesUpTo(unsigned int) at /lldb/source/Target/StackFrameList.cpp:304
#5 lldb_private::StackFrameList::GetFrameAtIndex(unsigned int) at /lldb/source/Target/StackFrameList.cpp:521
#6 lldb_private::StackFrameList::SetDefaultFileAndLineToSelectedFrame() at /lldb/source/Target/StackFrameList.cpp:702
#7 lldb_private::thread::SetDefaultFileAndLineToSelectedFrame() at /lldb/include/lldb/Target/Thread.h:415
#8 lldb_private::ThreadList::SetSelectedThreadByID(unsigned long long, bool) at /lldb/source/Target/ThreadList.cpp:691
#9 lldb::SBProcess::SetSelectedThread(lldb::SBThread const&) at /lldb/source/API/SBProcess.cpp:462
#10 Driver::UpdateSelectedThread() at /lldb/tools/driver/Driver.cpp:865
#11 Driver::HandleProcessEvent(lldb::SBEvent const&) at /lldb/tools/driver/Driver.cpp:1015
#12 Driver::MainLoop() at /lldb/tools/driver/Driver.cpp:1562
#13 main at /lldb/tools/driver/Driver.cpp:1727
#14 start ()

It happens because m_thread.GetUnwinder () at Target/StackFrameList.cpp:264 (GetFramesUpTo) returns a null unwinder.

Entire communication attached, it should be pretty easy to reproduce from that.

Félix

communication.txt (11 KB)