blob: 9379077335d87e882bdd480627b4fa5ab0c42ca0 [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"
Greg Claytonb72d0f02011-04-12 05:54:46 +000024#include "lldb/Target/Process.h"
Greg Clayton61d043b2011-03-22 04:00:09 +000025
26// Project includes
27#include "Utility/StringExtractorGDBRemote.h"
28#include "ProcessGDBRemote.h"
29#include "ProcessGDBRemoteLog.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
34//----------------------------------------------------------------------
35// GDBRemoteCommunicationServer constructor
36//----------------------------------------------------------------------
Greg Claytonb72d0f02011-04-12 05:54:46 +000037GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
38 GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
39 m_async_thread (LLDB_INVALID_HOST_THREAD),
40 m_process_launch_info (),
41 m_process_launch_error (),
42 m_proc_infos (),
43 m_proc_infos_index (0),
44 m_lo_port_num (0),
45 m_hi_port_num (0)
Greg Clayton61d043b2011-03-22 04:00:09 +000046{
47}
48
49//----------------------------------------------------------------------
50// Destructor
51//----------------------------------------------------------------------
52GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
53{
54}
55
56
57//void *
58//GDBRemoteCommunicationServer::AsyncThread (void *arg)
59//{
60// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
61//
62// LogSP log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
63// if (log)
64// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
65//
66// StringExtractorGDBRemote packet;
67//
68// while ()
69// {
70// if (packet.
71// }
72//
73// if (log)
74// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
75//
76// process->m_async_thread = LLDB_INVALID_HOST_THREAD;
77// return NULL;
78//}
79//
80bool
Greg Claytoncb8977d2011-03-23 00:09:55 +000081GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr,
Greg Clayton58e26e02011-03-24 04:28:38 +000082 Error &error,
Greg Claytoncb8977d2011-03-23 00:09:55 +000083 bool &interrupt,
84 bool &quit)
Greg Clayton61d043b2011-03-22 04:00:09 +000085{
86 StringExtractorGDBRemote packet;
Greg Claytoncb8977d2011-03-23 00:09:55 +000087 if (WaitForPacketNoLock (packet, timeout_ptr))
Greg Clayton61d043b2011-03-22 04:00:09 +000088 {
89 const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
90 switch (packet_type)
91 {
Greg Claytonb72d0f02011-04-12 05:54:46 +000092 case StringExtractorGDBRemote::eServerPacketType_nack:
93 case StringExtractorGDBRemote::eServerPacketType_ack:
94 break;
Greg Clayton61d043b2011-03-22 04:00:09 +000095
Greg Claytonb72d0f02011-04-12 05:54:46 +000096 case StringExtractorGDBRemote::eServerPacketType_invalid:
97 error.SetErrorString("invalid packet");
98 quit = true;
99 break;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000100
Greg Claytonb72d0f02011-04-12 05:54:46 +0000101 case StringExtractorGDBRemote::eServerPacketType_interrupt:
102 error.SetErrorString("interrupt received");
103 interrupt = true;
104 break;
105
106 case StringExtractorGDBRemote::eServerPacketType_unimplemented:
107 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000108
Greg Claytonb72d0f02011-04-12 05:54:46 +0000109 case StringExtractorGDBRemote::eServerPacketType_A:
110 return Handle_A (packet);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000111
Greg Claytonb72d0f02011-04-12 05:54:46 +0000112 case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
113 return Handle_qfProcessInfo (packet);
114
115 case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
116 return Handle_qsProcessInfo (packet);
117
118 case StringExtractorGDBRemote::eServerPacketType_qC:
119 return Handle_qC (packet);
120
121 case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
122 return Handle_qHostInfo (packet);
123
124 case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
125 return Handle_qLaunchGDBServer (packet);
126
127 case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
128 return Handle_qLaunchSuccess (packet);
129
130 case StringExtractorGDBRemote::eServerPacketType_qGroupName:
131 return Handle_qGroupName (packet);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000132
Greg Claytonb72d0f02011-04-12 05:54:46 +0000133 case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
134 return Handle_qProcessInfoPID (packet);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000135
Greg Claytonb72d0f02011-04-12 05:54:46 +0000136 case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
137 return Handle_qSpeedTest (packet);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000138
Greg Claytonb72d0f02011-04-12 05:54:46 +0000139 case StringExtractorGDBRemote::eServerPacketType_qUserName:
140 return Handle_qUserName (packet);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000141
Greg Claytonb72d0f02011-04-12 05:54:46 +0000142 case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
143 return Handle_QEnvironment (packet);
144
145 case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
146 return Handle_QSetDisableASLR (packet);
147
148 case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
149 return Handle_QSetSTDIN (packet);
150
151 case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
152 return Handle_QSetSTDOUT (packet);
153
154 case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
155 return Handle_QSetSTDERR (packet);
156
157 case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
158 return Handle_QSetWorkingDir (packet);
159
160 case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
161 return Handle_QStartNoAckMode (packet);
Greg Clayton61d043b2011-03-22 04:00:09 +0000162 }
163 return true;
164 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000165 else
166 {
167 if (!IsConnected())
168 error.SetErrorString("lost connection");
169 else
170 error.SetErrorString("timeout");
171 }
172
Greg Clayton61d043b2011-03-22 04:00:09 +0000173 return false;
174}
175
176size_t
Greg Clayton24bc5d92011-03-30 18:16:51 +0000177GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
Greg Clayton61d043b2011-03-22 04:00:09 +0000178{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000179 // TODO: Log the packet we aren't handling...
Greg Clayton61d043b2011-03-22 04:00:09 +0000180 return SendPacket ("");
181}
182
Greg Clayton58e26e02011-03-24 04:28:38 +0000183size_t
Greg Clayton24bc5d92011-03-30 18:16:51 +0000184GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
185{
186 char packet[16];
187 int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
188 assert (packet_len < sizeof(packet));
189 return SendPacket (packet, packet_len);
190}
191
192
193size_t
Greg Clayton58e26e02011-03-24 04:28:38 +0000194GDBRemoteCommunicationServer::SendOKResponse ()
195{
196 return SendPacket ("OK");
197}
198
199bool
200GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
201{
202 if (StartReadThread(error_ptr))
203 return GetAck();
204 return false;
205}
Greg Clayton61d043b2011-03-22 04:00:09 +0000206
207bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000208GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
Greg Clayton61d043b2011-03-22 04:00:09 +0000209{
210 StreamString response;
211
212 // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
213
214 ArchSpec host_arch (Host::GetArchitecture ());
Greg Clayton61d043b2011-03-22 04:00:09 +0000215 const llvm::Triple &host_triple = host_arch.GetTriple();
Greg Clayton58e26e02011-03-24 04:28:38 +0000216 response.PutCString("triple:");
217 response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
218 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
Greg Clayton61d043b2011-03-22 04:00:09 +0000219
Greg Clayton58e26e02011-03-24 04:28:38 +0000220 uint32_t cpu = host_arch.GetMachOCPUType();
221 uint32_t sub = host_arch.GetMachOCPUSubType();
222 if (cpu != LLDB_INVALID_CPUTYPE)
223 response.Printf ("cputype:%u;", cpu);
224 if (sub != LLDB_INVALID_CPUTYPE)
225 response.Printf ("cpusubtype:%u;", sub);
226
Greg Clayton61d043b2011-03-22 04:00:09 +0000227 switch (lldb::endian::InlHostByteOrder())
228 {
229 case eByteOrderBig: response.PutCString ("endian:big;"); break;
230 case eByteOrderLittle: response.PutCString ("endian:little;"); break;
231 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
232 default: response.PutCString ("endian:unknown;"); break;
233 }
234
Greg Clayton58e26e02011-03-24 04:28:38 +0000235 uint32_t major = UINT32_MAX;
236 uint32_t minor = UINT32_MAX;
237 uint32_t update = UINT32_MAX;
238 if (Host::GetOSVersion (major, minor, update))
239 {
240 if (major != UINT32_MAX)
241 {
242 response.Printf("os_version:%u", major);
243 if (minor != UINT32_MAX)
244 {
245 response.Printf(".%u", minor);
246 if (update != UINT32_MAX)
247 response.Printf(".%u", update);
248 }
249 response.PutChar(';');
250 }
251 }
252
253 std::string s;
254 if (Host::GetOSBuildString (s))
255 {
256 response.PutCString ("os_build:");
257 response.PutCStringAsRawHex8(s.c_str());
258 response.PutChar(';');
259 }
260 if (Host::GetOSKernelDescription (s))
261 {
262 response.PutCString ("os_kernel:");
263 response.PutCStringAsRawHex8(s.c_str());
264 response.PutChar(';');
265 }
266 if (Host::GetHostname (s))
267 {
268 response.PutCString ("hostname:");
269 response.PutCStringAsRawHex8(s.c_str());
270 response.PutChar(';');
271 }
272
Greg Clayton24bc5d92011-03-30 18:16:51 +0000273 return SendPacket (response) > 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000274}
Greg Clayton58e26e02011-03-24 04:28:38 +0000275
Greg Clayton24bc5d92011-03-30 18:16:51 +0000276static void
Greg Claytonb72d0f02011-04-12 05:54:46 +0000277CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000278{
279 response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;",
280 proc_info.GetProcessID(),
281 proc_info.GetParentProcessID(),
Greg Claytonb72d0f02011-04-12 05:54:46 +0000282 proc_info.GetUserID(),
283 proc_info.GetGroupID(),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000284 proc_info.GetEffectiveUserID(),
285 proc_info.GetEffectiveGroupID());
286 response.PutCString ("name:");
287 response.PutCStringAsRawHex8(proc_info.GetName());
288 response.PutChar(';');
289 const ArchSpec &proc_arch = proc_info.GetArchitecture();
290 if (proc_arch.IsValid())
291 {
292 const llvm::Triple &proc_triple = proc_arch.GetTriple();
293 response.PutCString("triple:");
294 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
295 response.PutChar(';');
296 }
297}
Greg Clayton58e26e02011-03-24 04:28:38 +0000298
299bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000300GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
Greg Clayton58e26e02011-03-24 04:28:38 +0000301{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000302 // Packet format: "qProcessInfoPID:%i" where %i is the pid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000303 packet.SetFilePos(::strlen ("qProcessInfoPID:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000304 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
305 if (pid != LLDB_INVALID_PROCESS_ID)
306 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000307 ProcessInstanceInfo proc_info;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000308 if (Host::GetProcessInfo(pid, proc_info))
309 {
310 StreamString response;
311 CreateProcessInfoResponse (proc_info, response);
312 return SendPacket (response);
313 }
314 }
315 return SendErrorResponse (1);
316}
317
318bool
319GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
320{
321 m_proc_infos_index = 0;
322 m_proc_infos.Clear();
323
Greg Claytonb72d0f02011-04-12 05:54:46 +0000324 ProcessInstanceInfoMatch match_info;
325 packet.SetFilePos(::strlen ("qfProcessInfo"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000326 if (packet.GetChar() == ':')
327 {
328
329 std::string key;
330 std::string value;
331 while (packet.GetNameColonValue(key, value))
332 {
333 bool success = true;
334 if (key.compare("name") == 0)
335 {
336 StringExtractor extractor;
337 extractor.GetStringRef().swap(value);
338 extractor.GetHexByteString (value);
339 match_info.GetProcessInfo().SetName (value.c_str());
340 }
341 else if (key.compare("name_match") == 0)
342 {
343 if (value.compare("equals") == 0)
344 {
345 match_info.SetNameMatchType (eNameMatchEquals);
346 }
347 else if (value.compare("starts_with") == 0)
348 {
349 match_info.SetNameMatchType (eNameMatchStartsWith);
350 }
351 else if (value.compare("ends_with") == 0)
352 {
353 match_info.SetNameMatchType (eNameMatchEndsWith);
354 }
355 else if (value.compare("contains") == 0)
356 {
357 match_info.SetNameMatchType (eNameMatchContains);
358 }
359 else if (value.compare("regex") == 0)
360 {
361 match_info.SetNameMatchType (eNameMatchRegularExpression);
362 }
363 else
364 {
365 success = false;
366 }
367 }
368 else if (key.compare("pid") == 0)
369 {
370 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
371 }
372 else if (key.compare("parent_pid") == 0)
373 {
374 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
375 }
376 else if (key.compare("uid") == 0)
377 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000378 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000379 }
380 else if (key.compare("gid") == 0)
381 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000382 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000383 }
384 else if (key.compare("euid") == 0)
385 {
386 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
387 }
388 else if (key.compare("egid") == 0)
389 {
390 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
391 }
392 else if (key.compare("all_users") == 0)
393 {
394 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
395 }
396 else if (key.compare("triple") == 0)
397 {
Greg Claytonf15996e2011-04-07 22:46:35 +0000398 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000399 }
400 else
401 {
402 success = false;
403 }
404
405 if (!success)
406 return SendErrorResponse (2);
407 }
408 }
409
410 if (Host::FindProcesses (match_info, m_proc_infos))
411 {
412 // We found something, return the first item by calling the get
413 // subsequent process info packet handler...
414 return Handle_qsProcessInfo (packet);
415 }
416 return SendErrorResponse (3);
417}
418
419bool
420GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
421{
422 if (m_proc_infos_index < m_proc_infos.GetSize())
423 {
424 StreamString response;
425 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
426 ++m_proc_infos_index;
427 return SendPacket (response);
428 }
429 return SendErrorResponse (4);
430}
431
432bool
433GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
434{
435 // Packet format: "qUserName:%i" where %i is the uid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000436 packet.SetFilePos(::strlen ("qUserName:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000437 uint32_t uid = packet.GetU32 (UINT32_MAX);
438 if (uid != UINT32_MAX)
439 {
440 std::string name;
441 if (Host::GetUserName (uid, name))
442 {
443 StreamString response;
444 response.PutCStringAsRawHex8 (name.c_str());
445 return SendPacket (response);
446 }
447 }
448 return SendErrorResponse (5);
449
450}
451
452bool
453GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
454{
455 // Packet format: "qGroupName:%i" where %i is the gid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000456 packet.SetFilePos(::strlen ("qGroupName:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000457 uint32_t gid = packet.GetU32 (UINT32_MAX);
458 if (gid != UINT32_MAX)
459 {
460 std::string name;
461 if (Host::GetGroupName (gid, name))
462 {
463 StreamString response;
464 response.PutCStringAsRawHex8 (name.c_str());
465 return SendPacket (response);
466 }
467 }
468 return SendErrorResponse (6);
469}
470
471bool
Greg Clayton06d7cc82011-04-04 18:18:57 +0000472GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
473{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000474 packet.SetFilePos(::strlen ("qSpeedTest:"));
Greg Clayton06d7cc82011-04-04 18:18:57 +0000475
476 std::string key;
477 std::string value;
478 bool success = packet.GetNameColonValue(key, value);
479 if (success && key.compare("response_size") == 0)
480 {
481 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
482 if (success)
483 {
484 if (response_size == 0)
485 return SendOKResponse();
486 StreamString response;
487 uint32_t bytes_left = response_size;
488 response.PutCString("data:");
489 while (bytes_left > 0)
490 {
491 if (bytes_left >= 26)
492 {
493 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
494 bytes_left -= 26;
495 }
496 else
497 {
498 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
499 bytes_left = 0;
500 }
501 }
502 return SendPacket (response);
503 }
504 }
505 return SendErrorResponse (7);
506}
Greg Claytonb72d0f02011-04-12 05:54:46 +0000507
508
509static void *
510AcceptPortFromInferior (void *arg)
511{
512 const char *connect_url = (const char *)arg;
513 ConnectionFileDescriptor file_conn;
514 Error error;
515 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
516 {
517 char pid_str[256];
518 ::memset (pid_str, 0, sizeof(pid_str));
519 ConnectionStatus status;
520 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
521 if (pid_str_len > 0)
522 {
523 int pid = atoi (pid_str);
524 return (void *)(intptr_t)pid;
525 }
526 }
527 return NULL;
528}
529//
530//static bool
531//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
532//{
533// const int time_delta_usecs = 100000;
534// const int num_retries = timeout_in_seconds/time_delta_usecs;
535// for (int i=0; i<num_retries; i++)
536// {
537// struct proc_bsdinfo bsd_info;
538// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
539// (uint64_t) 0,
540// &bsd_info,
541// PROC_PIDTBSDINFO_SIZE);
542//
543// switch (error)
544// {
545// case EINVAL:
546// case ENOTSUP:
547// case ESRCH:
548// case EPERM:
549// return false;
550//
551// default:
552// break;
553//
554// case 0:
555// if (bsd_info.pbi_status == SSTOP)
556// return true;
557// }
558// ::usleep (time_delta_usecs);
559// }
560// return false;
561//}
562
563bool
564GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
565{
566 // The 'A' packet is the most over designed packet ever here with
567 // redundant argument indexes, redundant argument lengths and needed hex
568 // encoded argument string values. Really all that is needed is a comma
569 // separated hex encoded argument value list, but we will stay true to the
570 // documented version of the 'A' packet here...
571
572 packet.SetFilePos(1); // Skip the 'A'
573 bool success = true;
574 while (success && packet.GetBytesLeft() > 0)
575 {
576 // Decode the decimal argument string length. This length is the
577 // number of hex nibbles in the argument string value.
578 const uint32_t arg_len = packet.GetU32(UINT32_MAX);
579 if (arg_len == UINT32_MAX)
580 success = false;
581 else
582 {
583 // Make sure the argument hex string length is followed by a comma
584 if (packet.GetChar() != ',')
585 success = false;
586 else
587 {
588 // Decode the argument index. We ignore this really becuase
589 // who would really send down the arguments in a random order???
590 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
591 if (arg_idx == UINT32_MAX)
592 success = false;
593 else
594 {
595 // Make sure the argument index is followed by a comma
596 if (packet.GetChar() != ',')
597 success = false;
598 else
599 {
600 // Decode the argument string value from hex bytes
601 // back into a UTF8 string and make sure the length
602 // matches the one supplied in the packet
603 std::string arg;
604 if (packet.GetHexByteString(arg) != (arg_len / 2))
605 success = false;
606 else
607 {
608 // If there are any bytes lft
609 if (packet.GetBytesLeft())
610 {
611 if (packet.GetChar() != ',')
612 success = false;
613 }
614
615 if (success)
616 {
617 if (arg_idx == 0)
618 m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
619 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
620 }
621 }
622 }
623 }
624 }
625 }
626 }
627
628 if (success)
629 {
630 m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
631 m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
632 if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
633 {
634 return SendOKResponse ();
635 }
636 }
637 return SendErrorResponse (8);
638}
639
640bool
641GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
642{
643 lldb::pid_t pid = m_process_launch_info.GetProcessID();
644 StreamString response;
645 response.Printf("QC%x", pid);
646 if (m_is_platform)
647 {
648 // If we launch a process and this GDB server is acting as a platform,
649 // then we need to clear the process launch state so we can start
650 // launching another process. In order to launch a process a bunch or
651 // packets need to be sent: environment packets, working directory,
652 // disable ASLR, and many more settings. When we launch a process we
653 // then need to know when to clear this information. Currently we are
654 // selecting the 'qC' packet as that packet which seems to make the most
655 // sense.
656 if (pid != LLDB_INVALID_PROCESS_ID)
657 {
658 m_process_launch_info.Clear();
659 }
660 }
661 return SendPacket (response);
662}
663
664bool
665GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
666{
667 // Spawn a local debugserver as a platform so we can then attach or launch
668 // a process...
669
670 if (m_is_platform)
671 {
672 // Sleep and wait a bit for debugserver to start to listen...
673 ConnectionFileDescriptor file_conn;
674 char connect_url[PATH_MAX];
675 Error error;
676 char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
677 if (::mktemp (unix_socket_name) == NULL)
678 {
679 error.SetErrorString ("failed to make temporary path for a unix socket");
680 }
681 else
682 {
683 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
684 // Spawn a new thread to accept the port that gets bound after
685 // binding to port 0 (zero).
686 lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
687 AcceptPortFromInferior,
688 connect_url,
689 &error);
690
691 if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
692 {
693 // Spawn a debugserver and try to get
694 ProcessLaunchInfo debugserver_launch_info;
695 error = StartDebugserverProcess ("localhost:0",
696 unix_socket_name,
697 debugserver_launch_info);
698
699 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
700 if (error.Success())
701 {
702 bool success = false;
703
704 thread_result_t accept_thread_result = NULL;
705 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
706 {
707 if (accept_thread_result)
708 {
709 uint16_t port = (intptr_t)accept_thread_result;
710 char response[256];
711 const int response_len = ::snprintf (response, sizeof(response), "pid:%u;port:%u;", debugserver_pid, port);
712 assert (response_len < sizeof(response));
713 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
714 success = SendPacket (response, response_len) > 0;
715 }
716 }
717 ::unlink (unix_socket_name);
718
719 if (!success)
720 {
721 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
722 ::kill (debugserver_pid, SIGINT);
723 }
724 return success;
725 }
726 }
727 }
728 }
729 return SendErrorResponse (13);
730}
731
732bool
733GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
734{
735 if (m_process_launch_error.Success())
736 return SendOKResponse();
737 StreamString response;
738 response.PutChar('E');
739 response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
740 return SendPacket (response);
741}
742
743bool
744GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
745{
746 packet.SetFilePos(::strlen ("QEnvironment:"));
747 const uint32_t bytes_left = packet.GetBytesLeft();
748 if (bytes_left > 0)
749 {
750 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
751 return SendOKResponse ();
752 }
753 return SendErrorResponse (9);
754}
755
756bool
757GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
758{
759 packet.SetFilePos(::strlen ("QSetDisableASLR:"));
760 if (packet.GetU32(0))
761 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
762 else
763 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
764 return SendOKResponse ();
765}
766
767bool
768GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
769{
770 packet.SetFilePos(::strlen ("QSetWorkingDir:"));
771 std::string path;
772 packet.GetHexByteString(path);
773 m_process_launch_info.SwapWorkingDirectory (path);
774 return SendOKResponse ();
775}
776
777bool
778GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
779{
780 packet.SetFilePos(::strlen ("QSetSTDIN:"));
781 ProcessLaunchInfo::FileAction file_action;
782 std::string path;
783 packet.GetHexByteString(path);
784 const bool read = false;
785 const bool write = true;
786 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
787 {
788 m_process_launch_info.AppendFileAction(file_action);
789 return SendOKResponse ();
790 }
791 return SendErrorResponse (10);
792}
793
794bool
795GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
796{
797 packet.SetFilePos(::strlen ("QSetSTDOUT:"));
798 ProcessLaunchInfo::FileAction file_action;
799 std::string path;
800 packet.GetHexByteString(path);
801 const bool read = true;
802 const bool write = false;
803 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
804 {
805 m_process_launch_info.AppendFileAction(file_action);
806 return SendOKResponse ();
807 }
808 return SendErrorResponse (11);
809}
810
811bool
812GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
813{
814 packet.SetFilePos(::strlen ("QSetSTDERR:"));
815 ProcessLaunchInfo::FileAction file_action;
816 std::string path;
817 packet.GetHexByteString(path);
818 const bool read = true;
819 const bool write = true;
820 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
821 {
822 m_process_launch_info.AppendFileAction(file_action);
823 return SendOKResponse ();
824 }
825 return SendErrorResponse (12);
826}
827
Greg Clayton06d7cc82011-04-04 18:18:57 +0000828bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000829GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
830{
831 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton58e26e02011-03-24 04:28:38 +0000832 SendOKResponse ();
833 m_send_acks = false;
834 return true;
835}