blob: c2431380fd9e0f363f7d674b4ed3f3d5df442dbe [file] [log] [blame]
Greg Clayton61d043b2011-03-22 04:00:09 +00001//===-- 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
30using namespace lldb;
31using namespace lldb_private;
32
33//----------------------------------------------------------------------
34// GDBRemoteCommunicationServer constructor
35//----------------------------------------------------------------------
36GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() :
37 GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet"),
Greg Clayton58e26e02011-03-24 04:28:38 +000038 m_async_thread (LLDB_INVALID_HOST_THREAD)
Greg Clayton61d043b2011-03-22 04:00:09 +000039{
40}
41
42//----------------------------------------------------------------------
43// Destructor
44//----------------------------------------------------------------------
45GDBRemoteCommunicationServer::~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//
73bool
Greg Claytoncb8977d2011-03-23 00:09:55 +000074GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr,
Greg Clayton58e26e02011-03-24 04:28:38 +000075 Error &error,
Greg Claytoncb8977d2011-03-23 00:09:55 +000076 bool &interrupt,
77 bool &quit)
Greg Clayton61d043b2011-03-22 04:00:09 +000078{
79 StringExtractorGDBRemote packet;
Greg Claytoncb8977d2011-03-23 00:09:55 +000080 if (WaitForPacketNoLock (packet, timeout_ptr))
Greg Clayton61d043b2011-03-22 04:00:09 +000081 {
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:
Greg Clayton58e26e02011-03-24 04:28:38 +000090 error.SetErrorString("invalid packet");
Greg Claytoncb8977d2011-03-23 00:09:55 +000091 quit = true;
92 break;
93
94 case StringExtractorGDBRemote::eServerPacketType_interrupt:
Greg Clayton58e26e02011-03-24 04:28:38 +000095 error.SetErrorString("interrupt received");
Greg Claytoncb8977d2011-03-23 00:09:55 +000096 interrupt = true;
97 break;
98
Greg Clayton61d043b2011-03-22 04:00:09 +000099 case StringExtractorGDBRemote::eServerPacketType_unimplemented:
Greg Clayton24bc5d92011-03-30 18:16:51 +0000100 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000101
102 case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
Greg Clayton24bc5d92011-03-30 18:16:51 +0000103 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
Greg Clayton06d7cc82011-04-04 18:18:57 +0000120 case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
121 return Handle_qSpeedTest (packet);
Greg Clayton58e26e02011-03-24 04:28:38 +0000122 case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
Greg Clayton24bc5d92011-03-30 18:16:51 +0000123 return Handle_QStartNoAckMode (packet);
Greg Clayton61d043b2011-03-22 04:00:09 +0000124 }
125 return true;
126 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000127 else
128 {
129 if (!IsConnected())
130 error.SetErrorString("lost connection");
131 else
132 error.SetErrorString("timeout");
133 }
134
Greg Clayton61d043b2011-03-22 04:00:09 +0000135 return false;
136}
137
138size_t
Greg Clayton24bc5d92011-03-30 18:16:51 +0000139GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
Greg Clayton61d043b2011-03-22 04:00:09 +0000140{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000141 // TODO: Log the packet we aren't handling...
Greg Clayton61d043b2011-03-22 04:00:09 +0000142 return SendPacket ("");
143}
144
Greg Clayton58e26e02011-03-24 04:28:38 +0000145size_t
Greg Clayton24bc5d92011-03-30 18:16:51 +0000146GDBRemoteCommunicationServer::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
155size_t
Greg Clayton58e26e02011-03-24 04:28:38 +0000156GDBRemoteCommunicationServer::SendOKResponse ()
157{
158 return SendPacket ("OK");
159}
160
161bool
162GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
163{
164 if (StartReadThread(error_ptr))
165 return GetAck();
166 return false;
167}
Greg Clayton61d043b2011-03-22 04:00:09 +0000168
169bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000170GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
Greg Clayton61d043b2011-03-22 04:00:09 +0000171{
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 ());
Greg Clayton61d043b2011-03-22 04:00:09 +0000177 const llvm::Triple &host_triple = host_arch.GetTriple();
Greg Clayton58e26e02011-03-24 04:28:38 +0000178 response.PutCString("triple:");
179 response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
180 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
Greg Clayton61d043b2011-03-22 04:00:09 +0000181
Greg Clayton58e26e02011-03-24 04:28:38 +0000182 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
Greg Clayton61d043b2011-03-22 04:00:09 +0000189 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
Greg Clayton58e26e02011-03-24 04:28:38 +0000197 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
Greg Clayton24bc5d92011-03-30 18:16:51 +0000235 return SendPacket (response) > 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000236}
Greg Clayton58e26e02011-03-24 04:28:38 +0000237
Greg Clayton24bc5d92011-03-30 18:16:51 +0000238static void
239CreateProcessInfoResponse (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}
Greg Clayton58e26e02011-03-24 04:28:38 +0000260
261bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000262GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
Greg Clayton58e26e02011-03-24 04:28:38 +0000263{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000264 // 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
280bool
281GDBRemoteCommunicationServer::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 {
Greg Claytonf15996e2011-04-07 22:46:35 +0000360 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000361 }
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
381bool
382GDBRemoteCommunicationServer::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
394bool
395GDBRemoteCommunicationServer::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
414bool
415GDBRemoteCommunicationServer::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
433bool
Greg Clayton06d7cc82011-04-04 18:18:57 +0000434GDBRemoteCommunicationServer::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}
469bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000470GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
471{
472 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton58e26e02011-03-24 04:28:38 +0000473 SendOKResponse ();
474 m_send_acks = false;
475 return true;
476}