blob: 9579e7cc2a5c67e8269ce9bc29e05a5f30cc33c3 [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
Greg Clayton1cb64962011-03-24 04:28:38 +0000316 uint32_t cpu = host_arch.GetMachOCPUType();
317 uint32_t sub = host_arch.GetMachOCPUSubType();
318 if (cpu != LLDB_INVALID_CPUTYPE)
319 response.Printf ("cputype:%u;", cpu);
320 if (sub != LLDB_INVALID_CPUTYPE)
321 response.Printf ("cpusubtype:%u;", sub);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000322
Enrico Granata1c5431a2012-07-13 23:55:22 +0000323 if (cpu == ArchSpec::kCore_arm_any)
Enrico Granataf04a2192012-07-13 23:18:48 +0000324 response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
325 else
326 response.Printf("watchpoint_exceptions_received:after;");
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000327
Greg Clayton576d8832011-03-22 04:00:09 +0000328 switch (lldb::endian::InlHostByteOrder())
329 {
330 case eByteOrderBig: response.PutCString ("endian:big;"); break;
331 case eByteOrderLittle: response.PutCString ("endian:little;"); break;
332 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
333 default: response.PutCString ("endian:unknown;"); break;
334 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000335
Greg Clayton1cb64962011-03-24 04:28:38 +0000336 uint32_t major = UINT32_MAX;
337 uint32_t minor = UINT32_MAX;
338 uint32_t update = UINT32_MAX;
339 if (Host::GetOSVersion (major, minor, update))
340 {
341 if (major != UINT32_MAX)
342 {
343 response.Printf("os_version:%u", major);
344 if (minor != UINT32_MAX)
345 {
346 response.Printf(".%u", minor);
347 if (update != UINT32_MAX)
348 response.Printf(".%u", update);
349 }
350 response.PutChar(';');
351 }
352 }
353
354 std::string s;
355 if (Host::GetOSBuildString (s))
356 {
357 response.PutCString ("os_build:");
358 response.PutCStringAsRawHex8(s.c_str());
359 response.PutChar(';');
360 }
361 if (Host::GetOSKernelDescription (s))
362 {
363 response.PutCString ("os_kernel:");
364 response.PutCStringAsRawHex8(s.c_str());
365 response.PutChar(';');
366 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000367#if defined(__APPLE__)
368
369#if defined(__arm__)
370 // For iOS devices, we are connected through a USB Mux so we never pretend
371 // to actually have a hostname as far as the remote lldb that is connecting
372 // to this lldb-platform is concerned
373 response.PutCString ("hostname:");
374 response.PutCStringAsRawHex8("localhost");
375 response.PutChar(';');
376#else // #if defined(__arm__)
Greg Clayton1cb64962011-03-24 04:28:38 +0000377 if (Host::GetHostname (s))
378 {
379 response.PutCString ("hostname:");
380 response.PutCStringAsRawHex8(s.c_str());
381 response.PutChar(';');
382 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000383
Greg Clayton2b98c562013-11-22 18:53:12 +0000384#endif // #if defined(__arm__)
385
386#else // #if defined(__APPLE__)
387 if (Host::GetHostname (s))
388 {
389 response.PutCString ("hostname:");
390 response.PutCStringAsRawHex8(s.c_str());
391 response.PutChar(';');
392 }
393#endif // #if defined(__APPLE__)
394
Greg Clayton3dedae12013-12-06 21:45:27 +0000395 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton576d8832011-03-22 04:00:09 +0000396}
Greg Clayton1cb64962011-03-24 04:28:38 +0000397
Greg Clayton32e0a752011-03-30 18:16:51 +0000398static void
Greg Clayton8b82f082011-04-12 05:54:46 +0000399CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
Greg Clayton32e0a752011-03-30 18:16:51 +0000400{
Daniel Malead01b2952012-11-29 21:49:15 +0000401 response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
Greg Clayton32e0a752011-03-30 18:16:51 +0000402 proc_info.GetProcessID(),
403 proc_info.GetParentProcessID(),
Greg Clayton8b82f082011-04-12 05:54:46 +0000404 proc_info.GetUserID(),
405 proc_info.GetGroupID(),
Greg Clayton32e0a752011-03-30 18:16:51 +0000406 proc_info.GetEffectiveUserID(),
407 proc_info.GetEffectiveGroupID());
408 response.PutCString ("name:");
409 response.PutCStringAsRawHex8(proc_info.GetName());
410 response.PutChar(';');
411 const ArchSpec &proc_arch = proc_info.GetArchitecture();
412 if (proc_arch.IsValid())
413 {
414 const llvm::Triple &proc_triple = proc_arch.GetTriple();
415 response.PutCString("triple:");
416 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
417 response.PutChar(';');
418 }
419}
Greg Clayton1cb64962011-03-24 04:28:38 +0000420
Greg Clayton3dedae12013-12-06 21:45:27 +0000421GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000422GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
Greg Clayton1cb64962011-03-24 04:28:38 +0000423{
Greg Clayton32e0a752011-03-30 18:16:51 +0000424 // Packet format: "qProcessInfoPID:%i" where %i is the pid
Greg Clayton8b82f082011-04-12 05:54:46 +0000425 packet.SetFilePos(::strlen ("qProcessInfoPID:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000426 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
427 if (pid != LLDB_INVALID_PROCESS_ID)
428 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000429 ProcessInstanceInfo proc_info;
Greg Clayton32e0a752011-03-30 18:16:51 +0000430 if (Host::GetProcessInfo(pid, proc_info))
431 {
432 StreamString response;
433 CreateProcessInfoResponse (proc_info, response);
Greg Clayton37a0a242012-04-11 00:24:49 +0000434 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000435 }
436 }
437 return SendErrorResponse (1);
438}
439
Greg Clayton3dedae12013-12-06 21:45:27 +0000440GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000441GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
442{
443 m_proc_infos_index = 0;
444 m_proc_infos.Clear();
445
Greg Clayton8b82f082011-04-12 05:54:46 +0000446 ProcessInstanceInfoMatch match_info;
447 packet.SetFilePos(::strlen ("qfProcessInfo"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000448 if (packet.GetChar() == ':')
449 {
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000450
Greg Clayton32e0a752011-03-30 18:16:51 +0000451 std::string key;
452 std::string value;
453 while (packet.GetNameColonValue(key, value))
454 {
455 bool success = true;
456 if (key.compare("name") == 0)
457 {
458 StringExtractor extractor;
459 extractor.GetStringRef().swap(value);
460 extractor.GetHexByteString (value);
Greg Clayton144f3a92011-11-15 03:53:30 +0000461 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
Greg Clayton32e0a752011-03-30 18:16:51 +0000462 }
463 else if (key.compare("name_match") == 0)
464 {
465 if (value.compare("equals") == 0)
466 {
467 match_info.SetNameMatchType (eNameMatchEquals);
468 }
469 else if (value.compare("starts_with") == 0)
470 {
471 match_info.SetNameMatchType (eNameMatchStartsWith);
472 }
473 else if (value.compare("ends_with") == 0)
474 {
475 match_info.SetNameMatchType (eNameMatchEndsWith);
476 }
477 else if (value.compare("contains") == 0)
478 {
479 match_info.SetNameMatchType (eNameMatchContains);
480 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000481 else if (value.compare("regex") == 0)
Greg Clayton32e0a752011-03-30 18:16:51 +0000482 {
483 match_info.SetNameMatchType (eNameMatchRegularExpression);
484 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000485 else
Greg Clayton32e0a752011-03-30 18:16:51 +0000486 {
487 success = false;
488 }
489 }
490 else if (key.compare("pid") == 0)
491 {
492 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
493 }
494 else if (key.compare("parent_pid") == 0)
495 {
496 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
497 }
498 else if (key.compare("uid") == 0)
499 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000500 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton32e0a752011-03-30 18:16:51 +0000501 }
502 else if (key.compare("gid") == 0)
503 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000504 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton32e0a752011-03-30 18:16:51 +0000505 }
506 else if (key.compare("euid") == 0)
507 {
508 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
509 }
510 else if (key.compare("egid") == 0)
511 {
512 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
513 }
514 else if (key.compare("all_users") == 0)
515 {
516 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
517 }
518 else if (key.compare("triple") == 0)
519 {
Greg Claytoneb0103f2011-04-07 22:46:35 +0000520 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
Greg Clayton32e0a752011-03-30 18:16:51 +0000521 }
522 else
523 {
524 success = false;
525 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000526
Greg Clayton32e0a752011-03-30 18:16:51 +0000527 if (!success)
528 return SendErrorResponse (2);
529 }
530 }
531
532 if (Host::FindProcesses (match_info, m_proc_infos))
533 {
534 // We found something, return the first item by calling the get
535 // subsequent process info packet handler...
536 return Handle_qsProcessInfo (packet);
537 }
538 return SendErrorResponse (3);
539}
540
Greg Clayton3dedae12013-12-06 21:45:27 +0000541GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000542GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
543{
544 if (m_proc_infos_index < m_proc_infos.GetSize())
545 {
546 StreamString response;
547 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
548 ++m_proc_infos_index;
Greg Clayton37a0a242012-04-11 00:24:49 +0000549 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000550 }
551 return SendErrorResponse (4);
552}
553
Greg Clayton3dedae12013-12-06 21:45:27 +0000554GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000555GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
556{
557 // Packet format: "qUserName:%i" where %i is the uid
Greg Clayton8b82f082011-04-12 05:54:46 +0000558 packet.SetFilePos(::strlen ("qUserName:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000559 uint32_t uid = packet.GetU32 (UINT32_MAX);
560 if (uid != UINT32_MAX)
561 {
562 std::string name;
563 if (Host::GetUserName (uid, name))
564 {
565 StreamString response;
566 response.PutCStringAsRawHex8 (name.c_str());
Greg Clayton37a0a242012-04-11 00:24:49 +0000567 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000568 }
569 }
570 return SendErrorResponse (5);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000571
Greg Clayton32e0a752011-03-30 18:16:51 +0000572}
573
Greg Clayton3dedae12013-12-06 21:45:27 +0000574GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +0000575GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
576{
577 // Packet format: "qGroupName:%i" where %i is the gid
Greg Clayton8b82f082011-04-12 05:54:46 +0000578 packet.SetFilePos(::strlen ("qGroupName:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000579 uint32_t gid = packet.GetU32 (UINT32_MAX);
580 if (gid != UINT32_MAX)
581 {
582 std::string name;
583 if (Host::GetGroupName (gid, name))
584 {
585 StreamString response;
586 response.PutCStringAsRawHex8 (name.c_str());
Greg Clayton37a0a242012-04-11 00:24:49 +0000587 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000588 }
589 }
590 return SendErrorResponse (6);
591}
592
Greg Clayton3dedae12013-12-06 21:45:27 +0000593GDBRemoteCommunication::PacketResult
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000594GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
595{
Greg Clayton8b82f082011-04-12 05:54:46 +0000596 packet.SetFilePos(::strlen ("qSpeedTest:"));
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000597
598 std::string key;
599 std::string value;
600 bool success = packet.GetNameColonValue(key, value);
601 if (success && key.compare("response_size") == 0)
602 {
603 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
604 if (success)
605 {
606 if (response_size == 0)
607 return SendOKResponse();
608 StreamString response;
609 uint32_t bytes_left = response_size;
610 response.PutCString("data:");
611 while (bytes_left > 0)
612 {
613 if (bytes_left >= 26)
614 {
615 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
616 bytes_left -= 26;
617 }
618 else
619 {
620 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
621 bytes_left = 0;
622 }
623 }
Greg Clayton37a0a242012-04-11 00:24:49 +0000624 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000625 }
626 }
627 return SendErrorResponse (7);
628}
Greg Clayton8b82f082011-04-12 05:54:46 +0000629
630
631static void *
632AcceptPortFromInferior (void *arg)
633{
634 const char *connect_url = (const char *)arg;
635 ConnectionFileDescriptor file_conn;
636 Error error;
637 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
638 {
639 char pid_str[256];
640 ::memset (pid_str, 0, sizeof(pid_str));
641 ConnectionStatus status;
Bill Wendlinged24dcc2012-04-03 07:50:11 +0000642 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
Greg Clayton8b82f082011-04-12 05:54:46 +0000643 if (pid_str_len > 0)
644 {
645 int pid = atoi (pid_str);
646 return (void *)(intptr_t)pid;
647 }
648 }
649 return NULL;
650}
651//
652//static bool
653//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
654//{
655// const int time_delta_usecs = 100000;
656// const int num_retries = timeout_in_seconds/time_delta_usecs;
657// for (int i=0; i<num_retries; i++)
658// {
659// struct proc_bsdinfo bsd_info;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000660// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
661// (uint64_t) 0,
662// &bsd_info,
Greg Clayton8b82f082011-04-12 05:54:46 +0000663// PROC_PIDTBSDINFO_SIZE);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000664//
Greg Clayton8b82f082011-04-12 05:54:46 +0000665// switch (error)
666// {
667// case EINVAL:
668// case ENOTSUP:
669// case ESRCH:
670// case EPERM:
671// return false;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000672//
Greg Clayton8b82f082011-04-12 05:54:46 +0000673// default:
674// break;
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000675//
Greg Clayton8b82f082011-04-12 05:54:46 +0000676// case 0:
677// if (bsd_info.pbi_status == SSTOP)
678// return true;
679// }
680// ::usleep (time_delta_usecs);
681// }
682// return false;
683//}
684
Greg Clayton3dedae12013-12-06 21:45:27 +0000685GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000686GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
687{
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000688 // The 'A' packet is the most over designed packet ever here with
689 // redundant argument indexes, redundant argument lengths and needed hex
690 // encoded argument string values. Really all that is needed is a comma
Greg Clayton8b82f082011-04-12 05:54:46 +0000691 // separated hex encoded argument value list, but we will stay true to the
692 // documented version of the 'A' packet here...
693
694 packet.SetFilePos(1); // Skip the 'A'
695 bool success = true;
696 while (success && packet.GetBytesLeft() > 0)
697 {
698 // Decode the decimal argument string length. This length is the
699 // number of hex nibbles in the argument string value.
700 const uint32_t arg_len = packet.GetU32(UINT32_MAX);
701 if (arg_len == UINT32_MAX)
702 success = false;
703 else
704 {
705 // Make sure the argument hex string length is followed by a comma
706 if (packet.GetChar() != ',')
707 success = false;
708 else
709 {
710 // Decode the argument index. We ignore this really becuase
711 // who would really send down the arguments in a random order???
712 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
713 if (arg_idx == UINT32_MAX)
714 success = false;
715 else
716 {
717 // Make sure the argument index is followed by a comma
718 if (packet.GetChar() != ',')
719 success = false;
720 else
721 {
722 // Decode the argument string value from hex bytes
723 // back into a UTF8 string and make sure the length
724 // matches the one supplied in the packet
725 std::string arg;
726 if (packet.GetHexByteString(arg) != (arg_len / 2))
727 success = false;
728 else
729 {
730 // If there are any bytes lft
731 if (packet.GetBytesLeft())
732 {
733 if (packet.GetChar() != ',')
734 success = false;
735 }
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000736
Greg Clayton8b82f082011-04-12 05:54:46 +0000737 if (success)
738 {
739 if (arg_idx == 0)
740 m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
741 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
742 }
743 }
744 }
745 }
746 }
747 }
748 }
749
750 if (success)
751 {
752 m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
753 m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
754 if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
755 {
756 return SendOKResponse ();
757 }
758 }
759 return SendErrorResponse (8);
760}
761
Greg Clayton3dedae12013-12-06 21:45:27 +0000762GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000763GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
764{
765 lldb::pid_t pid = m_process_launch_info.GetProcessID();
766 StreamString response;
Daniel Malead01b2952012-11-29 21:49:15 +0000767 response.Printf("QC%" PRIx64, pid);
Greg Clayton8b82f082011-04-12 05:54:46 +0000768 if (m_is_platform)
769 {
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000770 // If we launch a process and this GDB server is acting as a platform,
771 // then we need to clear the process launch state so we can start
Greg Clayton8b82f082011-04-12 05:54:46 +0000772 // launching another process. In order to launch a process a bunch or
773 // packets need to be sent: environment packets, working directory,
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000774 // disable ASLR, and many more settings. When we launch a process we
Greg Clayton8b82f082011-04-12 05:54:46 +0000775 // then need to know when to clear this information. Currently we are
776 // selecting the 'qC' packet as that packet which seems to make the most
777 // sense.
778 if (pid != LLDB_INVALID_PROCESS_ID)
779 {
780 m_process_launch_info.Clear();
781 }
782 }
Greg Clayton37a0a242012-04-11 00:24:49 +0000783 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton8b82f082011-04-12 05:54:46 +0000784}
785
786bool
Daniel Maleae0f8f572013-08-26 23:57:52 +0000787GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
788{
789 Mutex::Locker locker (m_spawned_pids_mutex);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000790 FreePortForProcess(pid);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000791 return m_spawned_pids.erase(pid) > 0;
792}
793bool
794GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
795 lldb::pid_t pid,
796 bool exited,
797 int signal, // Zero for no signal
798 int status) // Exit value of process if signal is zero
799{
800 GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
801 server->DebugserverProcessReaped (pid);
802 return true;
803}
804
Greg Clayton3dedae12013-12-06 21:45:27 +0000805GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000806GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
807{
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000808#ifdef _WIN32
Deepak Panickal263fde02014-01-14 11:34:44 +0000809 return SendErrorResponse(9);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000810#else
Greg Clayton8b82f082011-04-12 05:54:46 +0000811 // Spawn a local debugserver as a platform so we can then attach or launch
812 // a process...
813
814 if (m_is_platform)
815 {
816 // Sleep and wait a bit for debugserver to start to listen...
817 ConnectionFileDescriptor file_conn;
Greg Clayton8b82f082011-04-12 05:54:46 +0000818 Error error;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000819 std::string hostname;
Sylvestre Ledrufaa63ce2013-09-28 15:57:37 +0000820 // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
821 // with the TMPDIR environnement variable
Greg Clayton29b8fc42013-11-21 01:44:58 +0000822 packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
823 std::string name;
824 std::string value;
825 uint16_t port = UINT16_MAX;
826 while (packet.GetNameColonValue(name, value))
Greg Clayton8b82f082011-04-12 05:54:46 +0000827 {
Greg Clayton29b8fc42013-11-21 01:44:58 +0000828 if (name.compare ("host") == 0)
829 hostname.swap(value);
830 else if (name.compare ("port") == 0)
831 port = Args::StringToUInt32(value.c_str(), 0, 0);
Greg Clayton8b82f082011-04-12 05:54:46 +0000832 }
Greg Clayton29b8fc42013-11-21 01:44:58 +0000833 if (port == UINT16_MAX)
834 port = GetNextAvailablePort();
835
836 // Spawn a new thread to accept the port that gets bound after
837 // binding to port 0 (zero).
Greg Claytonfbb76342013-11-20 21:07:01 +0000838
Greg Clayton29b8fc42013-11-21 01:44:58 +0000839 if (error.Success())
840 {
841 // Spawn a debugserver and try to get the port it listens to.
842 ProcessLaunchInfo debugserver_launch_info;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000843 if (hostname.empty())
844 hostname = "localhost";
Greg Clayton29b8fc42013-11-21 01:44:58 +0000845 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
846 if (log)
Greg Claytonfda4fab2014-01-10 22:24:11 +0000847 log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000848
Greg Clayton29b8fc42013-11-21 01:44:58 +0000849 debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
850
Greg Claytonfda4fab2014-01-10 22:24:11 +0000851 error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
852 port,
Greg Clayton00fe87b2013-12-05 22:58:22 +0000853 debugserver_launch_info,
854 port);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000855
856 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000857
Greg Claytonfbb76342013-11-20 21:07:01 +0000858
Greg Clayton29b8fc42013-11-21 01:44:58 +0000859 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
860 {
861 Mutex::Locker locker (m_spawned_pids_mutex);
862 m_spawned_pids.insert(debugserver_pid);
863 if (port > 0)
864 AssociatePortWithProcess(port, debugserver_pid);
865 }
866 else
867 {
868 if (port > 0)
869 FreePort (port);
870 }
871
872 if (error.Success())
873 {
Greg Clayton91a9b2472013-12-04 19:19:12 +0000874 char response[256];
875 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
876 assert (response_len < sizeof(response));
Greg Clayton3dedae12013-12-06 21:45:27 +0000877 PacketResult packet_result = SendPacketNoLock (response, response_len);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000878
Greg Clayton3dedae12013-12-06 21:45:27 +0000879 if (packet_result != PacketResult::Success)
Greg Clayton29b8fc42013-11-21 01:44:58 +0000880 {
881 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
882 ::kill (debugserver_pid, SIGINT);
883 }
Greg Clayton3dedae12013-12-06 21:45:27 +0000884 return packet_result;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000885 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000886 }
887 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000888 return SendErrorResponse (9);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000889#endif
Greg Clayton8b82f082011-04-12 05:54:46 +0000890}
891
Greg Clayton3dedae12013-12-06 21:45:27 +0000892GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +0000893GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
894{
895 // Spawn a local debugserver as a platform so we can then attach or launch
896 // a process...
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000897
Daniel Maleae0f8f572013-08-26 23:57:52 +0000898 if (m_is_platform)
899 {
900 packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000901
Daniel Maleae0f8f572013-08-26 23:57:52 +0000902 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
903
904 // Scope for locker
905 {
906 Mutex::Locker locker (m_spawned_pids_mutex);
907 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
908 return SendErrorResponse (10);
909 }
Virgile Belloae12a362013-08-27 16:21:49 +0000910 Host::Kill (pid, SIGTERM);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000911
Daniel Maleae0f8f572013-08-26 23:57:52 +0000912 for (size_t i=0; i<10; ++i)
913 {
914 // Scope for locker
915 {
916 Mutex::Locker locker (m_spawned_pids_mutex);
917 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000918 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000919 }
920 usleep (10000);
921 }
922
923 // Scope for locker
924 {
925 Mutex::Locker locker (m_spawned_pids_mutex);
926 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000927 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000928 }
Virgile Belloae12a362013-08-27 16:21:49 +0000929 Host::Kill (pid, SIGKILL);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000930
Daniel Maleae0f8f572013-08-26 23:57:52 +0000931 for (size_t i=0; i<10; ++i)
932 {
933 // Scope for locker
934 {
935 Mutex::Locker locker (m_spawned_pids_mutex);
936 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000937 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000938 }
939 usleep (10000);
940 }
941 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000942 return SendErrorResponse (11);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000943}
944
Greg Clayton3dedae12013-12-06 21:45:27 +0000945GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000946GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
947{
948 if (m_process_launch_error.Success())
949 return SendOKResponse();
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000950 StreamString response;
Greg Clayton8b82f082011-04-12 05:54:46 +0000951 response.PutChar('E');
952 response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
Greg Clayton37a0a242012-04-11 00:24:49 +0000953 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton8b82f082011-04-12 05:54:46 +0000954}
955
Greg Clayton3dedae12013-12-06 21:45:27 +0000956GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000957GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
958{
959 packet.SetFilePos(::strlen ("QEnvironment:"));
960 const uint32_t bytes_left = packet.GetBytesLeft();
961 if (bytes_left > 0)
962 {
963 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
964 return SendOKResponse ();
965 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000966 return SendErrorResponse (12);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000967}
968
Greg Clayton3dedae12013-12-06 21:45:27 +0000969GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +0000970GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
971{
972 packet.SetFilePos(::strlen ("QLaunchArch:"));
973 const uint32_t bytes_left = packet.GetBytesLeft();
974 if (bytes_left > 0)
975 {
976 const char* arch_triple = packet.Peek();
977 ArchSpec arch_spec(arch_triple,NULL);
978 m_process_launch_info.SetArchitecture(arch_spec);
979 return SendOKResponse();
980 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000981 return SendErrorResponse(13);
Greg Clayton8b82f082011-04-12 05:54:46 +0000982}
983
Greg Clayton3dedae12013-12-06 21:45:27 +0000984GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000985GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
986{
987 packet.SetFilePos(::strlen ("QSetDisableASLR:"));
988 if (packet.GetU32(0))
989 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
990 else
991 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
992 return SendOKResponse ();
993}
994
Greg Clayton3dedae12013-12-06 21:45:27 +0000995GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000996GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
997{
998 packet.SetFilePos(::strlen ("QSetWorkingDir:"));
999 std::string path;
1000 packet.GetHexByteString(path);
Greg Claytonfbb76342013-11-20 21:07:01 +00001001 if (m_is_platform)
1002 {
Colin Riley909bb7a2013-11-26 15:10:46 +00001003#ifdef _WIN32
1004 // Not implemented on Windows
1005 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_QSetWorkingDir unimplemented");
1006#else
Greg Claytonfbb76342013-11-20 21:07:01 +00001007 // If this packet is sent to a platform, then change the current working directory
1008 if (::chdir(path.c_str()) != 0)
1009 return SendErrorResponse(errno);
Colin Riley909bb7a2013-11-26 15:10:46 +00001010#endif
Greg Claytonfbb76342013-11-20 21:07:01 +00001011 }
1012 else
1013 {
1014 m_process_launch_info.SwapWorkingDirectory (path);
1015 }
Greg Clayton8b82f082011-04-12 05:54:46 +00001016 return SendOKResponse ();
1017}
1018
Greg Clayton3dedae12013-12-06 21:45:27 +00001019GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001020GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
1021{
1022 StreamString response;
1023
1024 if (m_is_platform)
1025 {
1026 // If this packet is sent to a platform, then change the current working directory
1027 char cwd[PATH_MAX];
1028 if (getcwd(cwd, sizeof(cwd)) == NULL)
1029 {
1030 return SendErrorResponse(errno);
1031 }
1032 else
1033 {
1034 response.PutBytesAsRawHex8(cwd, strlen(cwd));
Greg Clayton3dedae12013-12-06 21:45:27 +00001035 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001036 }
1037 }
1038 else
1039 {
1040 const char *working_dir = m_process_launch_info.GetWorkingDirectory();
1041 if (working_dir && working_dir[0])
1042 {
1043 response.PutBytesAsRawHex8(working_dir, strlen(working_dir));
Greg Clayton3dedae12013-12-06 21:45:27 +00001044 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001045 }
1046 else
1047 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001048 return SendErrorResponse(14);
Greg Claytonfbb76342013-11-20 21:07:01 +00001049 }
1050 }
1051}
1052
Greg Clayton3dedae12013-12-06 21:45:27 +00001053GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001054GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
1055{
1056 packet.SetFilePos(::strlen ("QSetSTDIN:"));
1057 ProcessLaunchInfo::FileAction file_action;
1058 std::string path;
1059 packet.GetHexByteString(path);
1060 const bool read = false;
1061 const bool write = true;
1062 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
1063 {
1064 m_process_launch_info.AppendFileAction(file_action);
1065 return SendOKResponse ();
1066 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001067 return SendErrorResponse (15);
Greg Clayton8b82f082011-04-12 05:54:46 +00001068}
1069
Greg Clayton3dedae12013-12-06 21:45:27 +00001070GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001071GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
1072{
1073 packet.SetFilePos(::strlen ("QSetSTDOUT:"));
1074 ProcessLaunchInfo::FileAction file_action;
1075 std::string path;
1076 packet.GetHexByteString(path);
1077 const bool read = true;
1078 const bool write = false;
1079 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
1080 {
1081 m_process_launch_info.AppendFileAction(file_action);
1082 return SendOKResponse ();
1083 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001084 return SendErrorResponse (16);
Greg Clayton8b82f082011-04-12 05:54:46 +00001085}
1086
Greg Clayton3dedae12013-12-06 21:45:27 +00001087GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001088GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
1089{
1090 packet.SetFilePos(::strlen ("QSetSTDERR:"));
1091 ProcessLaunchInfo::FileAction file_action;
1092 std::string path;
1093 packet.GetHexByteString(path);
1094 const bool read = true;
Greg Clayton9845a8d2012-03-06 04:01:04 +00001095 const bool write = false;
Greg Clayton8b82f082011-04-12 05:54:46 +00001096 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
1097 {
1098 m_process_launch_info.AppendFileAction(file_action);
1099 return SendOKResponse ();
1100 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001101 return SendErrorResponse (17);
Greg Clayton8b82f082011-04-12 05:54:46 +00001102}
1103
Greg Clayton3dedae12013-12-06 21:45:27 +00001104GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +00001105GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
1106{
1107 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton3dedae12013-12-06 21:45:27 +00001108 PacketResult packet_result = SendOKResponse ();
Greg Clayton1cb64962011-03-24 04:28:38 +00001109 m_send_acks = false;
Greg Clayton3dedae12013-12-06 21:45:27 +00001110 return packet_result;
Greg Clayton1cb64962011-03-24 04:28:38 +00001111}
Daniel Maleae0f8f572013-08-26 23:57:52 +00001112
Greg Clayton3dedae12013-12-06 21:45:27 +00001113GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001114GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
Daniel Maleae0f8f572013-08-26 23:57:52 +00001115{
Greg Claytonfbb76342013-11-20 21:07:01 +00001116 packet.SetFilePos(::strlen("qPlatform_mkdir:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001117 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001118 if (packet.GetChar() == ',')
1119 {
1120 std::string path;
1121 packet.GetHexByteString(path);
1122 Error error = Host::MakeDirectory(path.c_str(),mode);
1123 if (error.Success())
1124 return SendPacketNoLock ("OK", 2);
1125 else
1126 return SendErrorResponse(error.GetError());
1127 }
1128 return SendErrorResponse(20);
Greg Claytonfbb76342013-11-20 21:07:01 +00001129}
1130
Greg Clayton3dedae12013-12-06 21:45:27 +00001131GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001132GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
1133{
1134 packet.SetFilePos(::strlen("qPlatform_chmod:"));
1135
1136 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001137 if (packet.GetChar() == ',')
1138 {
1139 std::string path;
1140 packet.GetHexByteString(path);
1141 Error error = Host::SetFilePermissions (path.c_str(), mode);
1142 if (error.Success())
1143 return SendPacketNoLock ("OK", 2);
1144 else
1145 return SendErrorResponse(error.GetError());
1146 }
1147 return SendErrorResponse(19);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001148}
1149
Greg Clayton3dedae12013-12-06 21:45:27 +00001150GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001151GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
1152{
1153 packet.SetFilePos(::strlen("vFile:open:"));
1154 std::string path;
1155 packet.GetHexByteStringTerminatedBy(path,',');
Greg Clayton2b98c562013-11-22 18:53:12 +00001156 if (!path.empty())
1157 {
1158 if (packet.GetChar() == ',')
1159 {
1160 uint32_t flags = packet.GetHexMaxU32(false, 0);
1161 if (packet.GetChar() == ',')
1162 {
1163 mode_t mode = packet.GetHexMaxU32(false, 0600);
1164 Error error;
1165 int fd = ::open (path.c_str(), flags, mode);
Greg Clayton2b98c562013-11-22 18:53:12 +00001166 const int save_errno = fd == -1 ? errno : 0;
1167 StreamString response;
1168 response.PutChar('F');
1169 response.Printf("%i", fd);
1170 if (save_errno)
1171 response.Printf(",%i", save_errno);
1172 return SendPacketNoLock(response.GetData(), response.GetSize());
1173 }
1174 }
1175 }
1176 return SendErrorResponse(18);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001177}
1178
Greg Clayton3dedae12013-12-06 21:45:27 +00001179GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001180GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
1181{
1182 packet.SetFilePos(::strlen("vFile:close:"));
1183 int fd = packet.GetS32(-1);
1184 Error error;
1185 int err = -1;
1186 int save_errno = 0;
1187 if (fd >= 0)
1188 {
1189 err = close(fd);
1190 save_errno = err == -1 ? errno : 0;
1191 }
1192 else
1193 {
1194 save_errno = EINVAL;
1195 }
1196 StreamString response;
1197 response.PutChar('F');
1198 response.Printf("%i", err);
1199 if (save_errno)
1200 response.Printf(",%i", save_errno);
Greg Clayton2b98c562013-11-22 18:53:12 +00001201 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001202}
1203
Greg Clayton3dedae12013-12-06 21:45:27 +00001204GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001205GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
1206{
Virgile Belloae12a362013-08-27 16:21:49 +00001207#ifdef _WIN32
1208 // Not implemented on Windows
Greg Clayton2b98c562013-11-22 18:53:12 +00001209 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pRead() unimplemented");
Virgile Belloae12a362013-08-27 16:21:49 +00001210#else
Daniel Maleae0f8f572013-08-26 23:57:52 +00001211 StreamGDBRemote response;
1212 packet.SetFilePos(::strlen("vFile:pread:"));
1213 int fd = packet.GetS32(-1);
Greg Clayton2b98c562013-11-22 18:53:12 +00001214 if (packet.GetChar() == ',')
Daniel Maleae0f8f572013-08-26 23:57:52 +00001215 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001216 uint64_t count = packet.GetU64(UINT64_MAX);
1217 if (packet.GetChar() == ',')
1218 {
1219 uint64_t offset = packet.GetU64(UINT32_MAX);
1220 if (count == UINT64_MAX)
1221 {
1222 response.Printf("F-1:%i", EINVAL);
1223 return SendPacketNoLock(response.GetData(), response.GetSize());
1224 }
1225
1226 std::string buffer(count, 0);
1227 const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
1228 const int save_errno = bytes_read == -1 ? errno : 0;
1229 response.PutChar('F');
1230 response.Printf("%zi", bytes_read);
1231 if (save_errno)
1232 response.Printf(",%i", save_errno);
1233 else
1234 {
1235 response.PutChar(';');
1236 response.PutEscapedBytes(&buffer[0], bytes_read);
1237 }
1238 return SendPacketNoLock(response.GetData(), response.GetSize());
1239 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001240 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001241 return SendErrorResponse(21);
1242
Virgile Belloae12a362013-08-27 16:21:49 +00001243#endif
Daniel Maleae0f8f572013-08-26 23:57:52 +00001244}
1245
Greg Clayton3dedae12013-12-06 21:45:27 +00001246GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001247GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
1248{
Virgile Belloae12a362013-08-27 16:21:49 +00001249#ifdef _WIN32
Greg Clayton2b98c562013-11-22 18:53:12 +00001250 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pWrite() unimplemented");
Virgile Belloae12a362013-08-27 16:21:49 +00001251#else
Daniel Maleae0f8f572013-08-26 23:57:52 +00001252 packet.SetFilePos(::strlen("vFile:pwrite:"));
1253
1254 StreamGDBRemote response;
1255 response.PutChar('F');
1256
1257 int fd = packet.GetU32(UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001258 if (packet.GetChar() == ',')
Daniel Maleae0f8f572013-08-26 23:57:52 +00001259 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001260 off_t offset = packet.GetU64(UINT32_MAX);
1261 if (packet.GetChar() == ',')
1262 {
1263 std::string buffer;
1264 if (packet.GetEscapedBinaryData(buffer))
1265 {
1266 const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
1267 const int save_errno = bytes_written == -1 ? errno : 0;
1268 response.Printf("%zi", bytes_written);
1269 if (save_errno)
1270 response.Printf(",%i", save_errno);
1271 }
1272 else
1273 {
1274 response.Printf ("-1,%i", EINVAL);
1275 }
1276 return SendPacketNoLock(response.GetData(), response.GetSize());
1277 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001278 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001279 return SendErrorResponse(27);
Virgile Belloae12a362013-08-27 16:21:49 +00001280#endif
Daniel Maleae0f8f572013-08-26 23:57:52 +00001281}
1282
Greg Clayton3dedae12013-12-06 21:45:27 +00001283GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001284GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
1285{
1286 packet.SetFilePos(::strlen("vFile:size:"));
1287 std::string path;
1288 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001289 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001290 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001291 lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
1292 StreamString response;
1293 response.PutChar('F');
1294 response.PutHex64(retcode);
1295 if (retcode == UINT64_MAX)
1296 {
1297 response.PutChar(',');
1298 response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
1299 }
1300 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001301 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001302 return SendErrorResponse(22);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001303}
1304
Greg Clayton3dedae12013-12-06 21:45:27 +00001305GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001306GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
1307{
1308 packet.SetFilePos(::strlen("vFile:mode:"));
1309 std::string path;
1310 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001311 if (!path.empty())
1312 {
1313 Error error;
1314 const uint32_t mode = File::GetPermissions(path.c_str(), error);
1315 StreamString response;
1316 response.Printf("F%u", mode);
1317 if (mode == 0 || error.Fail())
1318 response.Printf(",%i", (int)error.GetError());
1319 return SendPacketNoLock(response.GetData(), response.GetSize());
1320 }
1321 return SendErrorResponse(23);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001322}
1323
Greg Clayton3dedae12013-12-06 21:45:27 +00001324GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001325GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
1326{
1327 packet.SetFilePos(::strlen("vFile:exists:"));
1328 std::string path;
1329 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001330 if (!path.empty())
1331 {
1332 bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
1333 StreamString response;
1334 response.PutChar('F');
1335 response.PutChar(',');
1336 if (retcode)
1337 response.PutChar('1');
1338 else
1339 response.PutChar('0');
1340 return SendPacketNoLock(response.GetData(), response.GetSize());
1341 }
1342 return SendErrorResponse(24);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001343}
1344
Greg Clayton3dedae12013-12-06 21:45:27 +00001345GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001346GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
Daniel Maleae0f8f572013-08-26 23:57:52 +00001347{
Greg Claytonfbb76342013-11-20 21:07:01 +00001348 packet.SetFilePos(::strlen("vFile:symlink:"));
1349 std::string dst, src;
1350 packet.GetHexByteStringTerminatedBy(dst, ',');
1351 packet.GetChar(); // Skip ',' char
1352 packet.GetHexByteString(src);
1353 Error error = Host::Symlink(src.c_str(), dst.c_str());
1354 StreamString response;
1355 response.Printf("F%u,%u", error.GetError(), error.GetError());
Greg Clayton2b98c562013-11-22 18:53:12 +00001356 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001357}
1358
Greg Clayton3dedae12013-12-06 21:45:27 +00001359GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001360GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
1361{
1362 packet.SetFilePos(::strlen("vFile:unlink:"));
1363 std::string path;
1364 packet.GetHexByteString(path);
1365 Error error = Host::Unlink(path.c_str());
1366 StreamString response;
1367 response.Printf("F%u,%u", error.GetError(), error.GetError());
Greg Clayton2b98c562013-11-22 18:53:12 +00001368 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001369}
1370
Greg Clayton3dedae12013-12-06 21:45:27 +00001371GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001372GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
1373{
1374 packet.SetFilePos(::strlen("qPlatform_shell:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001375 std::string path;
1376 std::string working_dir;
1377 packet.GetHexByteStringTerminatedBy(path,',');
Greg Clayton2b98c562013-11-22 18:53:12 +00001378 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001379 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001380 if (packet.GetChar() == ',')
1381 {
1382 // FIXME: add timeout to qPlatform_shell packet
1383 // uint32_t timeout = packet.GetHexMaxU32(false, 32);
1384 uint32_t timeout = 10;
1385 if (packet.GetChar() == ',')
1386 packet.GetHexByteString(working_dir);
1387 int status, signo;
1388 std::string output;
1389 Error err = Host::RunShellCommand(path.c_str(),
1390 working_dir.empty() ? NULL : working_dir.c_str(),
1391 &status, &signo, &output, timeout);
1392 StreamGDBRemote response;
1393 if (err.Fail())
1394 {
1395 response.PutCString("F,");
1396 response.PutHex32(UINT32_MAX);
1397 }
1398 else
1399 {
1400 response.PutCString("F,");
1401 response.PutHex32(status);
1402 response.PutChar(',');
1403 response.PutHex32(signo);
1404 response.PutChar(',');
1405 response.PutEscapedBytes(output.c_str(), output.size());
1406 }
1407 return SendPacketNoLock(response.GetData(), response.GetSize());
1408 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001409 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001410 return SendErrorResponse(24);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001411}
1412
Greg Clayton3dedae12013-12-06 21:45:27 +00001413GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001414GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
1415{
Greg Clayton2b98c562013-11-22 18:53:12 +00001416 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented");
Daniel Maleae0f8f572013-08-26 23:57:52 +00001417}
1418
Greg Clayton3dedae12013-12-06 21:45:27 +00001419GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001420GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
1421{
Greg Clayton2b98c562013-11-22 18:53:12 +00001422 packet.SetFilePos(::strlen("vFile:MD5:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001423 std::string path;
1424 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001425 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001426 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001427 uint64_t a,b;
1428 StreamGDBRemote response;
1429 if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
1430 {
1431 response.PutCString("F,");
1432 response.PutCString("x");
1433 }
1434 else
1435 {
1436 response.PutCString("F,");
1437 response.PutHex64(a);
1438 response.PutHex64(b);
1439 }
1440 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001441 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001442 return SendErrorResponse(25);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001443}
Greg Clayton2b98c562013-11-22 18:53:12 +00001444