xref: /llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (revision eb0103f2d08a13812614da6f4dc3f6bb80c7aa21)
1 //===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 
11 #include "GDBRemoteCommunicationServer.h"
12 
13 // C Includes
14 // C++ Includes
15 // Other libraries and framework includes
16 #include "llvm/ADT/Triple.h"
17 #include "lldb/Interpreter/Args.h"
18 #include "lldb/Core/ConnectionFileDescriptor.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Core/State.h"
21 #include "lldb/Core/StreamString.h"
22 #include "lldb/Host/Host.h"
23 #include "lldb/Host/TimeValue.h"
24 
25 // Project includes
26 #include "Utility/StringExtractorGDBRemote.h"
27 #include "ProcessGDBRemote.h"
28 #include "ProcessGDBRemoteLog.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 //----------------------------------------------------------------------
34 // GDBRemoteCommunicationServer constructor
35 //----------------------------------------------------------------------
36 GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() :
37     GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet"),
38     m_async_thread (LLDB_INVALID_HOST_THREAD)
39 {
40 }
41 
42 //----------------------------------------------------------------------
43 // Destructor
44 //----------------------------------------------------------------------
45 GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
46 {
47 }
48 
49 
50 //void *
51 //GDBRemoteCommunicationServer::AsyncThread (void *arg)
52 //{
53 //    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
54 //
55 //    LogSP log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
56 //    if (log)
57 //        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
58 //
59 //    StringExtractorGDBRemote packet;
60 //
61 //    while ()
62 //    {
63 //        if (packet.
64 //    }
65 //
66 //    if (log)
67 //        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
68 //
69 //    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
70 //    return NULL;
71 //}
72 //
73 bool
74 GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr,
75                                                         Error &error,
76                                                         bool &interrupt,
77                                                         bool &quit)
78 {
79     StringExtractorGDBRemote packet;
80     if (WaitForPacketNoLock (packet, timeout_ptr))
81     {
82         const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
83         switch (packet_type)
84         {
85         case StringExtractorGDBRemote::eServerPacketType_nack:
86         case StringExtractorGDBRemote::eServerPacketType_ack:
87             break;
88 
89         case StringExtractorGDBRemote::eServerPacketType_invalid:
90             error.SetErrorString("invalid packet");
91             quit = true;
92             break;
93 
94         case StringExtractorGDBRemote::eServerPacketType_interrupt:
95             error.SetErrorString("interrupt received");
96             interrupt = true;
97             break;
98 
99         case StringExtractorGDBRemote::eServerPacketType_unimplemented:
100             return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
101 
102         case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
103             return Handle_qHostInfo (packet);
104 
105         case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
106             return Handle_qProcessInfoPID (packet);
107 
108         case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
109             return Handle_qfProcessInfo (packet);
110 
111         case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
112             return Handle_qsProcessInfo (packet);
113 
114         case StringExtractorGDBRemote::eServerPacketType_qUserName:
115             return Handle_qUserName (packet);
116 
117         case StringExtractorGDBRemote::eServerPacketType_qGroupName:
118             return Handle_qGroupName (packet);
119 
120         case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
121             return Handle_qSpeedTest (packet);
122         case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
123             return Handle_QStartNoAckMode (packet);
124         }
125         return true;
126     }
127     else
128     {
129         if (!IsConnected())
130             error.SetErrorString("lost connection");
131         else
132             error.SetErrorString("timeout");
133     }
134 
135     return false;
136 }
137 
138 size_t
139 GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
140 {
141     // TODO: Log the packet we aren't handling...
142     return SendPacket ("");
143 }
144 
145 size_t
146 GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
147 {
148     char packet[16];
149     int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
150     assert (packet_len < sizeof(packet));
151     return SendPacket (packet, packet_len);
152 }
153 
154 
155 size_t
156 GDBRemoteCommunicationServer::SendOKResponse ()
157 {
158     return SendPacket ("OK");
159 }
160 
161 bool
162 GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
163 {
164     if (StartReadThread(error_ptr))
165         return GetAck();
166     return false;
167 }
168 
169 bool
170 GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
171 {
172     StreamString response;
173 
174     // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
175 
176     ArchSpec host_arch (Host::GetArchitecture ());
177     const llvm::Triple &host_triple = host_arch.GetTriple();
178     response.PutCString("triple:");
179     response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
180     response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
181 
182     uint32_t cpu = host_arch.GetMachOCPUType();
183     uint32_t sub = host_arch.GetMachOCPUSubType();
184     if (cpu != LLDB_INVALID_CPUTYPE)
185         response.Printf ("cputype:%u;", cpu);
186     if (sub != LLDB_INVALID_CPUTYPE)
187         response.Printf ("cpusubtype:%u;", sub);
188 
189     switch (lldb::endian::InlHostByteOrder())
190     {
191     case eByteOrderBig:     response.PutCString ("endian:big;"); break;
192     case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
193     case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
194     default:                response.PutCString ("endian:unknown;"); break;
195     }
196 
197     uint32_t major = UINT32_MAX;
198     uint32_t minor = UINT32_MAX;
199     uint32_t update = UINT32_MAX;
200     if (Host::GetOSVersion (major, minor, update))
201     {
202         if (major != UINT32_MAX)
203         {
204             response.Printf("os_version:%u", major);
205             if (minor != UINT32_MAX)
206             {
207                 response.Printf(".%u", minor);
208                 if (update != UINT32_MAX)
209                     response.Printf(".%u", update);
210             }
211             response.PutChar(';');
212         }
213     }
214 
215     std::string s;
216     if (Host::GetOSBuildString (s))
217     {
218         response.PutCString ("os_build:");
219         response.PutCStringAsRawHex8(s.c_str());
220         response.PutChar(';');
221     }
222     if (Host::GetOSKernelDescription (s))
223     {
224         response.PutCString ("os_kernel:");
225         response.PutCStringAsRawHex8(s.c_str());
226         response.PutChar(';');
227     }
228     if (Host::GetHostname (s))
229     {
230         response.PutCString ("hostname:");
231         response.PutCStringAsRawHex8(s.c_str());
232         response.PutChar(';');
233     }
234 
235     return SendPacket (response) > 0;
236 }
237 
238 static void
239 CreateProcessInfoResponse (const ProcessInfo &proc_info, StreamString &response)
240 {
241     response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;",
242                      proc_info.GetProcessID(),
243                      proc_info.GetParentProcessID(),
244                      proc_info.GetRealUserID(),
245                      proc_info.GetRealGroupID(),
246                      proc_info.GetEffectiveUserID(),
247                      proc_info.GetEffectiveGroupID());
248     response.PutCString ("name:");
249     response.PutCStringAsRawHex8(proc_info.GetName());
250     response.PutChar(';');
251     const ArchSpec &proc_arch = proc_info.GetArchitecture();
252     if (proc_arch.IsValid())
253     {
254         const llvm::Triple &proc_triple = proc_arch.GetTriple();
255         response.PutCString("triple:");
256         response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
257         response.PutChar(';');
258     }
259 }
260 
261 bool
262 GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
263 {
264     // Packet format: "qProcessInfoPID:%i" where %i is the pid
265     packet.SetFilePos(strlen ("qProcessInfoPID:"));
266     lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
267     if (pid != LLDB_INVALID_PROCESS_ID)
268     {
269         ProcessInfo proc_info;
270         if (Host::GetProcessInfo(pid, proc_info))
271         {
272             StreamString response;
273             CreateProcessInfoResponse (proc_info, response);
274             return SendPacket (response);
275         }
276     }
277     return SendErrorResponse (1);
278 }
279 
280 bool
281 GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
282 {
283     m_proc_infos_index = 0;
284     m_proc_infos.Clear();
285 
286     ProcessInfoMatch match_info;
287     packet.SetFilePos(strlen ("qfProcessInfo"));
288     if (packet.GetChar() == ':')
289     {
290 
291         std::string key;
292         std::string value;
293         while (packet.GetNameColonValue(key, value))
294         {
295             bool success = true;
296             if (key.compare("name") == 0)
297             {
298                 StringExtractor extractor;
299                 extractor.GetStringRef().swap(value);
300                 extractor.GetHexByteString (value);
301                 match_info.GetProcessInfo().SetName (value.c_str());
302             }
303             else if (key.compare("name_match") == 0)
304             {
305                 if (value.compare("equals") == 0)
306                 {
307                     match_info.SetNameMatchType (eNameMatchEquals);
308                 }
309                 else if (value.compare("starts_with") == 0)
310                 {
311                     match_info.SetNameMatchType (eNameMatchStartsWith);
312                 }
313                 else if (value.compare("ends_with") == 0)
314                 {
315                     match_info.SetNameMatchType (eNameMatchEndsWith);
316                 }
317                 else if (value.compare("contains") == 0)
318                 {
319                     match_info.SetNameMatchType (eNameMatchContains);
320                 }
321                 else if (value.compare("regex") == 0)
322                 {
323                     match_info.SetNameMatchType (eNameMatchRegularExpression);
324                 }
325                 else
326                 {
327                     success = false;
328                 }
329             }
330             else if (key.compare("pid") == 0)
331             {
332                 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
333             }
334             else if (key.compare("parent_pid") == 0)
335             {
336                 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
337             }
338             else if (key.compare("uid") == 0)
339             {
340                 match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
341             }
342             else if (key.compare("gid") == 0)
343             {
344                 match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
345             }
346             else if (key.compare("euid") == 0)
347             {
348                 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
349             }
350             else if (key.compare("egid") == 0)
351             {
352                 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
353             }
354             else if (key.compare("all_users") == 0)
355             {
356                 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
357             }
358             else if (key.compare("triple") == 0)
359             {
360                 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
361             }
362             else
363             {
364                 success = false;
365             }
366 
367             if (!success)
368                 return SendErrorResponse (2);
369         }
370     }
371 
372     if (Host::FindProcesses (match_info, m_proc_infos))
373     {
374         // We found something, return the first item by calling the get
375         // subsequent process info packet handler...
376         return Handle_qsProcessInfo (packet);
377     }
378     return SendErrorResponse (3);
379 }
380 
381 bool
382 GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
383 {
384     if (m_proc_infos_index < m_proc_infos.GetSize())
385     {
386         StreamString response;
387         CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
388         ++m_proc_infos_index;
389         return SendPacket (response);
390     }
391     return SendErrorResponse (4);
392 }
393 
394 bool
395 GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
396 {
397     // Packet format: "qUserName:%i" where %i is the uid
398     packet.SetFilePos(strlen ("qUserName:"));
399     uint32_t uid = packet.GetU32 (UINT32_MAX);
400     if (uid != UINT32_MAX)
401     {
402         std::string name;
403         if (Host::GetUserName (uid, name))
404         {
405             StreamString response;
406             response.PutCStringAsRawHex8 (name.c_str());
407             return SendPacket (response);
408         }
409     }
410     return SendErrorResponse (5);
411 
412 }
413 
414 bool
415 GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
416 {
417     // Packet format: "qGroupName:%i" where %i is the gid
418     packet.SetFilePos(strlen ("qGroupName:"));
419     uint32_t gid = packet.GetU32 (UINT32_MAX);
420     if (gid != UINT32_MAX)
421     {
422         std::string name;
423         if (Host::GetGroupName (gid, name))
424         {
425             StreamString response;
426             response.PutCStringAsRawHex8 (name.c_str());
427             return SendPacket (response);
428         }
429     }
430     return SendErrorResponse (6);
431 }
432 
433 bool
434 GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
435 {
436     packet.SetFilePos(strlen ("qSpeedTest:"));
437 
438     std::string key;
439     std::string value;
440     bool success = packet.GetNameColonValue(key, value);
441     if (success && key.compare("response_size") == 0)
442     {
443         uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
444         if (success)
445         {
446             if (response_size == 0)
447                 return SendOKResponse();
448             StreamString response;
449             uint32_t bytes_left = response_size;
450             response.PutCString("data:");
451             while (bytes_left > 0)
452             {
453                 if (bytes_left >= 26)
454                 {
455                     response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
456                     bytes_left -= 26;
457                 }
458                 else
459                 {
460                     response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
461                     bytes_left = 0;
462                 }
463             }
464             return SendPacket (response);
465         }
466     }
467     return SendErrorResponse (7);
468 }
469 bool
470 GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
471 {
472     // Send response first before changing m_send_acks to we ack this packet
473     SendOKResponse ();
474     m_send_acks = false;
475     return true;
476 }
477