blob: bed8852b7a0f1e6b2493dc31a1d47226b251cec5 [file] [log] [blame]
Greg Clayton576d8832011-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
Sylvestre Ledrud28b9932013-09-28 15:23:41 +000010#include <errno.h>
Greg Clayton576d8832011-03-22 04:00:09 +000011
12#include "GDBRemoteCommunicationServer.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000013#include "lldb/Core/StreamGDBRemote.h"
Greg Clayton576d8832011-03-22 04:00:09 +000014
15// C Includes
16// C++ Includes
17// Other libraries and framework includes
18#include "llvm/ADT/Triple.h"
19#include "lldb/Interpreter/Args.h"
20#include "lldb/Core/ConnectionFileDescriptor.h"
21#include "lldb/Core/Log.h"
22#include "lldb/Core/State.h"
23#include "lldb/Core/StreamString.h"
Enrico Granataf2bbf712011-07-15 02:26:42 +000024#include "lldb/Host/Endian.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000025#include "lldb/Host/File.h"
Greg Clayton576d8832011-03-22 04:00:09 +000026#include "lldb/Host/Host.h"
27#include "lldb/Host/TimeValue.h"
Greg Clayton8b82f082011-04-12 05:54:46 +000028#include "lldb/Target/Process.h"
Greg Clayton576d8832011-03-22 04:00:09 +000029
30// Project includes
31#include "Utility/StringExtractorGDBRemote.h"
32#include "ProcessGDBRemote.h"
33#include "ProcessGDBRemoteLog.h"
34
35using namespace lldb;
36using namespace lldb_private;
37
38//----------------------------------------------------------------------
39// GDBRemoteCommunicationServer constructor
40//----------------------------------------------------------------------
Greg Clayton8b82f082011-04-12 05:54:46 +000041GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
42 GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
43 m_async_thread (LLDB_INVALID_HOST_THREAD),
44 m_process_launch_info (),
45 m_process_launch_error (),
Daniel Maleae0f8f572013-08-26 23:57:52 +000046 m_spawned_pids (),
47 m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
Greg Clayton8b82f082011-04-12 05:54:46 +000048 m_proc_infos (),
49 m_proc_infos_index (0),
Greg Clayton2b98c562013-11-22 18:53:12 +000050 m_port_map (),
51 m_port_offset(0)
Greg Clayton576d8832011-03-22 04:00:09 +000052{
53}
54
55//----------------------------------------------------------------------
56// Destructor
57//----------------------------------------------------------------------
58GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
59{
60}
61
62
63//void *
64//GDBRemoteCommunicationServer::AsyncThread (void *arg)
65//{
66// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
67//
Greg Clayton5160ce52013-03-27 23:08:40 +000068// Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Greg Clayton576d8832011-03-22 04:00:09 +000069// if (log)
70// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
71//
72// StringExtractorGDBRemote packet;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +000073//
Greg Clayton576d8832011-03-22 04:00:09 +000074// while ()
75// {
76// if (packet.
77// }
78//
79// if (log)
80// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
81//
82// process->m_async_thread = LLDB_INVALID_HOST_THREAD;
83// return NULL;
84//}
85//
86bool
Sylvestre Ledrub027bd22013-09-28 14:35:00 +000087GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
Greg Clayton1cb64962011-03-24 04:28:38 +000088 Error &error,
Sylvestre Ledrub027bd22013-09-28 14:35:00 +000089 bool &interrupt,
Greg Claytond314e812011-03-23 00:09:55 +000090 bool &quit)
Greg Clayton576d8832011-03-22 04:00:09 +000091{
92 StringExtractorGDBRemote packet;
Greg Clayton3dedae12013-12-06 21:45:27 +000093 PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
94 if (packet_result == PacketResult::Success)
Greg Clayton576d8832011-03-22 04:00:09 +000095 {
96 const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
97 switch (packet_type)
98 {
Greg Clayton3dedae12013-12-06 21:45:27 +000099 case StringExtractorGDBRemote::eServerPacketType_nack:
100 case StringExtractorGDBRemote::eServerPacketType_ack:
101 break;
Greg Clayton576d8832011-03-22 04:00:09 +0000102
Greg Clayton3dedae12013-12-06 21:45:27 +0000103 case StringExtractorGDBRemote::eServerPacketType_invalid:
104 error.SetErrorString("invalid packet");
105 quit = true;
106 break;
Greg Claytond314e812011-03-23 00:09:55 +0000107
Greg Clayton3dedae12013-12-06 21:45:27 +0000108 case StringExtractorGDBRemote::eServerPacketType_interrupt:
109 error.SetErrorString("interrupt received");
110 interrupt = true;
111 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000112
Greg Clayton3dedae12013-12-06 21:45:27 +0000113 default:
114 case StringExtractorGDBRemote::eServerPacketType_unimplemented:
115 packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
116 break;
Greg Clayton576d8832011-03-22 04:00:09 +0000117
Greg Clayton3dedae12013-12-06 21:45:27 +0000118 case StringExtractorGDBRemote::eServerPacketType_A:
119 packet_result = Handle_A (packet);
120 break;
Greg Clayton32e0a752011-03-30 18:16:51 +0000121
Greg Clayton3dedae12013-12-06 21:45:27 +0000122 case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
123 packet_result = Handle_qfProcessInfo (packet);
124 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000125
Greg Clayton3dedae12013-12-06 21:45:27 +0000126 case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
127 packet_result = Handle_qsProcessInfo (packet);
128 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000129
Greg Clayton3dedae12013-12-06 21:45:27 +0000130 case StringExtractorGDBRemote::eServerPacketType_qC:
131 packet_result = Handle_qC (packet);
132 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000133
Greg Clayton3dedae12013-12-06 21:45:27 +0000134 case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
135 packet_result = Handle_qHostInfo (packet);
136 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000137
Greg Clayton3dedae12013-12-06 21:45:27 +0000138 case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
139 packet_result = Handle_qLaunchGDBServer (packet);
140 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000141
Greg Clayton3dedae12013-12-06 21:45:27 +0000142 case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
143 packet_result = Handle_qKillSpawnedProcess (packet);
144 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000145
Greg Clayton3dedae12013-12-06 21:45:27 +0000146 case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
147 packet_result = Handle_qLaunchSuccess (packet);
148 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000149
Greg Clayton3dedae12013-12-06 21:45:27 +0000150 case StringExtractorGDBRemote::eServerPacketType_qGroupName:
151 packet_result = Handle_qGroupName (packet);
152 break;
Greg Clayton32e0a752011-03-30 18:16:51 +0000153
Greg Clayton3dedae12013-12-06 21:45:27 +0000154 case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
155 packet_result = Handle_qProcessInfoPID (packet);
156 break;
Greg Clayton32e0a752011-03-30 18:16:51 +0000157
Greg Clayton3dedae12013-12-06 21:45:27 +0000158 case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
159 packet_result = Handle_qSpeedTest (packet);
160 break;
Greg Clayton32e0a752011-03-30 18:16:51 +0000161
Greg Clayton3dedae12013-12-06 21:45:27 +0000162 case StringExtractorGDBRemote::eServerPacketType_qUserName:
163 packet_result = Handle_qUserName (packet);
164 break;
Greg Clayton32e0a752011-03-30 18:16:51 +0000165
Greg Clayton3dedae12013-12-06 21:45:27 +0000166 case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir:
167 packet_result = Handle_qGetWorkingDir(packet);
168 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000169
Greg Clayton3dedae12013-12-06 21:45:27 +0000170 case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
171 packet_result = Handle_QEnvironment (packet);
172 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000173
Greg Clayton3dedae12013-12-06 21:45:27 +0000174 case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
175 packet_result = Handle_QLaunchArch (packet);
176 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000177
Greg Clayton3dedae12013-12-06 21:45:27 +0000178 case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
179 packet_result = Handle_QSetDisableASLR (packet);
180 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000181
Greg Clayton3dedae12013-12-06 21:45:27 +0000182 case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
183 packet_result = Handle_QSetSTDIN (packet);
184 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000185
Greg Clayton3dedae12013-12-06 21:45:27 +0000186 case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
187 packet_result = Handle_QSetSTDOUT (packet);
188 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000189
Greg Clayton3dedae12013-12-06 21:45:27 +0000190 case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
191 packet_result = Handle_QSetSTDERR (packet);
192 break;
Greg Clayton8b82f082011-04-12 05:54:46 +0000193
Greg Clayton3dedae12013-12-06 21:45:27 +0000194 case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
195 packet_result = Handle_QSetWorkingDir (packet);
196 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000197
Greg Clayton3dedae12013-12-06 21:45:27 +0000198 case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
199 packet_result = Handle_QStartNoAckMode (packet);
200 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000201
Greg Clayton3dedae12013-12-06 21:45:27 +0000202 case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir:
203 packet_result = Handle_qPlatform_mkdir (packet);
204 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000205
Greg Clayton3dedae12013-12-06 21:45:27 +0000206 case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod:
207 packet_result = Handle_qPlatform_chmod (packet);
208 break;
Greg Claytonfbb76342013-11-20 21:07:01 +0000209
Greg Clayton3dedae12013-12-06 21:45:27 +0000210 case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell:
211 packet_result = Handle_qPlatform_shell (packet);
212 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000213
Greg Clayton3dedae12013-12-06 21:45:27 +0000214 case StringExtractorGDBRemote::eServerPacketType_vFile_open:
215 packet_result = Handle_vFile_Open (packet);
216 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000217
Greg Clayton3dedae12013-12-06 21:45:27 +0000218 case StringExtractorGDBRemote::eServerPacketType_vFile_close:
219 packet_result = Handle_vFile_Close (packet);
220 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000221
Greg Clayton3dedae12013-12-06 21:45:27 +0000222 case StringExtractorGDBRemote::eServerPacketType_vFile_pread:
223 packet_result = Handle_vFile_pRead (packet);
224 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000225
Greg Clayton3dedae12013-12-06 21:45:27 +0000226 case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite:
227 packet_result = Handle_vFile_pWrite (packet);
228 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000229
Greg Clayton3dedae12013-12-06 21:45:27 +0000230 case StringExtractorGDBRemote::eServerPacketType_vFile_size:
231 packet_result = Handle_vFile_Size (packet);
232 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000233
Greg Clayton3dedae12013-12-06 21:45:27 +0000234 case StringExtractorGDBRemote::eServerPacketType_vFile_mode:
235 packet_result = Handle_vFile_Mode (packet);
236 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000237
Greg Clayton3dedae12013-12-06 21:45:27 +0000238 case StringExtractorGDBRemote::eServerPacketType_vFile_exists:
239 packet_result = Handle_vFile_Exists (packet);
240 break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000241
Greg Clayton3dedae12013-12-06 21:45:27 +0000242 case StringExtractorGDBRemote::eServerPacketType_vFile_stat:
243 packet_result = Handle_vFile_Stat (packet);
244 break;
Greg Claytonfbb76342013-11-20 21:07:01 +0000245
Greg Clayton3dedae12013-12-06 21:45:27 +0000246 case StringExtractorGDBRemote::eServerPacketType_vFile_md5:
247 packet_result = Handle_vFile_MD5 (packet);
248 break;
249
250 case StringExtractorGDBRemote::eServerPacketType_vFile_symlink:
251 packet_result = Handle_vFile_symlink (packet);
252 break;
253
254 case StringExtractorGDBRemote::eServerPacketType_vFile_unlink:
255 packet_result = Handle_vFile_unlink (packet);
256 break;
Greg Clayton576d8832011-03-22 04:00:09 +0000257 }
Greg Clayton576d8832011-03-22 04:00:09 +0000258 }
Greg Clayton1cb64962011-03-24 04:28:38 +0000259 else
260 {
261 if (!IsConnected())
Greg Clayton3dedae12013-12-06 21:45:27 +0000262 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000263 error.SetErrorString("lost connection");
Greg Clayton3dedae12013-12-06 21:45:27 +0000264 quit = true;
265 }
Greg Clayton1cb64962011-03-24 04:28:38 +0000266 else
Greg Clayton3dedae12013-12-06 21:45:27 +0000267 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000268 error.SetErrorString("timeout");
Greg Clayton3dedae12013-12-06 21:45:27 +0000269 }
Greg Clayton1cb64962011-03-24 04:28:38 +0000270 }
Greg Clayton3dedae12013-12-06 21:45:27 +0000271 return packet_result == PacketResult::Success;
Greg Clayton576d8832011-03-22 04:00:09 +0000272}
273
Greg Clayton3dedae12013-12-06 21:45:27 +0000274GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000275GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
Greg Clayton576d8832011-03-22 04:00:09 +0000276{
Greg Clayton32e0a752011-03-30 18:16:51 +0000277 // TODO: Log the packet we aren't handling...
Greg Clayton37a0a242012-04-11 00:24:49 +0000278 return SendPacketNoLock ("", 0);
Greg Clayton576d8832011-03-22 04:00:09 +0000279}
280
Greg Clayton3dedae12013-12-06 21:45:27 +0000281GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000282GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
283{
284 char packet[16];
285 int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
Andy Gibbsa297a972013-06-19 19:04:53 +0000286 assert (packet_len < (int)sizeof(packet));
Greg Clayton37a0a242012-04-11 00:24:49 +0000287 return SendPacketNoLock (packet, packet_len);
Greg Clayton32e0a752011-03-30 18:16:51 +0000288}
289
290
Greg Clayton3dedae12013-12-06 21:45:27 +0000291GDBRemoteCommunication::PacketResult
Greg Clayton1cb64962011-03-24 04:28:38 +0000292GDBRemoteCommunicationServer::SendOKResponse ()
293{
Greg Clayton37a0a242012-04-11 00:24:49 +0000294 return SendPacketNoLock ("OK", 2);
Greg Clayton1cb64962011-03-24 04:28:38 +0000295}
296
297bool
298GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
299{
Greg Clayton3dedae12013-12-06 21:45:27 +0000300 return GetAck() == PacketResult::Success;
Greg Clayton1cb64962011-03-24 04:28:38 +0000301}
Greg Clayton576d8832011-03-22 04:00:09 +0000302
Greg Clayton3dedae12013-12-06 21:45:27 +0000303GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000304GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
Greg Clayton576d8832011-03-22 04:00:09 +0000305{
306 StreamString response;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000307
Greg Clayton576d8832011-03-22 04:00:09 +0000308 // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
309
310 ArchSpec host_arch (Host::GetArchitecture ());
Greg Clayton576d8832011-03-22 04:00:09 +0000311 const llvm::Triple &host_triple = host_arch.GetTriple();
Greg Clayton1cb64962011-03-24 04:28:38 +0000312 response.PutCString("triple:");
313 response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
314 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
Greg Clayton576d8832011-03-22 04:00:09 +0000315
Todd Fialaa9ddb0e2014-01-18 03:02:39 +0000316 const char* distribution_id = host_arch.GetDistributionId ().AsCString ();
317 if (distribution_id)
318 {
319 response.PutCString("distribution_id:");
320 response.PutCStringAsRawHex8(distribution_id);
321 response.PutCString(";");
322 }
323
Greg Clayton1cb64962011-03-24 04:28:38 +0000324 uint32_t cpu = host_arch.GetMachOCPUType();
325 uint32_t sub = host_arch.GetMachOCPUSubType();
326 if (cpu != LLDB_INVALID_CPUTYPE)
327 response.Printf ("cputype:%u;", cpu);
328 if (sub != LLDB_INVALID_CPUTYPE)
329 response.Printf ("cpusubtype:%u;", sub);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000330
Enrico Granata1c5431a2012-07-13 23:55:22 +0000331 if (cpu == ArchSpec::kCore_arm_any)
Enrico Granataf04a2192012-07-13 23:18:48 +0000332 response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
333 else
334 response.Printf("watchpoint_exceptions_received:after;");
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000335
Greg Clayton576d8832011-03-22 04:00:09 +0000336 switch (lldb::endian::InlHostByteOrder())
337 {
338 case eByteOrderBig: response.PutCString ("endian:big;"); break;
339 case eByteOrderLittle: response.PutCString ("endian:little;"); break;
340 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
341 default: response.PutCString ("endian:unknown;"); break;
342 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000343
Greg Clayton1cb64962011-03-24 04:28:38 +0000344 uint32_t major = UINT32_MAX;
345 uint32_t minor = UINT32_MAX;
346 uint32_t update = UINT32_MAX;
347 if (Host::GetOSVersion (major, minor, update))
348 {
349 if (major != UINT32_MAX)
350 {
351 response.Printf("os_version:%u", major);
352 if (minor != UINT32_MAX)
353 {
354 response.Printf(".%u", minor);
355 if (update != UINT32_MAX)
356 response.Printf(".%u", update);
357 }
358 response.PutChar(';');
359 }
360 }
361
362 std::string s;
363 if (Host::GetOSBuildString (s))
364 {
365 response.PutCString ("os_build:");
366 response.PutCStringAsRawHex8(s.c_str());
367 response.PutChar(';');
368 }
369 if (Host::GetOSKernelDescription (s))
370 {
371 response.PutCString ("os_kernel:");
372 response.PutCStringAsRawHex8(s.c_str());
373 response.PutChar(';');
374 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000375#if defined(__APPLE__)
376
377#if defined(__arm__)
378 // For iOS devices, we are connected through a USB Mux so we never pretend
379 // to actually have a hostname as far as the remote lldb that is connecting
380 // to this lldb-platform is concerned
381 response.PutCString ("hostname:");
382 response.PutCStringAsRawHex8("localhost");
383 response.PutChar(';');
384#else // #if defined(__arm__)
Greg Clayton1cb64962011-03-24 04:28:38 +0000385 if (Host::GetHostname (s))
386 {
387 response.PutCString ("hostname:");
388 response.PutCStringAsRawHex8(s.c_str());
389 response.PutChar(';');
390 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000391
Greg Clayton2b98c562013-11-22 18:53:12 +0000392#endif // #if defined(__arm__)
393
394#else // #if defined(__APPLE__)
395 if (Host::GetHostname (s))
396 {
397 response.PutCString ("hostname:");
398 response.PutCStringAsRawHex8(s.c_str());
399 response.PutChar(';');
400 }
401#endif // #if defined(__APPLE__)
402
Greg Clayton3dedae12013-12-06 21:45:27 +0000403 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton576d8832011-03-22 04:00:09 +0000404}
Greg Clayton1cb64962011-03-24 04:28:38 +0000405
Greg Clayton32e0a752011-03-30 18:16:51 +0000406static void
Greg Clayton8b82f082011-04-12 05:54:46 +0000407CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
Greg Clayton32e0a752011-03-30 18:16:51 +0000408{
Daniel Malead01b2952012-11-29 21:49:15 +0000409 response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
Greg Clayton32e0a752011-03-30 18:16:51 +0000410 proc_info.GetProcessID(),
411 proc_info.GetParentProcessID(),
Greg Clayton8b82f082011-04-12 05:54:46 +0000412 proc_info.GetUserID(),
413 proc_info.GetGroupID(),
Greg Clayton32e0a752011-03-30 18:16:51 +0000414 proc_info.GetEffectiveUserID(),
415 proc_info.GetEffectiveGroupID());
416 response.PutCString ("name:");
417 response.PutCStringAsRawHex8(proc_info.GetName());
418 response.PutChar(';');
419 const ArchSpec &proc_arch = proc_info.GetArchitecture();
420 if (proc_arch.IsValid())
421 {
422 const llvm::Triple &proc_triple = proc_arch.GetTriple();
423 response.PutCString("triple:");
424 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
425 response.PutChar(';');
426 }
427}
Greg Clayton1cb64962011-03-24 04:28:38 +0000428
Greg Clayton3dedae12013-12-06 21:45:27 +0000429GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000430GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
Greg Clayton1cb64962011-03-24 04:28:38 +0000431{
Greg Clayton32e0a752011-03-30 18:16:51 +0000432 // Packet format: "qProcessInfoPID:%i" where %i is the pid
Greg Clayton8b82f082011-04-12 05:54:46 +0000433 packet.SetFilePos(::strlen ("qProcessInfoPID:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000434 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
435 if (pid != LLDB_INVALID_PROCESS_ID)
436 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000437 ProcessInstanceInfo proc_info;
Greg Clayton32e0a752011-03-30 18:16:51 +0000438 if (Host::GetProcessInfo(pid, proc_info))
439 {
440 StreamString response;
441 CreateProcessInfoResponse (proc_info, response);
Greg Clayton37a0a242012-04-11 00:24:49 +0000442 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000443 }
444 }
445 return SendErrorResponse (1);
446}
447
Greg Clayton3dedae12013-12-06 21:45:27 +0000448GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000449GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
450{
451 m_proc_infos_index = 0;
452 m_proc_infos.Clear();
453
Greg Clayton8b82f082011-04-12 05:54:46 +0000454 ProcessInstanceInfoMatch match_info;
455 packet.SetFilePos(::strlen ("qfProcessInfo"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000456 if (packet.GetChar() == ':')
457 {
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000458
Greg Clayton32e0a752011-03-30 18:16:51 +0000459 std::string key;
460 std::string value;
461 while (packet.GetNameColonValue(key, value))
462 {
463 bool success = true;
464 if (key.compare("name") == 0)
465 {
466 StringExtractor extractor;
467 extractor.GetStringRef().swap(value);
468 extractor.GetHexByteString (value);
Greg Clayton144f3a92011-11-15 03:53:30 +0000469 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
Greg Clayton32e0a752011-03-30 18:16:51 +0000470 }
471 else if (key.compare("name_match") == 0)
472 {
473 if (value.compare("equals") == 0)
474 {
475 match_info.SetNameMatchType (eNameMatchEquals);
476 }
477 else if (value.compare("starts_with") == 0)
478 {
479 match_info.SetNameMatchType (eNameMatchStartsWith);
480 }
481 else if (value.compare("ends_with") == 0)
482 {
483 match_info.SetNameMatchType (eNameMatchEndsWith);
484 }
485 else if (value.compare("contains") == 0)
486 {
487 match_info.SetNameMatchType (eNameMatchContains);
488 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000489 else if (value.compare("regex") == 0)
Greg Clayton32e0a752011-03-30 18:16:51 +0000490 {
491 match_info.SetNameMatchType (eNameMatchRegularExpression);
492 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000493 else
Greg Clayton32e0a752011-03-30 18:16:51 +0000494 {
495 success = false;
496 }
497 }
498 else if (key.compare("pid") == 0)
499 {
500 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
501 }
502 else if (key.compare("parent_pid") == 0)
503 {
504 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
505 }
506 else if (key.compare("uid") == 0)
507 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000508 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton32e0a752011-03-30 18:16:51 +0000509 }
510 else if (key.compare("gid") == 0)
511 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000512 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton32e0a752011-03-30 18:16:51 +0000513 }
514 else if (key.compare("euid") == 0)
515 {
516 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
517 }
518 else if (key.compare("egid") == 0)
519 {
520 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
521 }
522 else if (key.compare("all_users") == 0)
523 {
524 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
525 }
526 else if (key.compare("triple") == 0)
527 {
Greg Claytoneb0103f2011-04-07 22:46:35 +0000528 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
Greg Clayton32e0a752011-03-30 18:16:51 +0000529 }
530 else
531 {
532 success = false;
533 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000534
Greg Clayton32e0a752011-03-30 18:16:51 +0000535 if (!success)
536 return SendErrorResponse (2);
537 }
538 }
539
540 if (Host::FindProcesses (match_info, m_proc_infos))
541 {
542 // We found something, return the first item by calling the get
543 // subsequent process info packet handler...
544 return Handle_qsProcessInfo (packet);
545 }
546 return SendErrorResponse (3);
547}
548
Greg Clayton3dedae12013-12-06 21:45:27 +0000549GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000550GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
551{
552 if (m_proc_infos_index < m_proc_infos.GetSize())
553 {
554 StreamString response;
555 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
556 ++m_proc_infos_index;
Greg Clayton37a0a242012-04-11 00:24:49 +0000557 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000558 }
559 return SendErrorResponse (4);
560}
561
Greg Clayton3dedae12013-12-06 21:45:27 +0000562GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000563GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
564{
565 // Packet format: "qUserName:%i" where %i is the uid
Greg Clayton8b82f082011-04-12 05:54:46 +0000566 packet.SetFilePos(::strlen ("qUserName:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000567 uint32_t uid = packet.GetU32 (UINT32_MAX);
568 if (uid != UINT32_MAX)
569 {
570 std::string name;
571 if (Host::GetUserName (uid, name))
572 {
573 StreamString response;
574 response.PutCStringAsRawHex8 (name.c_str());
Greg Clayton37a0a242012-04-11 00:24:49 +0000575 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000576 }
577 }
578 return SendErrorResponse (5);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000579
Greg Clayton32e0a752011-03-30 18:16:51 +0000580}
581
Greg Clayton3dedae12013-12-06 21:45:27 +0000582GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000583GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
584{
585 // Packet format: "qGroupName:%i" where %i is the gid
Greg Clayton8b82f082011-04-12 05:54:46 +0000586 packet.SetFilePos(::strlen ("qGroupName:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000587 uint32_t gid = packet.GetU32 (UINT32_MAX);
588 if (gid != UINT32_MAX)
589 {
590 std::string name;
591 if (Host::GetGroupName (gid, name))
592 {
593 StreamString response;
594 response.PutCStringAsRawHex8 (name.c_str());
Greg Clayton37a0a242012-04-11 00:24:49 +0000595 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000596 }
597 }
598 return SendErrorResponse (6);
599}
600
Greg Clayton3dedae12013-12-06 21:45:27 +0000601GDBRemoteCommunication::PacketResult
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000602GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
603{
Greg Clayton8b82f082011-04-12 05:54:46 +0000604 packet.SetFilePos(::strlen ("qSpeedTest:"));
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000605
606 std::string key;
607 std::string value;
608 bool success = packet.GetNameColonValue(key, value);
609 if (success && key.compare("response_size") == 0)
610 {
611 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
612 if (success)
613 {
614 if (response_size == 0)
615 return SendOKResponse();
616 StreamString response;
617 uint32_t bytes_left = response_size;
618 response.PutCString("data:");
619 while (bytes_left > 0)
620 {
621 if (bytes_left >= 26)
622 {
623 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
624 bytes_left -= 26;
625 }
626 else
627 {
628 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
629 bytes_left = 0;
630 }
631 }
Greg Clayton37a0a242012-04-11 00:24:49 +0000632 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000633 }
634 }
635 return SendErrorResponse (7);
636}
Greg Clayton8b82f082011-04-12 05:54:46 +0000637
638
639static void *
640AcceptPortFromInferior (void *arg)
641{
642 const char *connect_url = (const char *)arg;
643 ConnectionFileDescriptor file_conn;
644 Error error;
645 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
646 {
647 char pid_str[256];
648 ::memset (pid_str, 0, sizeof(pid_str));
649 ConnectionStatus status;
Bill Wendlinged24dcc2012-04-03 07:50:11 +0000650 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
Greg Clayton8b82f082011-04-12 05:54:46 +0000651 if (pid_str_len > 0)
652 {
653 int pid = atoi (pid_str);
654 return (void *)(intptr_t)pid;
655 }
656 }
657 return NULL;
658}
659//
660//static bool
661//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
662//{
663// const int time_delta_usecs = 100000;
664// const int num_retries = timeout_in_seconds/time_delta_usecs;
665// for (int i=0; i<num_retries; i++)
666// {
667// struct proc_bsdinfo bsd_info;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000668// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
669// (uint64_t) 0,
670// &bsd_info,
Greg Clayton8b82f082011-04-12 05:54:46 +0000671// PROC_PIDTBSDINFO_SIZE);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000672//
Greg Clayton8b82f082011-04-12 05:54:46 +0000673// switch (error)
674// {
675// case EINVAL:
676// case ENOTSUP:
677// case ESRCH:
678// case EPERM:
679// return false;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000680//
Greg Clayton8b82f082011-04-12 05:54:46 +0000681// default:
682// break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000683//
Greg Clayton8b82f082011-04-12 05:54:46 +0000684// case 0:
685// if (bsd_info.pbi_status == SSTOP)
686// return true;
687// }
688// ::usleep (time_delta_usecs);
689// }
690// return false;
691//}
692
Greg Clayton3dedae12013-12-06 21:45:27 +0000693GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000694GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
695{
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000696 // The 'A' packet is the most over designed packet ever here with
697 // redundant argument indexes, redundant argument lengths and needed hex
698 // encoded argument string values. Really all that is needed is a comma
Greg Clayton8b82f082011-04-12 05:54:46 +0000699 // separated hex encoded argument value list, but we will stay true to the
700 // documented version of the 'A' packet here...
701
702 packet.SetFilePos(1); // Skip the 'A'
703 bool success = true;
704 while (success && packet.GetBytesLeft() > 0)
705 {
706 // Decode the decimal argument string length. This length is the
707 // number of hex nibbles in the argument string value.
708 const uint32_t arg_len = packet.GetU32(UINT32_MAX);
709 if (arg_len == UINT32_MAX)
710 success = false;
711 else
712 {
713 // Make sure the argument hex string length is followed by a comma
714 if (packet.GetChar() != ',')
715 success = false;
716 else
717 {
718 // Decode the argument index. We ignore this really becuase
719 // who would really send down the arguments in a random order???
720 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
721 if (arg_idx == UINT32_MAX)
722 success = false;
723 else
724 {
725 // Make sure the argument index is followed by a comma
726 if (packet.GetChar() != ',')
727 success = false;
728 else
729 {
730 // Decode the argument string value from hex bytes
731 // back into a UTF8 string and make sure the length
732 // matches the one supplied in the packet
733 std::string arg;
734 if (packet.GetHexByteString(arg) != (arg_len / 2))
735 success = false;
736 else
737 {
738 // If there are any bytes lft
739 if (packet.GetBytesLeft())
740 {
741 if (packet.GetChar() != ',')
742 success = false;
743 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000744
Greg Clayton8b82f082011-04-12 05:54:46 +0000745 if (success)
746 {
747 if (arg_idx == 0)
748 m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
749 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
750 }
751 }
752 }
753 }
754 }
755 }
756 }
757
758 if (success)
759 {
760 m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
761 m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
762 if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
763 {
764 return SendOKResponse ();
765 }
766 }
767 return SendErrorResponse (8);
768}
769
Greg Clayton3dedae12013-12-06 21:45:27 +0000770GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000771GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
772{
773 lldb::pid_t pid = m_process_launch_info.GetProcessID();
774 StreamString response;
Daniel Malead01b2952012-11-29 21:49:15 +0000775 response.Printf("QC%" PRIx64, pid);
Greg Clayton8b82f082011-04-12 05:54:46 +0000776 if (m_is_platform)
777 {
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000778 // If we launch a process and this GDB server is acting as a platform,
779 // then we need to clear the process launch state so we can start
Greg Clayton8b82f082011-04-12 05:54:46 +0000780 // launching another process. In order to launch a process a bunch or
781 // packets need to be sent: environment packets, working directory,
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000782 // disable ASLR, and many more settings. When we launch a process we
Greg Clayton8b82f082011-04-12 05:54:46 +0000783 // then need to know when to clear this information. Currently we are
784 // selecting the 'qC' packet as that packet which seems to make the most
785 // sense.
786 if (pid != LLDB_INVALID_PROCESS_ID)
787 {
788 m_process_launch_info.Clear();
789 }
790 }
Greg Clayton37a0a242012-04-11 00:24:49 +0000791 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton8b82f082011-04-12 05:54:46 +0000792}
793
794bool
Daniel Maleae0f8f572013-08-26 23:57:52 +0000795GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
796{
797 Mutex::Locker locker (m_spawned_pids_mutex);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000798 FreePortForProcess(pid);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000799 return m_spawned_pids.erase(pid) > 0;
800}
801bool
802GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
803 lldb::pid_t pid,
804 bool exited,
805 int signal, // Zero for no signal
806 int status) // Exit value of process if signal is zero
807{
808 GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
809 server->DebugserverProcessReaped (pid);
810 return true;
811}
812
Greg Clayton3dedae12013-12-06 21:45:27 +0000813GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000814GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
815{
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000816#ifdef _WIN32
Deepak Panickal263fde02014-01-14 11:34:44 +0000817 return SendErrorResponse(9);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000818#else
Greg Clayton8b82f082011-04-12 05:54:46 +0000819 // Spawn a local debugserver as a platform so we can then attach or launch
820 // a process...
821
822 if (m_is_platform)
823 {
824 // Sleep and wait a bit for debugserver to start to listen...
825 ConnectionFileDescriptor file_conn;
Greg Clayton8b82f082011-04-12 05:54:46 +0000826 Error error;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000827 std::string hostname;
Sylvestre Ledrufaa63ce2013-09-28 15:57:37 +0000828 // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
829 // with the TMPDIR environnement variable
Greg Clayton29b8fc42013-11-21 01:44:58 +0000830 packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
831 std::string name;
832 std::string value;
833 uint16_t port = UINT16_MAX;
834 while (packet.GetNameColonValue(name, value))
Greg Clayton8b82f082011-04-12 05:54:46 +0000835 {
Greg Clayton29b8fc42013-11-21 01:44:58 +0000836 if (name.compare ("host") == 0)
837 hostname.swap(value);
838 else if (name.compare ("port") == 0)
839 port = Args::StringToUInt32(value.c_str(), 0, 0);
Greg Clayton8b82f082011-04-12 05:54:46 +0000840 }
Greg Clayton29b8fc42013-11-21 01:44:58 +0000841 if (port == UINT16_MAX)
842 port = GetNextAvailablePort();
843
844 // Spawn a new thread to accept the port that gets bound after
845 // binding to port 0 (zero).
Greg Claytonfbb76342013-11-20 21:07:01 +0000846
Greg Clayton29b8fc42013-11-21 01:44:58 +0000847 if (error.Success())
848 {
849 // Spawn a debugserver and try to get the port it listens to.
850 ProcessLaunchInfo debugserver_launch_info;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000851 if (hostname.empty())
852 hostname = "localhost";
Greg Clayton29b8fc42013-11-21 01:44:58 +0000853 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
854 if (log)
Greg Claytonfda4fab2014-01-10 22:24:11 +0000855 log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000856
Greg Clayton29b8fc42013-11-21 01:44:58 +0000857 debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
858
Greg Claytonfda4fab2014-01-10 22:24:11 +0000859 error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
860 port,
Greg Clayton00fe87b2013-12-05 22:58:22 +0000861 debugserver_launch_info,
862 port);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000863
864 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000865
Greg Claytonfbb76342013-11-20 21:07:01 +0000866
Greg Clayton29b8fc42013-11-21 01:44:58 +0000867 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
868 {
869 Mutex::Locker locker (m_spawned_pids_mutex);
870 m_spawned_pids.insert(debugserver_pid);
871 if (port > 0)
872 AssociatePortWithProcess(port, debugserver_pid);
873 }
874 else
875 {
876 if (port > 0)
877 FreePort (port);
878 }
879
880 if (error.Success())
881 {
Greg Clayton91a9b2472013-12-04 19:19:12 +0000882 char response[256];
883 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
884 assert (response_len < sizeof(response));
Greg Clayton3dedae12013-12-06 21:45:27 +0000885 PacketResult packet_result = SendPacketNoLock (response, response_len);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000886
Greg Clayton3dedae12013-12-06 21:45:27 +0000887 if (packet_result != PacketResult::Success)
Greg Clayton29b8fc42013-11-21 01:44:58 +0000888 {
889 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
890 ::kill (debugserver_pid, SIGINT);
891 }
Greg Clayton3dedae12013-12-06 21:45:27 +0000892 return packet_result;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000893 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000894 }
895 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000896 return SendErrorResponse (9);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000897#endif
Greg Clayton8b82f082011-04-12 05:54:46 +0000898}
899
Greg Clayton3dedae12013-12-06 21:45:27 +0000900GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +0000901GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
902{
903 // Spawn a local debugserver as a platform so we can then attach or launch
904 // a process...
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000905
Daniel Maleae0f8f572013-08-26 23:57:52 +0000906 if (m_is_platform)
907 {
908 packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000909
Daniel Maleae0f8f572013-08-26 23:57:52 +0000910 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
911
912 // Scope for locker
913 {
914 Mutex::Locker locker (m_spawned_pids_mutex);
915 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
916 return SendErrorResponse (10);
917 }
Virgile Belloae12a362013-08-27 16:21:49 +0000918 Host::Kill (pid, SIGTERM);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000919
Daniel Maleae0f8f572013-08-26 23:57:52 +0000920 for (size_t i=0; i<10; ++i)
921 {
922 // Scope for locker
923 {
924 Mutex::Locker locker (m_spawned_pids_mutex);
925 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000926 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000927 }
928 usleep (10000);
929 }
930
931 // Scope for locker
932 {
933 Mutex::Locker locker (m_spawned_pids_mutex);
934 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000935 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000936 }
Virgile Belloae12a362013-08-27 16:21:49 +0000937 Host::Kill (pid, SIGKILL);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000938
Daniel Maleae0f8f572013-08-26 23:57:52 +0000939 for (size_t i=0; i<10; ++i)
940 {
941 // Scope for locker
942 {
943 Mutex::Locker locker (m_spawned_pids_mutex);
944 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000945 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000946 }
947 usleep (10000);
948 }
949 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000950 return SendErrorResponse (11);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000951}
952
Greg Clayton3dedae12013-12-06 21:45:27 +0000953GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000954GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
955{
956 if (m_process_launch_error.Success())
957 return SendOKResponse();
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000958 StreamString response;
Greg Clayton8b82f082011-04-12 05:54:46 +0000959 response.PutChar('E');
960 response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
Greg Clayton37a0a242012-04-11 00:24:49 +0000961 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton8b82f082011-04-12 05:54:46 +0000962}
963
Greg Clayton3dedae12013-12-06 21:45:27 +0000964GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000965GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
966{
967 packet.SetFilePos(::strlen ("QEnvironment:"));
968 const uint32_t bytes_left = packet.GetBytesLeft();
969 if (bytes_left > 0)
970 {
971 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
972 return SendOKResponse ();
973 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000974 return SendErrorResponse (12);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000975}
976
Greg Clayton3dedae12013-12-06 21:45:27 +0000977GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +0000978GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
979{
980 packet.SetFilePos(::strlen ("QLaunchArch:"));
981 const uint32_t bytes_left = packet.GetBytesLeft();
982 if (bytes_left > 0)
983 {
984 const char* arch_triple = packet.Peek();
985 ArchSpec arch_spec(arch_triple,NULL);
986 m_process_launch_info.SetArchitecture(arch_spec);
987 return SendOKResponse();
988 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000989 return SendErrorResponse(13);
Greg Clayton8b82f082011-04-12 05:54:46 +0000990}
991
Greg Clayton3dedae12013-12-06 21:45:27 +0000992GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000993GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
994{
995 packet.SetFilePos(::strlen ("QSetDisableASLR:"));
996 if (packet.GetU32(0))
997 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
998 else
999 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
1000 return SendOKResponse ();
1001}
1002
Greg Clayton3dedae12013-12-06 21:45:27 +00001003GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001004GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
1005{
1006 packet.SetFilePos(::strlen ("QSetWorkingDir:"));
1007 std::string path;
1008 packet.GetHexByteString(path);
Greg Claytonfbb76342013-11-20 21:07:01 +00001009 if (m_is_platform)
1010 {
Colin Riley909bb7a2013-11-26 15:10:46 +00001011#ifdef _WIN32
1012 // Not implemented on Windows
1013 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_QSetWorkingDir unimplemented");
1014#else
Greg Claytonfbb76342013-11-20 21:07:01 +00001015 // If this packet is sent to a platform, then change the current working directory
1016 if (::chdir(path.c_str()) != 0)
1017 return SendErrorResponse(errno);
Colin Riley909bb7a2013-11-26 15:10:46 +00001018#endif
Greg Claytonfbb76342013-11-20 21:07:01 +00001019 }
1020 else
1021 {
1022 m_process_launch_info.SwapWorkingDirectory (path);
1023 }
Greg Clayton8b82f082011-04-12 05:54:46 +00001024 return SendOKResponse ();
1025}
1026
Greg Clayton3dedae12013-12-06 21:45:27 +00001027GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001028GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
1029{
1030 StreamString response;
1031
1032 if (m_is_platform)
1033 {
1034 // If this packet is sent to a platform, then change the current working directory
1035 char cwd[PATH_MAX];
1036 if (getcwd(cwd, sizeof(cwd)) == NULL)
1037 {
1038 return SendErrorResponse(errno);
1039 }
1040 else
1041 {
1042 response.PutBytesAsRawHex8(cwd, strlen(cwd));
Greg Clayton3dedae12013-12-06 21:45:27 +00001043 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001044 }
1045 }
1046 else
1047 {
1048 const char *working_dir = m_process_launch_info.GetWorkingDirectory();
1049 if (working_dir && working_dir[0])
1050 {
1051 response.PutBytesAsRawHex8(working_dir, strlen(working_dir));
Greg Clayton3dedae12013-12-06 21:45:27 +00001052 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001053 }
1054 else
1055 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001056 return SendErrorResponse(14);
Greg Claytonfbb76342013-11-20 21:07:01 +00001057 }
1058 }
1059}
1060
Greg Clayton3dedae12013-12-06 21:45:27 +00001061GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001062GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
1063{
1064 packet.SetFilePos(::strlen ("QSetSTDIN:"));
1065 ProcessLaunchInfo::FileAction file_action;
1066 std::string path;
1067 packet.GetHexByteString(path);
1068 const bool read = false;
1069 const bool write = true;
1070 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
1071 {
1072 m_process_launch_info.AppendFileAction(file_action);
1073 return SendOKResponse ();
1074 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001075 return SendErrorResponse (15);
Greg Clayton8b82f082011-04-12 05:54:46 +00001076}
1077
Greg Clayton3dedae12013-12-06 21:45:27 +00001078GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001079GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
1080{
1081 packet.SetFilePos(::strlen ("QSetSTDOUT:"));
1082 ProcessLaunchInfo::FileAction file_action;
1083 std::string path;
1084 packet.GetHexByteString(path);
1085 const bool read = true;
1086 const bool write = false;
1087 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
1088 {
1089 m_process_launch_info.AppendFileAction(file_action);
1090 return SendOKResponse ();
1091 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001092 return SendErrorResponse (16);
Greg Clayton8b82f082011-04-12 05:54:46 +00001093}
1094
Greg Clayton3dedae12013-12-06 21:45:27 +00001095GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001096GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
1097{
1098 packet.SetFilePos(::strlen ("QSetSTDERR:"));
1099 ProcessLaunchInfo::FileAction file_action;
1100 std::string path;
1101 packet.GetHexByteString(path);
1102 const bool read = true;
Greg Clayton9845a8d2012-03-06 04:01:04 +00001103 const bool write = false;
Greg Clayton8b82f082011-04-12 05:54:46 +00001104 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
1105 {
1106 m_process_launch_info.AppendFileAction(file_action);
1107 return SendOKResponse ();
1108 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001109 return SendErrorResponse (17);
Greg Clayton8b82f082011-04-12 05:54:46 +00001110}
1111
Greg Clayton3dedae12013-12-06 21:45:27 +00001112GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +00001113GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
1114{
1115 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton3dedae12013-12-06 21:45:27 +00001116 PacketResult packet_result = SendOKResponse ();
Greg Clayton1cb64962011-03-24 04:28:38 +00001117 m_send_acks = false;
Greg Clayton3dedae12013-12-06 21:45:27 +00001118 return packet_result;
Greg Clayton1cb64962011-03-24 04:28:38 +00001119}
Daniel Maleae0f8f572013-08-26 23:57:52 +00001120
Greg Clayton3dedae12013-12-06 21:45:27 +00001121GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001122GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
Daniel Maleae0f8f572013-08-26 23:57:52 +00001123{
Greg Claytonfbb76342013-11-20 21:07:01 +00001124 packet.SetFilePos(::strlen("qPlatform_mkdir:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001125 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001126 if (packet.GetChar() == ',')
1127 {
1128 std::string path;
1129 packet.GetHexByteString(path);
1130 Error error = Host::MakeDirectory(path.c_str(),mode);
1131 if (error.Success())
1132 return SendPacketNoLock ("OK", 2);
1133 else
1134 return SendErrorResponse(error.GetError());
1135 }
1136 return SendErrorResponse(20);
Greg Claytonfbb76342013-11-20 21:07:01 +00001137}
1138
Greg Clayton3dedae12013-12-06 21:45:27 +00001139GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001140GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
1141{
1142 packet.SetFilePos(::strlen("qPlatform_chmod:"));
1143
1144 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001145 if (packet.GetChar() == ',')
1146 {
1147 std::string path;
1148 packet.GetHexByteString(path);
1149 Error error = Host::SetFilePermissions (path.c_str(), mode);
1150 if (error.Success())
1151 return SendPacketNoLock ("OK", 2);
1152 else
1153 return SendErrorResponse(error.GetError());
1154 }
1155 return SendErrorResponse(19);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001156}
1157
Greg Clayton3dedae12013-12-06 21:45:27 +00001158GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001159GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
1160{
1161 packet.SetFilePos(::strlen("vFile:open:"));
1162 std::string path;
1163 packet.GetHexByteStringTerminatedBy(path,',');
Greg Clayton2b98c562013-11-22 18:53:12 +00001164 if (!path.empty())
1165 {
1166 if (packet.GetChar() == ',')
1167 {
1168 uint32_t flags = packet.GetHexMaxU32(false, 0);
1169 if (packet.GetChar() == ',')
1170 {
1171 mode_t mode = packet.GetHexMaxU32(false, 0600);
1172 Error error;
1173 int fd = ::open (path.c_str(), flags, mode);
Greg Clayton2b98c562013-11-22 18:53:12 +00001174 const int save_errno = fd == -1 ? errno : 0;
1175 StreamString response;
1176 response.PutChar('F');
1177 response.Printf("%i", fd);
1178 if (save_errno)
1179 response.Printf(",%i", save_errno);
1180 return SendPacketNoLock(response.GetData(), response.GetSize());
1181 }
1182 }
1183 }
1184 return SendErrorResponse(18);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001185}
1186
Greg Clayton3dedae12013-12-06 21:45:27 +00001187GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001188GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
1189{
1190 packet.SetFilePos(::strlen("vFile:close:"));
1191 int fd = packet.GetS32(-1);
1192 Error error;
1193 int err = -1;
1194 int save_errno = 0;
1195 if (fd >= 0)
1196 {
1197 err = close(fd);
1198 save_errno = err == -1 ? errno : 0;
1199 }
1200 else
1201 {
1202 save_errno = EINVAL;
1203 }
1204 StreamString response;
1205 response.PutChar('F');
1206 response.Printf("%i", err);
1207 if (save_errno)
1208 response.Printf(",%i", save_errno);
Greg Clayton2b98c562013-11-22 18:53:12 +00001209 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001210}
1211
Greg Clayton3dedae12013-12-06 21:45:27 +00001212GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001213GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
1214{
Virgile Belloae12a362013-08-27 16:21:49 +00001215#ifdef _WIN32
1216 // Not implemented on Windows
Greg Clayton2b98c562013-11-22 18:53:12 +00001217 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pRead() unimplemented");
Virgile Belloae12a362013-08-27 16:21:49 +00001218#else
Daniel Maleae0f8f572013-08-26 23:57:52 +00001219 StreamGDBRemote response;
1220 packet.SetFilePos(::strlen("vFile:pread:"));
1221 int fd = packet.GetS32(-1);
Greg Clayton2b98c562013-11-22 18:53:12 +00001222 if (packet.GetChar() == ',')
Daniel Maleae0f8f572013-08-26 23:57:52 +00001223 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001224 uint64_t count = packet.GetU64(UINT64_MAX);
1225 if (packet.GetChar() == ',')
1226 {
1227 uint64_t offset = packet.GetU64(UINT32_MAX);
1228 if (count == UINT64_MAX)
1229 {
1230 response.Printf("F-1:%i", EINVAL);
1231 return SendPacketNoLock(response.GetData(), response.GetSize());
1232 }
1233
1234 std::string buffer(count, 0);
1235 const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
1236 const int save_errno = bytes_read == -1 ? errno : 0;
1237 response.PutChar('F');
1238 response.Printf("%zi", bytes_read);
1239 if (save_errno)
1240 response.Printf(",%i", save_errno);
1241 else
1242 {
1243 response.PutChar(';');
1244 response.PutEscapedBytes(&buffer[0], bytes_read);
1245 }
1246 return SendPacketNoLock(response.GetData(), response.GetSize());
1247 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001248 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001249 return SendErrorResponse(21);
1250
Virgile Belloae12a362013-08-27 16:21:49 +00001251#endif
Daniel Maleae0f8f572013-08-26 23:57:52 +00001252}
1253
Greg Clayton3dedae12013-12-06 21:45:27 +00001254GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001255GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
1256{
Virgile Belloae12a362013-08-27 16:21:49 +00001257#ifdef _WIN32
Greg Clayton2b98c562013-11-22 18:53:12 +00001258 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pWrite() unimplemented");
Virgile Belloae12a362013-08-27 16:21:49 +00001259#else
Daniel Maleae0f8f572013-08-26 23:57:52 +00001260 packet.SetFilePos(::strlen("vFile:pwrite:"));
1261
1262 StreamGDBRemote response;
1263 response.PutChar('F');
1264
1265 int fd = packet.GetU32(UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001266 if (packet.GetChar() == ',')
Daniel Maleae0f8f572013-08-26 23:57:52 +00001267 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001268 off_t offset = packet.GetU64(UINT32_MAX);
1269 if (packet.GetChar() == ',')
1270 {
1271 std::string buffer;
1272 if (packet.GetEscapedBinaryData(buffer))
1273 {
1274 const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
1275 const int save_errno = bytes_written == -1 ? errno : 0;
1276 response.Printf("%zi", bytes_written);
1277 if (save_errno)
1278 response.Printf(",%i", save_errno);
1279 }
1280 else
1281 {
1282 response.Printf ("-1,%i", EINVAL);
1283 }
1284 return SendPacketNoLock(response.GetData(), response.GetSize());
1285 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001286 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001287 return SendErrorResponse(27);
Virgile Belloae12a362013-08-27 16:21:49 +00001288#endif
Daniel Maleae0f8f572013-08-26 23:57:52 +00001289}
1290
Greg Clayton3dedae12013-12-06 21:45:27 +00001291GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001292GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
1293{
1294 packet.SetFilePos(::strlen("vFile:size:"));
1295 std::string path;
1296 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001297 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001298 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001299 lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
1300 StreamString response;
1301 response.PutChar('F');
1302 response.PutHex64(retcode);
1303 if (retcode == UINT64_MAX)
1304 {
1305 response.PutChar(',');
1306 response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
1307 }
1308 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001309 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001310 return SendErrorResponse(22);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001311}
1312
Greg Clayton3dedae12013-12-06 21:45:27 +00001313GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001314GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
1315{
1316 packet.SetFilePos(::strlen("vFile:mode:"));
1317 std::string path;
1318 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001319 if (!path.empty())
1320 {
1321 Error error;
1322 const uint32_t mode = File::GetPermissions(path.c_str(), error);
1323 StreamString response;
1324 response.Printf("F%u", mode);
1325 if (mode == 0 || error.Fail())
1326 response.Printf(",%i", (int)error.GetError());
1327 return SendPacketNoLock(response.GetData(), response.GetSize());
1328 }
1329 return SendErrorResponse(23);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001330}
1331
Greg Clayton3dedae12013-12-06 21:45:27 +00001332GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001333GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
1334{
1335 packet.SetFilePos(::strlen("vFile:exists:"));
1336 std::string path;
1337 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001338 if (!path.empty())
1339 {
1340 bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
1341 StreamString response;
1342 response.PutChar('F');
1343 response.PutChar(',');
1344 if (retcode)
1345 response.PutChar('1');
1346 else
1347 response.PutChar('0');
1348 return SendPacketNoLock(response.GetData(), response.GetSize());
1349 }
1350 return SendErrorResponse(24);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001351}
1352
Greg Clayton3dedae12013-12-06 21:45:27 +00001353GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001354GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
Daniel Maleae0f8f572013-08-26 23:57:52 +00001355{
Greg Claytonfbb76342013-11-20 21:07:01 +00001356 packet.SetFilePos(::strlen("vFile:symlink:"));
1357 std::string dst, src;
1358 packet.GetHexByteStringTerminatedBy(dst, ',');
1359 packet.GetChar(); // Skip ',' char
1360 packet.GetHexByteString(src);
1361 Error error = Host::Symlink(src.c_str(), dst.c_str());
1362 StreamString response;
1363 response.Printf("F%u,%u", error.GetError(), error.GetError());
Greg Clayton2b98c562013-11-22 18:53:12 +00001364 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001365}
1366
Greg Clayton3dedae12013-12-06 21:45:27 +00001367GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001368GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
1369{
1370 packet.SetFilePos(::strlen("vFile:unlink:"));
1371 std::string path;
1372 packet.GetHexByteString(path);
1373 Error error = Host::Unlink(path.c_str());
1374 StreamString response;
1375 response.Printf("F%u,%u", error.GetError(), error.GetError());
Greg Clayton2b98c562013-11-22 18:53:12 +00001376 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001377}
1378
Greg Clayton3dedae12013-12-06 21:45:27 +00001379GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001380GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
1381{
1382 packet.SetFilePos(::strlen("qPlatform_shell:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001383 std::string path;
1384 std::string working_dir;
1385 packet.GetHexByteStringTerminatedBy(path,',');
Greg Clayton2b98c562013-11-22 18:53:12 +00001386 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001387 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001388 if (packet.GetChar() == ',')
1389 {
1390 // FIXME: add timeout to qPlatform_shell packet
1391 // uint32_t timeout = packet.GetHexMaxU32(false, 32);
1392 uint32_t timeout = 10;
1393 if (packet.GetChar() == ',')
1394 packet.GetHexByteString(working_dir);
1395 int status, signo;
1396 std::string output;
1397 Error err = Host::RunShellCommand(path.c_str(),
1398 working_dir.empty() ? NULL : working_dir.c_str(),
1399 &status, &signo, &output, timeout);
1400 StreamGDBRemote response;
1401 if (err.Fail())
1402 {
1403 response.PutCString("F,");
1404 response.PutHex32(UINT32_MAX);
1405 }
1406 else
1407 {
1408 response.PutCString("F,");
1409 response.PutHex32(status);
1410 response.PutChar(',');
1411 response.PutHex32(signo);
1412 response.PutChar(',');
1413 response.PutEscapedBytes(output.c_str(), output.size());
1414 }
1415 return SendPacketNoLock(response.GetData(), response.GetSize());
1416 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001417 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001418 return SendErrorResponse(24);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001419}
1420
Greg Clayton3dedae12013-12-06 21:45:27 +00001421GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001422GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
1423{
Greg Clayton2b98c562013-11-22 18:53:12 +00001424 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented");
Daniel Maleae0f8f572013-08-26 23:57:52 +00001425}
1426
Greg Clayton3dedae12013-12-06 21:45:27 +00001427GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001428GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
1429{
Greg Clayton2b98c562013-11-22 18:53:12 +00001430 packet.SetFilePos(::strlen("vFile:MD5:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001431 std::string path;
1432 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001433 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001434 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001435 uint64_t a,b;
1436 StreamGDBRemote response;
1437 if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
1438 {
1439 response.PutCString("F,");
1440 response.PutCString("x");
1441 }
1442 else
1443 {
1444 response.PutCString("F,");
1445 response.PutHex64(a);
1446 response.PutHex64(b);
1447 }
1448 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001449 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001450 return SendErrorResponse(25);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001451}
Greg Clayton2b98c562013-11-22 18:53:12 +00001452