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