blob: 0619c10765571918bc7e1c138e4bdbcee60d6f25 [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 Clayton63afdb02011-06-17 01:22:15 +000081GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
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 Clayton63afdb02011-06-17 01:22:15 +000087 if (WaitForPacketWithTimeoutMicroSeconds(packet, timeout_usec))
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{
Greg Clayton63afdb02011-06-17 01:22:15 +0000202 return GetAck();
Greg Clayton58e26e02011-03-24 04:28:38 +0000203}
Greg Clayton61d043b2011-03-22 04:00:09 +0000204
205bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000206GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
Greg Clayton61d043b2011-03-22 04:00:09 +0000207{
208 StreamString response;
209
210 // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
211
212 ArchSpec host_arch (Host::GetArchitecture ());
Greg Clayton61d043b2011-03-22 04:00:09 +0000213 const llvm::Triple &host_triple = host_arch.GetTriple();
Greg Clayton58e26e02011-03-24 04:28:38 +0000214 response.PutCString("triple:");
215 response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
216 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
Greg Clayton61d043b2011-03-22 04:00:09 +0000217
Greg Clayton58e26e02011-03-24 04:28:38 +0000218 uint32_t cpu = host_arch.GetMachOCPUType();
219 uint32_t sub = host_arch.GetMachOCPUSubType();
220 if (cpu != LLDB_INVALID_CPUTYPE)
221 response.Printf ("cputype:%u;", cpu);
222 if (sub != LLDB_INVALID_CPUTYPE)
223 response.Printf ("cpusubtype:%u;", sub);
224
Greg Clayton61d043b2011-03-22 04:00:09 +0000225 switch (lldb::endian::InlHostByteOrder())
226 {
227 case eByteOrderBig: response.PutCString ("endian:big;"); break;
228 case eByteOrderLittle: response.PutCString ("endian:little;"); break;
229 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
230 default: response.PutCString ("endian:unknown;"); break;
231 }
232
Greg Clayton58e26e02011-03-24 04:28:38 +0000233 uint32_t major = UINT32_MAX;
234 uint32_t minor = UINT32_MAX;
235 uint32_t update = UINT32_MAX;
236 if (Host::GetOSVersion (major, minor, update))
237 {
238 if (major != UINT32_MAX)
239 {
240 response.Printf("os_version:%u", major);
241 if (minor != UINT32_MAX)
242 {
243 response.Printf(".%u", minor);
244 if (update != UINT32_MAX)
245 response.Printf(".%u", update);
246 }
247 response.PutChar(';');
248 }
249 }
250
251 std::string s;
252 if (Host::GetOSBuildString (s))
253 {
254 response.PutCString ("os_build:");
255 response.PutCStringAsRawHex8(s.c_str());
256 response.PutChar(';');
257 }
258 if (Host::GetOSKernelDescription (s))
259 {
260 response.PutCString ("os_kernel:");
261 response.PutCStringAsRawHex8(s.c_str());
262 response.PutChar(';');
263 }
264 if (Host::GetHostname (s))
265 {
266 response.PutCString ("hostname:");
267 response.PutCStringAsRawHex8(s.c_str());
268 response.PutChar(';');
269 }
270
Greg Clayton24bc5d92011-03-30 18:16:51 +0000271 return SendPacket (response) > 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000272}
Greg Clayton58e26e02011-03-24 04:28:38 +0000273
Greg Clayton24bc5d92011-03-30 18:16:51 +0000274static void
Greg Claytonb72d0f02011-04-12 05:54:46 +0000275CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000276{
277 response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;",
278 proc_info.GetProcessID(),
279 proc_info.GetParentProcessID(),
Greg Claytonb72d0f02011-04-12 05:54:46 +0000280 proc_info.GetUserID(),
281 proc_info.GetGroupID(),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000282 proc_info.GetEffectiveUserID(),
283 proc_info.GetEffectiveGroupID());
284 response.PutCString ("name:");
285 response.PutCStringAsRawHex8(proc_info.GetName());
286 response.PutChar(';');
287 const ArchSpec &proc_arch = proc_info.GetArchitecture();
288 if (proc_arch.IsValid())
289 {
290 const llvm::Triple &proc_triple = proc_arch.GetTriple();
291 response.PutCString("triple:");
292 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
293 response.PutChar(';');
294 }
295}
Greg Clayton58e26e02011-03-24 04:28:38 +0000296
297bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000298GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
Greg Clayton58e26e02011-03-24 04:28:38 +0000299{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000300 // Packet format: "qProcessInfoPID:%i" where %i is the pid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000301 packet.SetFilePos(::strlen ("qProcessInfoPID:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000302 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
303 if (pid != LLDB_INVALID_PROCESS_ID)
304 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000305 ProcessInstanceInfo proc_info;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000306 if (Host::GetProcessInfo(pid, proc_info))
307 {
308 StreamString response;
309 CreateProcessInfoResponse (proc_info, response);
310 return SendPacket (response);
311 }
312 }
313 return SendErrorResponse (1);
314}
315
316bool
317GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
318{
319 m_proc_infos_index = 0;
320 m_proc_infos.Clear();
321
Greg Claytonb72d0f02011-04-12 05:54:46 +0000322 ProcessInstanceInfoMatch match_info;
323 packet.SetFilePos(::strlen ("qfProcessInfo"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000324 if (packet.GetChar() == ':')
325 {
326
327 std::string key;
328 std::string value;
329 while (packet.GetNameColonValue(key, value))
330 {
331 bool success = true;
332 if (key.compare("name") == 0)
333 {
334 StringExtractor extractor;
335 extractor.GetStringRef().swap(value);
336 extractor.GetHexByteString (value);
337 match_info.GetProcessInfo().SetName (value.c_str());
338 }
339 else if (key.compare("name_match") == 0)
340 {
341 if (value.compare("equals") == 0)
342 {
343 match_info.SetNameMatchType (eNameMatchEquals);
344 }
345 else if (value.compare("starts_with") == 0)
346 {
347 match_info.SetNameMatchType (eNameMatchStartsWith);
348 }
349 else if (value.compare("ends_with") == 0)
350 {
351 match_info.SetNameMatchType (eNameMatchEndsWith);
352 }
353 else if (value.compare("contains") == 0)
354 {
355 match_info.SetNameMatchType (eNameMatchContains);
356 }
357 else if (value.compare("regex") == 0)
358 {
359 match_info.SetNameMatchType (eNameMatchRegularExpression);
360 }
361 else
362 {
363 success = false;
364 }
365 }
366 else if (key.compare("pid") == 0)
367 {
368 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
369 }
370 else if (key.compare("parent_pid") == 0)
371 {
372 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
373 }
374 else if (key.compare("uid") == 0)
375 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000376 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000377 }
378 else if (key.compare("gid") == 0)
379 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000380 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000381 }
382 else if (key.compare("euid") == 0)
383 {
384 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
385 }
386 else if (key.compare("egid") == 0)
387 {
388 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
389 }
390 else if (key.compare("all_users") == 0)
391 {
392 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
393 }
394 else if (key.compare("triple") == 0)
395 {
Greg Claytonf15996e2011-04-07 22:46:35 +0000396 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000397 }
398 else
399 {
400 success = false;
401 }
402
403 if (!success)
404 return SendErrorResponse (2);
405 }
406 }
407
408 if (Host::FindProcesses (match_info, m_proc_infos))
409 {
410 // We found something, return the first item by calling the get
411 // subsequent process info packet handler...
412 return Handle_qsProcessInfo (packet);
413 }
414 return SendErrorResponse (3);
415}
416
417bool
418GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
419{
420 if (m_proc_infos_index < m_proc_infos.GetSize())
421 {
422 StreamString response;
423 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
424 ++m_proc_infos_index;
425 return SendPacket (response);
426 }
427 return SendErrorResponse (4);
428}
429
430bool
431GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
432{
433 // Packet format: "qUserName:%i" where %i is the uid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000434 packet.SetFilePos(::strlen ("qUserName:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000435 uint32_t uid = packet.GetU32 (UINT32_MAX);
436 if (uid != UINT32_MAX)
437 {
438 std::string name;
439 if (Host::GetUserName (uid, name))
440 {
441 StreamString response;
442 response.PutCStringAsRawHex8 (name.c_str());
443 return SendPacket (response);
444 }
445 }
446 return SendErrorResponse (5);
447
448}
449
450bool
451GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
452{
453 // Packet format: "qGroupName:%i" where %i is the gid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000454 packet.SetFilePos(::strlen ("qGroupName:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000455 uint32_t gid = packet.GetU32 (UINT32_MAX);
456 if (gid != UINT32_MAX)
457 {
458 std::string name;
459 if (Host::GetGroupName (gid, name))
460 {
461 StreamString response;
462 response.PutCStringAsRawHex8 (name.c_str());
463 return SendPacket (response);
464 }
465 }
466 return SendErrorResponse (6);
467}
468
469bool
Greg Clayton06d7cc82011-04-04 18:18:57 +0000470GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
471{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000472 packet.SetFilePos(::strlen ("qSpeedTest:"));
Greg Clayton06d7cc82011-04-04 18:18:57 +0000473
474 std::string key;
475 std::string value;
476 bool success = packet.GetNameColonValue(key, value);
477 if (success && key.compare("response_size") == 0)
478 {
479 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
480 if (success)
481 {
482 if (response_size == 0)
483 return SendOKResponse();
484 StreamString response;
485 uint32_t bytes_left = response_size;
486 response.PutCString("data:");
487 while (bytes_left > 0)
488 {
489 if (bytes_left >= 26)
490 {
491 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
492 bytes_left -= 26;
493 }
494 else
495 {
496 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
497 bytes_left = 0;
498 }
499 }
500 return SendPacket (response);
501 }
502 }
503 return SendErrorResponse (7);
504}
Greg Claytonb72d0f02011-04-12 05:54:46 +0000505
506
507static void *
508AcceptPortFromInferior (void *arg)
509{
510 const char *connect_url = (const char *)arg;
511 ConnectionFileDescriptor file_conn;
512 Error error;
513 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
514 {
515 char pid_str[256];
516 ::memset (pid_str, 0, sizeof(pid_str));
517 ConnectionStatus status;
Greg Clayton63afdb02011-06-17 01:22:15 +0000518 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), NULL, status, NULL);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000519 if (pid_str_len > 0)
520 {
521 int pid = atoi (pid_str);
522 return (void *)(intptr_t)pid;
523 }
524 }
525 return NULL;
526}
527//
528//static bool
529//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
530//{
531// const int time_delta_usecs = 100000;
532// const int num_retries = timeout_in_seconds/time_delta_usecs;
533// for (int i=0; i<num_retries; i++)
534// {
535// struct proc_bsdinfo bsd_info;
536// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
537// (uint64_t) 0,
538// &bsd_info,
539// PROC_PIDTBSDINFO_SIZE);
540//
541// switch (error)
542// {
543// case EINVAL:
544// case ENOTSUP:
545// case ESRCH:
546// case EPERM:
547// return false;
548//
549// default:
550// break;
551//
552// case 0:
553// if (bsd_info.pbi_status == SSTOP)
554// return true;
555// }
556// ::usleep (time_delta_usecs);
557// }
558// return false;
559//}
560
561bool
562GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
563{
564 // The 'A' packet is the most over designed packet ever here with
565 // redundant argument indexes, redundant argument lengths and needed hex
566 // encoded argument string values. Really all that is needed is a comma
567 // separated hex encoded argument value list, but we will stay true to the
568 // documented version of the 'A' packet here...
569
570 packet.SetFilePos(1); // Skip the 'A'
571 bool success = true;
572 while (success && packet.GetBytesLeft() > 0)
573 {
574 // Decode the decimal argument string length. This length is the
575 // number of hex nibbles in the argument string value.
576 const uint32_t arg_len = packet.GetU32(UINT32_MAX);
577 if (arg_len == UINT32_MAX)
578 success = false;
579 else
580 {
581 // Make sure the argument hex string length is followed by a comma
582 if (packet.GetChar() != ',')
583 success = false;
584 else
585 {
586 // Decode the argument index. We ignore this really becuase
587 // who would really send down the arguments in a random order???
588 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
589 if (arg_idx == UINT32_MAX)
590 success = false;
591 else
592 {
593 // Make sure the argument index is followed by a comma
594 if (packet.GetChar() != ',')
595 success = false;
596 else
597 {
598 // Decode the argument string value from hex bytes
599 // back into a UTF8 string and make sure the length
600 // matches the one supplied in the packet
601 std::string arg;
602 if (packet.GetHexByteString(arg) != (arg_len / 2))
603 success = false;
604 else
605 {
606 // If there are any bytes lft
607 if (packet.GetBytesLeft())
608 {
609 if (packet.GetChar() != ',')
610 success = false;
611 }
612
613 if (success)
614 {
615 if (arg_idx == 0)
616 m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
617 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
618 }
619 }
620 }
621 }
622 }
623 }
624 }
625
626 if (success)
627 {
628 m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
629 m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
630 if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
631 {
632 return SendOKResponse ();
633 }
634 }
635 return SendErrorResponse (8);
636}
637
638bool
639GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
640{
641 lldb::pid_t pid = m_process_launch_info.GetProcessID();
642 StreamString response;
643 response.Printf("QC%x", pid);
644 if (m_is_platform)
645 {
646 // If we launch a process and this GDB server is acting as a platform,
647 // then we need to clear the process launch state so we can start
648 // launching another process. In order to launch a process a bunch or
649 // packets need to be sent: environment packets, working directory,
650 // disable ASLR, and many more settings. When we launch a process we
651 // then need to know when to clear this information. Currently we are
652 // selecting the 'qC' packet as that packet which seems to make the most
653 // sense.
654 if (pid != LLDB_INVALID_PROCESS_ID)
655 {
656 m_process_launch_info.Clear();
657 }
658 }
659 return SendPacket (response);
660}
661
662bool
663GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
664{
665 // Spawn a local debugserver as a platform so we can then attach or launch
666 // a process...
667
668 if (m_is_platform)
669 {
670 // Sleep and wait a bit for debugserver to start to listen...
671 ConnectionFileDescriptor file_conn;
672 char connect_url[PATH_MAX];
673 Error error;
674 char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
675 if (::mktemp (unix_socket_name) == NULL)
676 {
677 error.SetErrorString ("failed to make temporary path for a unix socket");
678 }
679 else
680 {
681 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
682 // Spawn a new thread to accept the port that gets bound after
683 // binding to port 0 (zero).
684 lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
685 AcceptPortFromInferior,
686 connect_url,
687 &error);
688
689 if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
690 {
691 // Spawn a debugserver and try to get
692 ProcessLaunchInfo debugserver_launch_info;
693 error = StartDebugserverProcess ("localhost:0",
694 unix_socket_name,
695 debugserver_launch_info);
696
697 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
698 if (error.Success())
699 {
700 bool success = false;
701
702 thread_result_t accept_thread_result = NULL;
703 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
704 {
705 if (accept_thread_result)
706 {
707 uint16_t port = (intptr_t)accept_thread_result;
708 char response[256];
709 const int response_len = ::snprintf (response, sizeof(response), "pid:%u;port:%u;", debugserver_pid, port);
710 assert (response_len < sizeof(response));
711 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
712 success = SendPacket (response, response_len) > 0;
713 }
714 }
715 ::unlink (unix_socket_name);
716
717 if (!success)
718 {
719 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
720 ::kill (debugserver_pid, SIGINT);
721 }
722 return success;
723 }
724 }
725 }
726 }
727 return SendErrorResponse (13);
728}
729
730bool
731GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
732{
733 if (m_process_launch_error.Success())
734 return SendOKResponse();
735 StreamString response;
736 response.PutChar('E');
737 response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
738 return SendPacket (response);
739}
740
741bool
742GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
743{
744 packet.SetFilePos(::strlen ("QEnvironment:"));
745 const uint32_t bytes_left = packet.GetBytesLeft();
746 if (bytes_left > 0)
747 {
748 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
749 return SendOKResponse ();
750 }
751 return SendErrorResponse (9);
752}
753
754bool
755GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
756{
757 packet.SetFilePos(::strlen ("QSetDisableASLR:"));
758 if (packet.GetU32(0))
759 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
760 else
761 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
762 return SendOKResponse ();
763}
764
765bool
766GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
767{
768 packet.SetFilePos(::strlen ("QSetWorkingDir:"));
769 std::string path;
770 packet.GetHexByteString(path);
771 m_process_launch_info.SwapWorkingDirectory (path);
772 return SendOKResponse ();
773}
774
775bool
776GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
777{
778 packet.SetFilePos(::strlen ("QSetSTDIN:"));
779 ProcessLaunchInfo::FileAction file_action;
780 std::string path;
781 packet.GetHexByteString(path);
782 const bool read = false;
783 const bool write = true;
784 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
785 {
786 m_process_launch_info.AppendFileAction(file_action);
787 return SendOKResponse ();
788 }
789 return SendErrorResponse (10);
790}
791
792bool
793GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
794{
795 packet.SetFilePos(::strlen ("QSetSTDOUT:"));
796 ProcessLaunchInfo::FileAction file_action;
797 std::string path;
798 packet.GetHexByteString(path);
799 const bool read = true;
800 const bool write = false;
801 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
802 {
803 m_process_launch_info.AppendFileAction(file_action);
804 return SendOKResponse ();
805 }
806 return SendErrorResponse (11);
807}
808
809bool
810GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
811{
812 packet.SetFilePos(::strlen ("QSetSTDERR:"));
813 ProcessLaunchInfo::FileAction file_action;
814 std::string path;
815 packet.GetHexByteString(path);
816 const bool read = true;
817 const bool write = true;
818 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
819 {
820 m_process_launch_info.AppendFileAction(file_action);
821 return SendOKResponse ();
822 }
823 return SendErrorResponse (12);
824}
825
Greg Clayton06d7cc82011-04-04 18:18:57 +0000826bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000827GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
828{
829 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton58e26e02011-03-24 04:28:38 +0000830 SendOKResponse ();
831 m_send_acks = false;
832 return true;
833}