blob: 115d55774c71a143b748365ce195c175a54e69a9 [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 Clayton516f0842012-04-11 00:24:49 +000088 if (WaitForPacketWithTimeoutMicroSecondsNoLock (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 Clayton516f0842012-04-11 00:24:49 +0000181 return SendPacketNoLock ("", 0);
Greg Clayton61d043b2011-03-22 04:00:09 +0000182}
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));
Greg Clayton516f0842012-04-11 00:24:49 +0000190 return SendPacketNoLock (packet, packet_len);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000191}
192
193
194size_t
Greg Clayton58e26e02011-03-24 04:28:38 +0000195GDBRemoteCommunicationServer::SendOKResponse ()
196{
Greg Clayton516f0842012-04-11 00:24:49 +0000197 return SendPacketNoLock ("OK", 2);
Greg Clayton58e26e02011-03-24 04:28:38 +0000198}
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
Enrico Granata6adf91f2012-07-13 23:55:22 +0000226 if (cpu == ArchSpec::kCore_arm_any)
Enrico Granata7de2a3b2012-07-13 23:18:48 +0000227 response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
228 else
229 response.Printf("watchpoint_exceptions_received:after;");
230
Greg Clayton61d043b2011-03-22 04:00:09 +0000231 switch (lldb::endian::InlHostByteOrder())
232 {
233 case eByteOrderBig: response.PutCString ("endian:big;"); break;
234 case eByteOrderLittle: response.PutCString ("endian:little;"); break;
235 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
236 default: response.PutCString ("endian:unknown;"); break;
237 }
238
Greg Clayton58e26e02011-03-24 04:28:38 +0000239 uint32_t major = UINT32_MAX;
240 uint32_t minor = UINT32_MAX;
241 uint32_t update = UINT32_MAX;
242 if (Host::GetOSVersion (major, minor, update))
243 {
244 if (major != UINT32_MAX)
245 {
246 response.Printf("os_version:%u", major);
247 if (minor != UINT32_MAX)
248 {
249 response.Printf(".%u", minor);
250 if (update != UINT32_MAX)
251 response.Printf(".%u", update);
252 }
253 response.PutChar(';');
254 }
255 }
256
257 std::string s;
258 if (Host::GetOSBuildString (s))
259 {
260 response.PutCString ("os_build:");
261 response.PutCStringAsRawHex8(s.c_str());
262 response.PutChar(';');
263 }
264 if (Host::GetOSKernelDescription (s))
265 {
266 response.PutCString ("os_kernel:");
267 response.PutCStringAsRawHex8(s.c_str());
268 response.PutChar(';');
269 }
270 if (Host::GetHostname (s))
271 {
272 response.PutCString ("hostname:");
273 response.PutCStringAsRawHex8(s.c_str());
274 response.PutChar(';');
275 }
276
Greg Clayton516f0842012-04-11 00:24:49 +0000277 return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000278}
Greg Clayton58e26e02011-03-24 04:28:38 +0000279
Greg Clayton24bc5d92011-03-30 18:16:51 +0000280static void
Greg Claytonb72d0f02011-04-12 05:54:46 +0000281CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000282{
Greg Claytond9919d32011-12-01 23:28:38 +0000283 response.Printf ("pid:%llu;ppid:%llu;uid:%i;gid:%i;euid:%i;egid:%i;",
Greg Clayton24bc5d92011-03-30 18:16:51 +0000284 proc_info.GetProcessID(),
285 proc_info.GetParentProcessID(),
Greg Claytonb72d0f02011-04-12 05:54:46 +0000286 proc_info.GetUserID(),
287 proc_info.GetGroupID(),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000288 proc_info.GetEffectiveUserID(),
289 proc_info.GetEffectiveGroupID());
290 response.PutCString ("name:");
291 response.PutCStringAsRawHex8(proc_info.GetName());
292 response.PutChar(';');
293 const ArchSpec &proc_arch = proc_info.GetArchitecture();
294 if (proc_arch.IsValid())
295 {
296 const llvm::Triple &proc_triple = proc_arch.GetTriple();
297 response.PutCString("triple:");
298 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
299 response.PutChar(';');
300 }
301}
Greg Clayton58e26e02011-03-24 04:28:38 +0000302
303bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000304GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
Greg Clayton58e26e02011-03-24 04:28:38 +0000305{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000306 // Packet format: "qProcessInfoPID:%i" where %i is the pid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000307 packet.SetFilePos(::strlen ("qProcessInfoPID:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000308 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
309 if (pid != LLDB_INVALID_PROCESS_ID)
310 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000311 ProcessInstanceInfo proc_info;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000312 if (Host::GetProcessInfo(pid, proc_info))
313 {
314 StreamString response;
315 CreateProcessInfoResponse (proc_info, response);
Greg Clayton516f0842012-04-11 00:24:49 +0000316 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton24bc5d92011-03-30 18:16:51 +0000317 }
318 }
319 return SendErrorResponse (1);
320}
321
322bool
323GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
324{
325 m_proc_infos_index = 0;
326 m_proc_infos.Clear();
327
Greg Claytonb72d0f02011-04-12 05:54:46 +0000328 ProcessInstanceInfoMatch match_info;
329 packet.SetFilePos(::strlen ("qfProcessInfo"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000330 if (packet.GetChar() == ':')
331 {
332
333 std::string key;
334 std::string value;
335 while (packet.GetNameColonValue(key, value))
336 {
337 bool success = true;
338 if (key.compare("name") == 0)
339 {
340 StringExtractor extractor;
341 extractor.GetStringRef().swap(value);
342 extractor.GetHexByteString (value);
Greg Clayton527154d2011-11-15 03:53:30 +0000343 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000344 }
345 else if (key.compare("name_match") == 0)
346 {
347 if (value.compare("equals") == 0)
348 {
349 match_info.SetNameMatchType (eNameMatchEquals);
350 }
351 else if (value.compare("starts_with") == 0)
352 {
353 match_info.SetNameMatchType (eNameMatchStartsWith);
354 }
355 else if (value.compare("ends_with") == 0)
356 {
357 match_info.SetNameMatchType (eNameMatchEndsWith);
358 }
359 else if (value.compare("contains") == 0)
360 {
361 match_info.SetNameMatchType (eNameMatchContains);
362 }
363 else if (value.compare("regex") == 0)
364 {
365 match_info.SetNameMatchType (eNameMatchRegularExpression);
366 }
367 else
368 {
369 success = false;
370 }
371 }
372 else if (key.compare("pid") == 0)
373 {
374 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
375 }
376 else if (key.compare("parent_pid") == 0)
377 {
378 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
379 }
380 else if (key.compare("uid") == 0)
381 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000382 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000383 }
384 else if (key.compare("gid") == 0)
385 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000386 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000387 }
388 else if (key.compare("euid") == 0)
389 {
390 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
391 }
392 else if (key.compare("egid") == 0)
393 {
394 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
395 }
396 else if (key.compare("all_users") == 0)
397 {
398 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
399 }
400 else if (key.compare("triple") == 0)
401 {
Greg Claytonf15996e2011-04-07 22:46:35 +0000402 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000403 }
404 else
405 {
406 success = false;
407 }
408
409 if (!success)
410 return SendErrorResponse (2);
411 }
412 }
413
414 if (Host::FindProcesses (match_info, m_proc_infos))
415 {
416 // We found something, return the first item by calling the get
417 // subsequent process info packet handler...
418 return Handle_qsProcessInfo (packet);
419 }
420 return SendErrorResponse (3);
421}
422
423bool
424GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
425{
426 if (m_proc_infos_index < m_proc_infos.GetSize())
427 {
428 StreamString response;
429 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
430 ++m_proc_infos_index;
Greg Clayton516f0842012-04-11 00:24:49 +0000431 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton24bc5d92011-03-30 18:16:51 +0000432 }
433 return SendErrorResponse (4);
434}
435
436bool
437GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
438{
439 // Packet format: "qUserName:%i" where %i is the uid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000440 packet.SetFilePos(::strlen ("qUserName:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000441 uint32_t uid = packet.GetU32 (UINT32_MAX);
442 if (uid != UINT32_MAX)
443 {
444 std::string name;
445 if (Host::GetUserName (uid, name))
446 {
447 StreamString response;
448 response.PutCStringAsRawHex8 (name.c_str());
Greg Clayton516f0842012-04-11 00:24:49 +0000449 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton24bc5d92011-03-30 18:16:51 +0000450 }
451 }
452 return SendErrorResponse (5);
453
454}
455
456bool
457GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
458{
459 // Packet format: "qGroupName:%i" where %i is the gid
Greg Claytonb72d0f02011-04-12 05:54:46 +0000460 packet.SetFilePos(::strlen ("qGroupName:"));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000461 uint32_t gid = packet.GetU32 (UINT32_MAX);
462 if (gid != UINT32_MAX)
463 {
464 std::string name;
465 if (Host::GetGroupName (gid, name))
466 {
467 StreamString response;
468 response.PutCStringAsRawHex8 (name.c_str());
Greg Clayton516f0842012-04-11 00:24:49 +0000469 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton24bc5d92011-03-30 18:16:51 +0000470 }
471 }
472 return SendErrorResponse (6);
473}
474
475bool
Greg Clayton06d7cc82011-04-04 18:18:57 +0000476GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
477{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000478 packet.SetFilePos(::strlen ("qSpeedTest:"));
Greg Clayton06d7cc82011-04-04 18:18:57 +0000479
480 std::string key;
481 std::string value;
482 bool success = packet.GetNameColonValue(key, value);
483 if (success && key.compare("response_size") == 0)
484 {
485 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
486 if (success)
487 {
488 if (response_size == 0)
489 return SendOKResponse();
490 StreamString response;
491 uint32_t bytes_left = response_size;
492 response.PutCString("data:");
493 while (bytes_left > 0)
494 {
495 if (bytes_left >= 26)
496 {
497 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
498 bytes_left -= 26;
499 }
500 else
501 {
502 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
503 bytes_left = 0;
504 }
505 }
Greg Clayton516f0842012-04-11 00:24:49 +0000506 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton06d7cc82011-04-04 18:18:57 +0000507 }
508 }
509 return SendErrorResponse (7);
510}
Greg Claytonb72d0f02011-04-12 05:54:46 +0000511
512
513static void *
514AcceptPortFromInferior (void *arg)
515{
516 const char *connect_url = (const char *)arg;
517 ConnectionFileDescriptor file_conn;
518 Error error;
519 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
520 {
521 char pid_str[256];
522 ::memset (pid_str, 0, sizeof(pid_str));
523 ConnectionStatus status;
Bill Wendling8c1b3822012-04-03 07:50:11 +0000524 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000525 if (pid_str_len > 0)
526 {
527 int pid = atoi (pid_str);
528 return (void *)(intptr_t)pid;
529 }
530 }
531 return NULL;
532}
533//
534//static bool
535//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
536//{
537// const int time_delta_usecs = 100000;
538// const int num_retries = timeout_in_seconds/time_delta_usecs;
539// for (int i=0; i<num_retries; i++)
540// {
541// struct proc_bsdinfo bsd_info;
542// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
543// (uint64_t) 0,
544// &bsd_info,
545// PROC_PIDTBSDINFO_SIZE);
546//
547// switch (error)
548// {
549// case EINVAL:
550// case ENOTSUP:
551// case ESRCH:
552// case EPERM:
553// return false;
554//
555// default:
556// break;
557//
558// case 0:
559// if (bsd_info.pbi_status == SSTOP)
560// return true;
561// }
562// ::usleep (time_delta_usecs);
563// }
564// return false;
565//}
566
567bool
568GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
569{
570 // The 'A' packet is the most over designed packet ever here with
571 // redundant argument indexes, redundant argument lengths and needed hex
572 // encoded argument string values. Really all that is needed is a comma
573 // separated hex encoded argument value list, but we will stay true to the
574 // documented version of the 'A' packet here...
575
576 packet.SetFilePos(1); // Skip the 'A'
577 bool success = true;
578 while (success && packet.GetBytesLeft() > 0)
579 {
580 // Decode the decimal argument string length. This length is the
581 // number of hex nibbles in the argument string value.
582 const uint32_t arg_len = packet.GetU32(UINT32_MAX);
583 if (arg_len == UINT32_MAX)
584 success = false;
585 else
586 {
587 // Make sure the argument hex string length is followed by a comma
588 if (packet.GetChar() != ',')
589 success = false;
590 else
591 {
592 // Decode the argument index. We ignore this really becuase
593 // who would really send down the arguments in a random order???
594 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
595 if (arg_idx == UINT32_MAX)
596 success = false;
597 else
598 {
599 // Make sure the argument index is followed by a comma
600 if (packet.GetChar() != ',')
601 success = false;
602 else
603 {
604 // Decode the argument string value from hex bytes
605 // back into a UTF8 string and make sure the length
606 // matches the one supplied in the packet
607 std::string arg;
608 if (packet.GetHexByteString(arg) != (arg_len / 2))
609 success = false;
610 else
611 {
612 // If there are any bytes lft
613 if (packet.GetBytesLeft())
614 {
615 if (packet.GetChar() != ',')
616 success = false;
617 }
618
619 if (success)
620 {
621 if (arg_idx == 0)
622 m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
623 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
624 }
625 }
626 }
627 }
628 }
629 }
630 }
631
632 if (success)
633 {
634 m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
635 m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
636 if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
637 {
638 return SendOKResponse ();
639 }
640 }
641 return SendErrorResponse (8);
642}
643
644bool
645GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
646{
647 lldb::pid_t pid = m_process_launch_info.GetProcessID();
648 StreamString response;
Greg Claytond9919d32011-12-01 23:28:38 +0000649 response.Printf("QC%llx", pid);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000650 if (m_is_platform)
651 {
652 // If we launch a process and this GDB server is acting as a platform,
653 // then we need to clear the process launch state so we can start
654 // launching another process. In order to launch a process a bunch or
655 // packets need to be sent: environment packets, working directory,
656 // disable ASLR, and many more settings. When we launch a process we
657 // then need to know when to clear this information. Currently we are
658 // selecting the 'qC' packet as that packet which seems to make the most
659 // sense.
660 if (pid != LLDB_INVALID_PROCESS_ID)
661 {
662 m_process_launch_info.Clear();
663 }
664 }
Greg Clayton516f0842012-04-11 00:24:49 +0000665 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Claytonb72d0f02011-04-12 05:54:46 +0000666}
667
668bool
669GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
670{
671 // Spawn a local debugserver as a platform so we can then attach or launch
672 // a process...
673
674 if (m_is_platform)
675 {
676 // Sleep and wait a bit for debugserver to start to listen...
677 ConnectionFileDescriptor file_conn;
678 char connect_url[PATH_MAX];
679 Error error;
680 char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
681 if (::mktemp (unix_socket_name) == NULL)
682 {
683 error.SetErrorString ("failed to make temporary path for a unix socket");
684 }
685 else
686 {
687 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
688 // Spawn a new thread to accept the port that gets bound after
689 // binding to port 0 (zero).
690 lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
691 AcceptPortFromInferior,
692 connect_url,
693 &error);
694
695 if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
696 {
697 // Spawn a debugserver and try to get
698 ProcessLaunchInfo debugserver_launch_info;
699 error = StartDebugserverProcess ("localhost:0",
700 unix_socket_name,
701 debugserver_launch_info);
702
703 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
704 if (error.Success())
705 {
706 bool success = false;
707
708 thread_result_t accept_thread_result = NULL;
709 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
710 {
711 if (accept_thread_result)
712 {
713 uint16_t port = (intptr_t)accept_thread_result;
714 char response[256];
Greg Claytond9919d32011-12-01 23:28:38 +0000715 const int response_len = ::snprintf (response, sizeof(response), "pid:%llu;port:%u;", debugserver_pid, port);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000716 assert (response_len < sizeof(response));
717 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
Greg Clayton516f0842012-04-11 00:24:49 +0000718 success = SendPacketNoLock (response, response_len) > 0;
Greg Claytonb72d0f02011-04-12 05:54:46 +0000719 }
720 }
721 ::unlink (unix_socket_name);
722
723 if (!success)
724 {
725 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
726 ::kill (debugserver_pid, SIGINT);
727 }
728 return success;
729 }
730 }
731 }
732 }
733 return SendErrorResponse (13);
734}
735
736bool
737GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
738{
739 if (m_process_launch_error.Success())
740 return SendOKResponse();
741 StreamString response;
742 response.PutChar('E');
743 response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
Greg Clayton516f0842012-04-11 00:24:49 +0000744 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Claytonb72d0f02011-04-12 05:54:46 +0000745}
746
747bool
748GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
749{
750 packet.SetFilePos(::strlen ("QEnvironment:"));
751 const uint32_t bytes_left = packet.GetBytesLeft();
752 if (bytes_left > 0)
753 {
754 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
755 return SendOKResponse ();
756 }
757 return SendErrorResponse (9);
758}
759
760bool
761GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
762{
763 packet.SetFilePos(::strlen ("QSetDisableASLR:"));
764 if (packet.GetU32(0))
765 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
766 else
767 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
768 return SendOKResponse ();
769}
770
771bool
772GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
773{
774 packet.SetFilePos(::strlen ("QSetWorkingDir:"));
775 std::string path;
776 packet.GetHexByteString(path);
777 m_process_launch_info.SwapWorkingDirectory (path);
778 return SendOKResponse ();
779}
780
781bool
782GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
783{
784 packet.SetFilePos(::strlen ("QSetSTDIN:"));
785 ProcessLaunchInfo::FileAction file_action;
786 std::string path;
787 packet.GetHexByteString(path);
788 const bool read = false;
789 const bool write = true;
790 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
791 {
792 m_process_launch_info.AppendFileAction(file_action);
793 return SendOKResponse ();
794 }
795 return SendErrorResponse (10);
796}
797
798bool
799GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
800{
801 packet.SetFilePos(::strlen ("QSetSTDOUT:"));
802 ProcessLaunchInfo::FileAction file_action;
803 std::string path;
804 packet.GetHexByteString(path);
805 const bool read = true;
806 const bool write = false;
807 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
808 {
809 m_process_launch_info.AppendFileAction(file_action);
810 return SendOKResponse ();
811 }
812 return SendErrorResponse (11);
813}
814
815bool
816GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
817{
818 packet.SetFilePos(::strlen ("QSetSTDERR:"));
819 ProcessLaunchInfo::FileAction file_action;
820 std::string path;
821 packet.GetHexByteString(path);
822 const bool read = true;
Greg Clayton95ec1682012-03-06 04:01:04 +0000823 const bool write = false;
Greg Claytonb72d0f02011-04-12 05:54:46 +0000824 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
825 {
826 m_process_launch_info.AppendFileAction(file_action);
827 return SendOKResponse ();
828 }
829 return SendErrorResponse (12);
830}
831
Greg Clayton06d7cc82011-04-04 18:18:57 +0000832bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000833GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
834{
835 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton58e26e02011-03-24 04:28:38 +0000836 SendOKResponse ();
837 m_send_acks = false;
838 return true;
839}