blob: 91658b98d6199a75e8f6467d79a6e0c9825d0090 [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
809 // No unix sockets on windows
810 return false;
811#else
Greg Clayton8b82f082011-04-12 05:54:46 +0000812 // Spawn a local debugserver as a platform so we can then attach or launch
813 // a process...
814
815 if (m_is_platform)
816 {
817 // Sleep and wait a bit for debugserver to start to listen...
818 ConnectionFileDescriptor file_conn;
Greg Clayton8b82f082011-04-12 05:54:46 +0000819 Error error;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000820 std::string hostname;
Sylvestre Ledrufaa63ce2013-09-28 15:57:37 +0000821 // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
822 // with the TMPDIR environnement variable
Greg Clayton29b8fc42013-11-21 01:44:58 +0000823 packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
824 std::string name;
825 std::string value;
826 uint16_t port = UINT16_MAX;
827 while (packet.GetNameColonValue(name, value))
Greg Clayton8b82f082011-04-12 05:54:46 +0000828 {
Greg Clayton29b8fc42013-11-21 01:44:58 +0000829 if (name.compare ("host") == 0)
830 hostname.swap(value);
831 else if (name.compare ("port") == 0)
832 port = Args::StringToUInt32(value.c_str(), 0, 0);
Greg Clayton8b82f082011-04-12 05:54:46 +0000833 }
Greg Clayton29b8fc42013-11-21 01:44:58 +0000834 if (port == UINT16_MAX)
835 port = GetNextAvailablePort();
836
837 // Spawn a new thread to accept the port that gets bound after
838 // binding to port 0 (zero).
Greg Claytonfbb76342013-11-20 21:07:01 +0000839
Greg Clayton29b8fc42013-11-21 01:44:58 +0000840 if (error.Success())
841 {
842 // Spawn a debugserver and try to get the port it listens to.
843 ProcessLaunchInfo debugserver_launch_info;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000844 if (hostname.empty())
845 hostname = "localhost";
Greg Clayton29b8fc42013-11-21 01:44:58 +0000846 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
847 if (log)
Greg Claytonfda4fab2014-01-10 22:24:11 +0000848 log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000849
Greg Clayton29b8fc42013-11-21 01:44:58 +0000850 debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
851
Greg Claytonfda4fab2014-01-10 22:24:11 +0000852 error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
853 port,
Greg Clayton00fe87b2013-12-05 22:58:22 +0000854 debugserver_launch_info,
855 port);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000856
857 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000858
Greg Claytonfbb76342013-11-20 21:07:01 +0000859
Greg Clayton29b8fc42013-11-21 01:44:58 +0000860 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
861 {
862 Mutex::Locker locker (m_spawned_pids_mutex);
863 m_spawned_pids.insert(debugserver_pid);
864 if (port > 0)
865 AssociatePortWithProcess(port, debugserver_pid);
866 }
867 else
868 {
869 if (port > 0)
870 FreePort (port);
871 }
872
873 if (error.Success())
874 {
Greg Clayton91a9b2472013-12-04 19:19:12 +0000875 char response[256];
876 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
877 assert (response_len < sizeof(response));
Greg Clayton3dedae12013-12-06 21:45:27 +0000878 PacketResult packet_result = SendPacketNoLock (response, response_len);
Greg Clayton29b8fc42013-11-21 01:44:58 +0000879
Greg Clayton3dedae12013-12-06 21:45:27 +0000880 if (packet_result != PacketResult::Success)
Greg Clayton29b8fc42013-11-21 01:44:58 +0000881 {
882 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
883 ::kill (debugserver_pid, SIGINT);
884 }
Greg Clayton3dedae12013-12-06 21:45:27 +0000885 return packet_result;
Greg Clayton29b8fc42013-11-21 01:44:58 +0000886 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000887 }
888 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000889 return SendErrorResponse (9);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000890#endif
Greg Clayton8b82f082011-04-12 05:54:46 +0000891}
892
Greg Clayton3dedae12013-12-06 21:45:27 +0000893GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +0000894GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
895{
896 // Spawn a local debugserver as a platform so we can then attach or launch
897 // a process...
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000898
Daniel Maleae0f8f572013-08-26 23:57:52 +0000899 if (m_is_platform)
900 {
901 packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000902
Daniel Maleae0f8f572013-08-26 23:57:52 +0000903 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
904
905 // Scope for locker
906 {
907 Mutex::Locker locker (m_spawned_pids_mutex);
908 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
909 return SendErrorResponse (10);
910 }
Virgile Belloae12a362013-08-27 16:21:49 +0000911 Host::Kill (pid, SIGTERM);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000912
Daniel Maleae0f8f572013-08-26 23:57:52 +0000913 for (size_t i=0; i<10; ++i)
914 {
915 // Scope for locker
916 {
917 Mutex::Locker locker (m_spawned_pids_mutex);
918 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000919 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000920 }
921 usleep (10000);
922 }
923
924 // Scope for locker
925 {
926 Mutex::Locker locker (m_spawned_pids_mutex);
927 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000928 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000929 }
Virgile Belloae12a362013-08-27 16:21:49 +0000930 Host::Kill (pid, SIGKILL);
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000931
Daniel Maleae0f8f572013-08-26 23:57:52 +0000932 for (size_t i=0; i<10; ++i)
933 {
934 // Scope for locker
935 {
936 Mutex::Locker locker (m_spawned_pids_mutex);
937 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
Greg Clayton2b98c562013-11-22 18:53:12 +0000938 return SendOKResponse();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000939 }
940 usleep (10000);
941 }
942 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000943 return SendErrorResponse (11);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000944}
945
Greg Clayton3dedae12013-12-06 21:45:27 +0000946GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000947GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
948{
949 if (m_process_launch_error.Success())
950 return SendOKResponse();
Sylvestre Ledrub027bd22013-09-28 14:35:00 +0000951 StreamString response;
Greg Clayton8b82f082011-04-12 05:54:46 +0000952 response.PutChar('E');
953 response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
Greg Clayton37a0a242012-04-11 00:24:49 +0000954 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton8b82f082011-04-12 05:54:46 +0000955}
956
Greg Clayton3dedae12013-12-06 21:45:27 +0000957GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000958GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
959{
960 packet.SetFilePos(::strlen ("QEnvironment:"));
961 const uint32_t bytes_left = packet.GetBytesLeft();
962 if (bytes_left > 0)
963 {
964 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
965 return SendOKResponse ();
966 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000967 return SendErrorResponse (12);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000968}
969
Greg Clayton3dedae12013-12-06 21:45:27 +0000970GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +0000971GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
972{
973 packet.SetFilePos(::strlen ("QLaunchArch:"));
974 const uint32_t bytes_left = packet.GetBytesLeft();
975 if (bytes_left > 0)
976 {
977 const char* arch_triple = packet.Peek();
978 ArchSpec arch_spec(arch_triple,NULL);
979 m_process_launch_info.SetArchitecture(arch_spec);
980 return SendOKResponse();
981 }
Greg Clayton2b98c562013-11-22 18:53:12 +0000982 return SendErrorResponse(13);
Greg Clayton8b82f082011-04-12 05:54:46 +0000983}
984
Greg Clayton3dedae12013-12-06 21:45:27 +0000985GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000986GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
987{
988 packet.SetFilePos(::strlen ("QSetDisableASLR:"));
989 if (packet.GetU32(0))
990 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
991 else
992 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
993 return SendOKResponse ();
994}
995
Greg Clayton3dedae12013-12-06 21:45:27 +0000996GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +0000997GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
998{
999 packet.SetFilePos(::strlen ("QSetWorkingDir:"));
1000 std::string path;
1001 packet.GetHexByteString(path);
Greg Claytonfbb76342013-11-20 21:07:01 +00001002 if (m_is_platform)
1003 {
Colin Riley909bb7a2013-11-26 15:10:46 +00001004#ifdef _WIN32
1005 // Not implemented on Windows
1006 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_QSetWorkingDir unimplemented");
1007#else
Greg Claytonfbb76342013-11-20 21:07:01 +00001008 // If this packet is sent to a platform, then change the current working directory
1009 if (::chdir(path.c_str()) != 0)
1010 return SendErrorResponse(errno);
Colin Riley909bb7a2013-11-26 15:10:46 +00001011#endif
Greg Claytonfbb76342013-11-20 21:07:01 +00001012 }
1013 else
1014 {
1015 m_process_launch_info.SwapWorkingDirectory (path);
1016 }
Greg Clayton8b82f082011-04-12 05:54:46 +00001017 return SendOKResponse ();
1018}
1019
Greg Clayton3dedae12013-12-06 21:45:27 +00001020GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001021GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
1022{
1023 StreamString response;
1024
1025 if (m_is_platform)
1026 {
1027 // If this packet is sent to a platform, then change the current working directory
1028 char cwd[PATH_MAX];
1029 if (getcwd(cwd, sizeof(cwd)) == NULL)
1030 {
1031 return SendErrorResponse(errno);
1032 }
1033 else
1034 {
1035 response.PutBytesAsRawHex8(cwd, strlen(cwd));
Greg Clayton3dedae12013-12-06 21:45:27 +00001036 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001037 }
1038 }
1039 else
1040 {
1041 const char *working_dir = m_process_launch_info.GetWorkingDirectory();
1042 if (working_dir && working_dir[0])
1043 {
1044 response.PutBytesAsRawHex8(working_dir, strlen(working_dir));
Greg Clayton3dedae12013-12-06 21:45:27 +00001045 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001046 }
1047 else
1048 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001049 return SendErrorResponse(14);
Greg Claytonfbb76342013-11-20 21:07:01 +00001050 }
1051 }
1052}
1053
Greg Clayton3dedae12013-12-06 21:45:27 +00001054GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001055GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
1056{
1057 packet.SetFilePos(::strlen ("QSetSTDIN:"));
1058 ProcessLaunchInfo::FileAction file_action;
1059 std::string path;
1060 packet.GetHexByteString(path);
1061 const bool read = false;
1062 const bool write = true;
1063 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
1064 {
1065 m_process_launch_info.AppendFileAction(file_action);
1066 return SendOKResponse ();
1067 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001068 return SendErrorResponse (15);
Greg Clayton8b82f082011-04-12 05:54:46 +00001069}
1070
Greg Clayton3dedae12013-12-06 21:45:27 +00001071GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001072GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
1073{
1074 packet.SetFilePos(::strlen ("QSetSTDOUT:"));
1075 ProcessLaunchInfo::FileAction file_action;
1076 std::string path;
1077 packet.GetHexByteString(path);
1078 const bool read = true;
1079 const bool write = false;
1080 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
1081 {
1082 m_process_launch_info.AppendFileAction(file_action);
1083 return SendOKResponse ();
1084 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001085 return SendErrorResponse (16);
Greg Clayton8b82f082011-04-12 05:54:46 +00001086}
1087
Greg Clayton3dedae12013-12-06 21:45:27 +00001088GDBRemoteCommunication::PacketResult
Greg Clayton8b82f082011-04-12 05:54:46 +00001089GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
1090{
1091 packet.SetFilePos(::strlen ("QSetSTDERR:"));
1092 ProcessLaunchInfo::FileAction file_action;
1093 std::string path;
1094 packet.GetHexByteString(path);
1095 const bool read = true;
Greg Clayton9845a8d2012-03-06 04:01:04 +00001096 const bool write = false;
Greg Clayton8b82f082011-04-12 05:54:46 +00001097 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
1098 {
1099 m_process_launch_info.AppendFileAction(file_action);
1100 return SendOKResponse ();
1101 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001102 return SendErrorResponse (17);
Greg Clayton8b82f082011-04-12 05:54:46 +00001103}
1104
Greg Clayton3dedae12013-12-06 21:45:27 +00001105GDBRemoteCommunication::PacketResult
Greg Clayton32e0a752011-03-30 18:16:51 +00001106GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
1107{
1108 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton3dedae12013-12-06 21:45:27 +00001109 PacketResult packet_result = SendOKResponse ();
Greg Clayton1cb64962011-03-24 04:28:38 +00001110 m_send_acks = false;
Greg Clayton3dedae12013-12-06 21:45:27 +00001111 return packet_result;
Greg Clayton1cb64962011-03-24 04:28:38 +00001112}
Daniel Maleae0f8f572013-08-26 23:57:52 +00001113
Greg Clayton3dedae12013-12-06 21:45:27 +00001114GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001115GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
Daniel Maleae0f8f572013-08-26 23:57:52 +00001116{
Greg Claytonfbb76342013-11-20 21:07:01 +00001117 packet.SetFilePos(::strlen("qPlatform_mkdir:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001118 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001119 if (packet.GetChar() == ',')
1120 {
1121 std::string path;
1122 packet.GetHexByteString(path);
1123 Error error = Host::MakeDirectory(path.c_str(),mode);
1124 if (error.Success())
1125 return SendPacketNoLock ("OK", 2);
1126 else
1127 return SendErrorResponse(error.GetError());
1128 }
1129 return SendErrorResponse(20);
Greg Claytonfbb76342013-11-20 21:07:01 +00001130}
1131
Greg Clayton3dedae12013-12-06 21:45:27 +00001132GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001133GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
1134{
1135 packet.SetFilePos(::strlen("qPlatform_chmod:"));
1136
1137 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001138 if (packet.GetChar() == ',')
1139 {
1140 std::string path;
1141 packet.GetHexByteString(path);
1142 Error error = Host::SetFilePermissions (path.c_str(), mode);
1143 if (error.Success())
1144 return SendPacketNoLock ("OK", 2);
1145 else
1146 return SendErrorResponse(error.GetError());
1147 }
1148 return SendErrorResponse(19);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001149}
1150
Greg Clayton3dedae12013-12-06 21:45:27 +00001151GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001152GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
1153{
1154 packet.SetFilePos(::strlen("vFile:open:"));
1155 std::string path;
1156 packet.GetHexByteStringTerminatedBy(path,',');
Greg Clayton2b98c562013-11-22 18:53:12 +00001157 if (!path.empty())
1158 {
1159 if (packet.GetChar() == ',')
1160 {
1161 uint32_t flags = packet.GetHexMaxU32(false, 0);
1162 if (packet.GetChar() == ',')
1163 {
1164 mode_t mode = packet.GetHexMaxU32(false, 0600);
1165 Error error;
1166 int fd = ::open (path.c_str(), flags, mode);
Greg Clayton2b98c562013-11-22 18:53:12 +00001167 const int save_errno = fd == -1 ? errno : 0;
1168 StreamString response;
1169 response.PutChar('F');
1170 response.Printf("%i", fd);
1171 if (save_errno)
1172 response.Printf(",%i", save_errno);
1173 return SendPacketNoLock(response.GetData(), response.GetSize());
1174 }
1175 }
1176 }
1177 return SendErrorResponse(18);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001178}
1179
Greg Clayton3dedae12013-12-06 21:45:27 +00001180GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001181GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
1182{
1183 packet.SetFilePos(::strlen("vFile:close:"));
1184 int fd = packet.GetS32(-1);
1185 Error error;
1186 int err = -1;
1187 int save_errno = 0;
1188 if (fd >= 0)
1189 {
1190 err = close(fd);
1191 save_errno = err == -1 ? errno : 0;
1192 }
1193 else
1194 {
1195 save_errno = EINVAL;
1196 }
1197 StreamString response;
1198 response.PutChar('F');
1199 response.Printf("%i", err);
1200 if (save_errno)
1201 response.Printf(",%i", save_errno);
Greg Clayton2b98c562013-11-22 18:53:12 +00001202 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001203}
1204
Greg Clayton3dedae12013-12-06 21:45:27 +00001205GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001206GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
1207{
Virgile Belloae12a362013-08-27 16:21:49 +00001208#ifdef _WIN32
1209 // Not implemented on Windows
Greg Clayton2b98c562013-11-22 18:53:12 +00001210 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pRead() unimplemented");
Virgile Belloae12a362013-08-27 16:21:49 +00001211#else
Daniel Maleae0f8f572013-08-26 23:57:52 +00001212 StreamGDBRemote response;
1213 packet.SetFilePos(::strlen("vFile:pread:"));
1214 int fd = packet.GetS32(-1);
Greg Clayton2b98c562013-11-22 18:53:12 +00001215 if (packet.GetChar() == ',')
Daniel Maleae0f8f572013-08-26 23:57:52 +00001216 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001217 uint64_t count = packet.GetU64(UINT64_MAX);
1218 if (packet.GetChar() == ',')
1219 {
1220 uint64_t offset = packet.GetU64(UINT32_MAX);
1221 if (count == UINT64_MAX)
1222 {
1223 response.Printf("F-1:%i", EINVAL);
1224 return SendPacketNoLock(response.GetData(), response.GetSize());
1225 }
1226
1227 std::string buffer(count, 0);
1228 const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
1229 const int save_errno = bytes_read == -1 ? errno : 0;
1230 response.PutChar('F');
1231 response.Printf("%zi", bytes_read);
1232 if (save_errno)
1233 response.Printf(",%i", save_errno);
1234 else
1235 {
1236 response.PutChar(';');
1237 response.PutEscapedBytes(&buffer[0], bytes_read);
1238 }
1239 return SendPacketNoLock(response.GetData(), response.GetSize());
1240 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001241 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001242 return SendErrorResponse(21);
1243
Virgile Belloae12a362013-08-27 16:21:49 +00001244#endif
Daniel Maleae0f8f572013-08-26 23:57:52 +00001245}
1246
Greg Clayton3dedae12013-12-06 21:45:27 +00001247GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001248GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
1249{
Virgile Belloae12a362013-08-27 16:21:49 +00001250#ifdef _WIN32
Greg Clayton2b98c562013-11-22 18:53:12 +00001251 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pWrite() unimplemented");
Virgile Belloae12a362013-08-27 16:21:49 +00001252#else
Daniel Maleae0f8f572013-08-26 23:57:52 +00001253 packet.SetFilePos(::strlen("vFile:pwrite:"));
1254
1255 StreamGDBRemote response;
1256 response.PutChar('F');
1257
1258 int fd = packet.GetU32(UINT32_MAX);
Greg Clayton2b98c562013-11-22 18:53:12 +00001259 if (packet.GetChar() == ',')
Daniel Maleae0f8f572013-08-26 23:57:52 +00001260 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001261 off_t offset = packet.GetU64(UINT32_MAX);
1262 if (packet.GetChar() == ',')
1263 {
1264 std::string buffer;
1265 if (packet.GetEscapedBinaryData(buffer))
1266 {
1267 const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
1268 const int save_errno = bytes_written == -1 ? errno : 0;
1269 response.Printf("%zi", bytes_written);
1270 if (save_errno)
1271 response.Printf(",%i", save_errno);
1272 }
1273 else
1274 {
1275 response.Printf ("-1,%i", EINVAL);
1276 }
1277 return SendPacketNoLock(response.GetData(), response.GetSize());
1278 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001279 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001280 return SendErrorResponse(27);
Virgile Belloae12a362013-08-27 16:21:49 +00001281#endif
Daniel Maleae0f8f572013-08-26 23:57:52 +00001282}
1283
Greg Clayton3dedae12013-12-06 21:45:27 +00001284GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001285GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
1286{
1287 packet.SetFilePos(::strlen("vFile:size:"));
1288 std::string path;
1289 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001290 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001291 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001292 lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
1293 StreamString response;
1294 response.PutChar('F');
1295 response.PutHex64(retcode);
1296 if (retcode == UINT64_MAX)
1297 {
1298 response.PutChar(',');
1299 response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
1300 }
1301 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001302 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001303 return SendErrorResponse(22);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001304}
1305
Greg Clayton3dedae12013-12-06 21:45:27 +00001306GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001307GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
1308{
1309 packet.SetFilePos(::strlen("vFile:mode:"));
1310 std::string path;
1311 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001312 if (!path.empty())
1313 {
1314 Error error;
1315 const uint32_t mode = File::GetPermissions(path.c_str(), error);
1316 StreamString response;
1317 response.Printf("F%u", mode);
1318 if (mode == 0 || error.Fail())
1319 response.Printf(",%i", (int)error.GetError());
1320 return SendPacketNoLock(response.GetData(), response.GetSize());
1321 }
1322 return SendErrorResponse(23);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001323}
1324
Greg Clayton3dedae12013-12-06 21:45:27 +00001325GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001326GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
1327{
1328 packet.SetFilePos(::strlen("vFile:exists:"));
1329 std::string path;
1330 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001331 if (!path.empty())
1332 {
1333 bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
1334 StreamString response;
1335 response.PutChar('F');
1336 response.PutChar(',');
1337 if (retcode)
1338 response.PutChar('1');
1339 else
1340 response.PutChar('0');
1341 return SendPacketNoLock(response.GetData(), response.GetSize());
1342 }
1343 return SendErrorResponse(24);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001344}
1345
Greg Clayton3dedae12013-12-06 21:45:27 +00001346GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001347GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
Daniel Maleae0f8f572013-08-26 23:57:52 +00001348{
Greg Claytonfbb76342013-11-20 21:07:01 +00001349 packet.SetFilePos(::strlen("vFile:symlink:"));
1350 std::string dst, src;
1351 packet.GetHexByteStringTerminatedBy(dst, ',');
1352 packet.GetChar(); // Skip ',' char
1353 packet.GetHexByteString(src);
1354 Error error = Host::Symlink(src.c_str(), dst.c_str());
1355 StreamString response;
1356 response.Printf("F%u,%u", error.GetError(), error.GetError());
Greg Clayton2b98c562013-11-22 18:53:12 +00001357 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001358}
1359
Greg Clayton3dedae12013-12-06 21:45:27 +00001360GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001361GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
1362{
1363 packet.SetFilePos(::strlen("vFile:unlink:"));
1364 std::string path;
1365 packet.GetHexByteString(path);
1366 Error error = Host::Unlink(path.c_str());
1367 StreamString response;
1368 response.Printf("F%u,%u", error.GetError(), error.GetError());
Greg Clayton2b98c562013-11-22 18:53:12 +00001369 return SendPacketNoLock(response.GetData(), response.GetSize());
Greg Claytonfbb76342013-11-20 21:07:01 +00001370}
1371
Greg Clayton3dedae12013-12-06 21:45:27 +00001372GDBRemoteCommunication::PacketResult
Greg Claytonfbb76342013-11-20 21:07:01 +00001373GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
1374{
1375 packet.SetFilePos(::strlen("qPlatform_shell:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001376 std::string path;
1377 std::string working_dir;
1378 packet.GetHexByteStringTerminatedBy(path,',');
Greg Clayton2b98c562013-11-22 18:53:12 +00001379 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001380 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001381 if (packet.GetChar() == ',')
1382 {
1383 // FIXME: add timeout to qPlatform_shell packet
1384 // uint32_t timeout = packet.GetHexMaxU32(false, 32);
1385 uint32_t timeout = 10;
1386 if (packet.GetChar() == ',')
1387 packet.GetHexByteString(working_dir);
1388 int status, signo;
1389 std::string output;
1390 Error err = Host::RunShellCommand(path.c_str(),
1391 working_dir.empty() ? NULL : working_dir.c_str(),
1392 &status, &signo, &output, timeout);
1393 StreamGDBRemote response;
1394 if (err.Fail())
1395 {
1396 response.PutCString("F,");
1397 response.PutHex32(UINT32_MAX);
1398 }
1399 else
1400 {
1401 response.PutCString("F,");
1402 response.PutHex32(status);
1403 response.PutChar(',');
1404 response.PutHex32(signo);
1405 response.PutChar(',');
1406 response.PutEscapedBytes(output.c_str(), output.size());
1407 }
1408 return SendPacketNoLock(response.GetData(), response.GetSize());
1409 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001410 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001411 return SendErrorResponse(24);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001412}
1413
Greg Clayton3dedae12013-12-06 21:45:27 +00001414GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001415GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
1416{
Greg Clayton2b98c562013-11-22 18:53:12 +00001417 return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented");
Daniel Maleae0f8f572013-08-26 23:57:52 +00001418}
1419
Greg Clayton3dedae12013-12-06 21:45:27 +00001420GDBRemoteCommunication::PacketResult
Daniel Maleae0f8f572013-08-26 23:57:52 +00001421GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
1422{
Greg Clayton2b98c562013-11-22 18:53:12 +00001423 packet.SetFilePos(::strlen("vFile:MD5:"));
Daniel Maleae0f8f572013-08-26 23:57:52 +00001424 std::string path;
1425 packet.GetHexByteString(path);
Greg Clayton2b98c562013-11-22 18:53:12 +00001426 if (!path.empty())
Daniel Maleae0f8f572013-08-26 23:57:52 +00001427 {
Greg Clayton2b98c562013-11-22 18:53:12 +00001428 uint64_t a,b;
1429 StreamGDBRemote response;
1430 if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
1431 {
1432 response.PutCString("F,");
1433 response.PutCString("x");
1434 }
1435 else
1436 {
1437 response.PutCString("F,");
1438 response.PutHex64(a);
1439 response.PutHex64(b);
1440 }
1441 return SendPacketNoLock(response.GetData(), response.GetSize());
Daniel Maleae0f8f572013-08-26 23:57:52 +00001442 }
Greg Clayton2b98c562013-11-22 18:53:12 +00001443 return SendErrorResponse(25);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001444}
Greg Clayton2b98c562013-11-22 18:53:12 +00001445