blob: 5c69b89e83ef1039a1ec5c8f2fdc4c2e90c15315 [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
10
11#include "GDBRemoteCommunicationServer.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000012#include "lldb/Core/StreamGDBRemote.h"
Greg Clayton576d8832011-03-22 04:00:09 +000013
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17#include "llvm/ADT/Triple.h"
18#include "lldb/Interpreter/Args.h"
19#include "lldb/Core/ConnectionFileDescriptor.h"
20#include "lldb/Core/Log.h"
21#include "lldb/Core/State.h"
22#include "lldb/Core/StreamString.h"
Enrico Granataf2bbf712011-07-15 02:26:42 +000023#include "lldb/Host/Endian.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000024#include "lldb/Host/File.h"
Greg Clayton576d8832011-03-22 04:00:09 +000025#include "lldb/Host/Host.h"
26#include "lldb/Host/TimeValue.h"
Greg Clayton8b82f082011-04-12 05:54:46 +000027#include "lldb/Target/Process.h"
Greg Clayton576d8832011-03-22 04:00:09 +000028
29// Project includes
30#include "Utility/StringExtractorGDBRemote.h"
31#include "ProcessGDBRemote.h"
32#include "ProcessGDBRemoteLog.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
37//----------------------------------------------------------------------
38// GDBRemoteCommunicationServer constructor
39//----------------------------------------------------------------------
Greg Clayton8b82f082011-04-12 05:54:46 +000040GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
41 GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
42 m_async_thread (LLDB_INVALID_HOST_THREAD),
43 m_process_launch_info (),
44 m_process_launch_error (),
Daniel Maleae0f8f572013-08-26 23:57:52 +000045 m_spawned_pids (),
46 m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
Greg Clayton8b82f082011-04-12 05:54:46 +000047 m_proc_infos (),
48 m_proc_infos_index (0),
49 m_lo_port_num (0),
Daniel Maleae0f8f572013-08-26 23:57:52 +000050 m_hi_port_num (0),
51 m_next_port (0),
52 m_use_port_range (false)
Greg Clayton576d8832011-03-22 04:00:09 +000053{
Daniel Maleae0f8f572013-08-26 23:57:52 +000054 // We seldom need to override the port number that the debugserver process
55 // starts with. We just pass in 0 to let the system choose a random port.
56 // In rare situation where the need arises, use two environment variables
57 // to override.
58 uint16_t lo_port_num = 0;
59 uint16_t hi_port_num = 0;
60 const char *lo_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_LO_PORT");
61 if (lo_port_c_str)
62 lo_port_num = ::atoi(lo_port_c_str);
63 const char *hi_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_HI_PORT");
64 if (hi_port_c_str)
65 hi_port_num = ::atoi(hi_port_c_str);
66 if (lo_port_num && hi_port_num && lo_port_num < hi_port_num)
67 {
68 SetPortRange(lo_port_num, hi_port_num);
69 }
Greg Clayton576d8832011-03-22 04:00:09 +000070}
71
72//----------------------------------------------------------------------
73// Destructor
74//----------------------------------------------------------------------
75GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
76{
77}
78
79
80//void *
81//GDBRemoteCommunicationServer::AsyncThread (void *arg)
82//{
83// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
84//
Greg Clayton5160ce52013-03-27 23:08:40 +000085// Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Greg Clayton576d8832011-03-22 04:00:09 +000086// if (log)
87// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
88//
89// StringExtractorGDBRemote packet;
90//
91// while ()
92// {
93// if (packet.
94// }
95//
96// if (log)
97// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
98//
99// process->m_async_thread = LLDB_INVALID_HOST_THREAD;
100// return NULL;
101//}
102//
103bool
Greg Clayton73bf5db2011-06-17 01:22:15 +0000104GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
Greg Clayton1cb64962011-03-24 04:28:38 +0000105 Error &error,
Greg Claytond314e812011-03-23 00:09:55 +0000106 bool &interrupt,
107 bool &quit)
Greg Clayton576d8832011-03-22 04:00:09 +0000108{
109 StringExtractorGDBRemote packet;
Greg Clayton37a0a242012-04-11 00:24:49 +0000110 if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec))
Greg Clayton576d8832011-03-22 04:00:09 +0000111 {
112 const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
113 switch (packet_type)
114 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000115 case StringExtractorGDBRemote::eServerPacketType_nack:
116 case StringExtractorGDBRemote::eServerPacketType_ack:
117 break;
Greg Clayton576d8832011-03-22 04:00:09 +0000118
Greg Clayton8b82f082011-04-12 05:54:46 +0000119 case StringExtractorGDBRemote::eServerPacketType_invalid:
120 error.SetErrorString("invalid packet");
121 quit = true;
122 break;
Greg Claytond314e812011-03-23 00:09:55 +0000123
Greg Clayton8b82f082011-04-12 05:54:46 +0000124 case StringExtractorGDBRemote::eServerPacketType_interrupt:
125 error.SetErrorString("interrupt received");
126 interrupt = true;
127 break;
128
129 case StringExtractorGDBRemote::eServerPacketType_unimplemented:
130 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
Greg Clayton576d8832011-03-22 04:00:09 +0000131
Greg Clayton8b82f082011-04-12 05:54:46 +0000132 case StringExtractorGDBRemote::eServerPacketType_A:
133 return Handle_A (packet);
Greg Clayton32e0a752011-03-30 18:16:51 +0000134
Greg Clayton8b82f082011-04-12 05:54:46 +0000135 case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
136 return Handle_qfProcessInfo (packet);
137
138 case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
139 return Handle_qsProcessInfo (packet);
140
141 case StringExtractorGDBRemote::eServerPacketType_qC:
142 return Handle_qC (packet);
143
144 case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
145 return Handle_qHostInfo (packet);
146
147 case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
148 return Handle_qLaunchGDBServer (packet);
149
Daniel Maleae0f8f572013-08-26 23:57:52 +0000150 case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
151 return Handle_qKillSpawnedProcess (packet);
152
Greg Clayton8b82f082011-04-12 05:54:46 +0000153 case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
154 return Handle_qLaunchSuccess (packet);
155
156 case StringExtractorGDBRemote::eServerPacketType_qGroupName:
157 return Handle_qGroupName (packet);
Greg Clayton32e0a752011-03-30 18:16:51 +0000158
Greg Clayton8b82f082011-04-12 05:54:46 +0000159 case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
160 return Handle_qProcessInfoPID (packet);
Greg Clayton32e0a752011-03-30 18:16:51 +0000161
Greg Clayton8b82f082011-04-12 05:54:46 +0000162 case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
163 return Handle_qSpeedTest (packet);
Greg Clayton32e0a752011-03-30 18:16:51 +0000164
Greg Clayton8b82f082011-04-12 05:54:46 +0000165 case StringExtractorGDBRemote::eServerPacketType_qUserName:
166 return Handle_qUserName (packet);
Greg Clayton32e0a752011-03-30 18:16:51 +0000167
Greg Clayton8b82f082011-04-12 05:54:46 +0000168 case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
169 return Handle_QEnvironment (packet);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000170
171 case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
172 return Handle_QLaunchArch (packet);
Greg Clayton8b82f082011-04-12 05:54:46 +0000173
174 case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
175 return Handle_QSetDisableASLR (packet);
176
177 case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
178 return Handle_QSetSTDIN (packet);
179
180 case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
181 return Handle_QSetSTDOUT (packet);
182
183 case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
184 return Handle_QSetSTDERR (packet);
185
186 case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
187 return Handle_QSetWorkingDir (packet);
188
189 case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
190 return Handle_QStartNoAckMode (packet);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000191
192 case StringExtractorGDBRemote::eServerPacketType_qPlatform_IO_MkDir:
193 return Handle_qPlatform_IO_MkDir (packet);
194
195 case StringExtractorGDBRemote::eServerPacketType_qPlatform_RunCommand:
196 return Handle_qPlatform_RunCommand (packet);
197
198 case StringExtractorGDBRemote::eServerPacketType_vFile_Open:
199 return Handle_vFile_Open (packet);
200
201 case StringExtractorGDBRemote::eServerPacketType_vFile_Close:
202 return Handle_vFile_Close (packet);
203
204 case StringExtractorGDBRemote::eServerPacketType_vFile_pRead:
205 return Handle_vFile_pRead (packet);
206
207 case StringExtractorGDBRemote::eServerPacketType_vFile_pWrite:
208 return Handle_vFile_pWrite (packet);
209
210 case StringExtractorGDBRemote::eServerPacketType_vFile_Size:
211 return Handle_vFile_Size (packet);
212
213 case StringExtractorGDBRemote::eServerPacketType_vFile_Mode:
214 return Handle_vFile_Mode (packet);
215
216 case StringExtractorGDBRemote::eServerPacketType_vFile_Exists:
217 return Handle_vFile_Exists (packet);
218
219 case StringExtractorGDBRemote::eServerPacketType_vFile_Stat:
220 return Handle_vFile_Stat (packet);
221
222 case StringExtractorGDBRemote::eServerPacketType_vFile_MD5:
223 return Handle_vFile_MD5 (packet);
Greg Clayton576d8832011-03-22 04:00:09 +0000224 }
225 return true;
226 }
Greg Clayton1cb64962011-03-24 04:28:38 +0000227 else
228 {
229 if (!IsConnected())
230 error.SetErrorString("lost connection");
231 else
232 error.SetErrorString("timeout");
233 }
234
Greg Clayton576d8832011-03-22 04:00:09 +0000235 return false;
236}
237
238size_t
Greg Clayton32e0a752011-03-30 18:16:51 +0000239GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
Greg Clayton576d8832011-03-22 04:00:09 +0000240{
Greg Clayton32e0a752011-03-30 18:16:51 +0000241 // TODO: Log the packet we aren't handling...
Greg Clayton37a0a242012-04-11 00:24:49 +0000242 return SendPacketNoLock ("", 0);
Greg Clayton576d8832011-03-22 04:00:09 +0000243}
244
Greg Clayton1cb64962011-03-24 04:28:38 +0000245size_t
Greg Clayton32e0a752011-03-30 18:16:51 +0000246GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
247{
248 char packet[16];
249 int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
Andy Gibbsa297a972013-06-19 19:04:53 +0000250 assert (packet_len < (int)sizeof(packet));
Greg Clayton37a0a242012-04-11 00:24:49 +0000251 return SendPacketNoLock (packet, packet_len);
Greg Clayton32e0a752011-03-30 18:16:51 +0000252}
253
254
255size_t
Greg Clayton1cb64962011-03-24 04:28:38 +0000256GDBRemoteCommunicationServer::SendOKResponse ()
257{
Greg Clayton37a0a242012-04-11 00:24:49 +0000258 return SendPacketNoLock ("OK", 2);
Greg Clayton1cb64962011-03-24 04:28:38 +0000259}
260
261bool
262GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
263{
Greg Clayton73bf5db2011-06-17 01:22:15 +0000264 return GetAck();
Greg Clayton1cb64962011-03-24 04:28:38 +0000265}
Greg Clayton576d8832011-03-22 04:00:09 +0000266
267bool
Greg Clayton32e0a752011-03-30 18:16:51 +0000268GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
Greg Clayton576d8832011-03-22 04:00:09 +0000269{
270 StreamString response;
271
272 // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
273
274 ArchSpec host_arch (Host::GetArchitecture ());
Greg Clayton576d8832011-03-22 04:00:09 +0000275 const llvm::Triple &host_triple = host_arch.GetTriple();
Greg Clayton1cb64962011-03-24 04:28:38 +0000276 response.PutCString("triple:");
277 response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
278 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
Greg Clayton576d8832011-03-22 04:00:09 +0000279
Greg Clayton1cb64962011-03-24 04:28:38 +0000280 uint32_t cpu = host_arch.GetMachOCPUType();
281 uint32_t sub = host_arch.GetMachOCPUSubType();
282 if (cpu != LLDB_INVALID_CPUTYPE)
283 response.Printf ("cputype:%u;", cpu);
284 if (sub != LLDB_INVALID_CPUTYPE)
285 response.Printf ("cpusubtype:%u;", sub);
286
Enrico Granata1c5431a2012-07-13 23:55:22 +0000287 if (cpu == ArchSpec::kCore_arm_any)
Enrico Granataf04a2192012-07-13 23:18:48 +0000288 response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
289 else
290 response.Printf("watchpoint_exceptions_received:after;");
291
Greg Clayton576d8832011-03-22 04:00:09 +0000292 switch (lldb::endian::InlHostByteOrder())
293 {
294 case eByteOrderBig: response.PutCString ("endian:big;"); break;
295 case eByteOrderLittle: response.PutCString ("endian:little;"); break;
296 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
297 default: response.PutCString ("endian:unknown;"); break;
298 }
299
Greg Clayton1cb64962011-03-24 04:28:38 +0000300 uint32_t major = UINT32_MAX;
301 uint32_t minor = UINT32_MAX;
302 uint32_t update = UINT32_MAX;
303 if (Host::GetOSVersion (major, minor, update))
304 {
305 if (major != UINT32_MAX)
306 {
307 response.Printf("os_version:%u", major);
308 if (minor != UINT32_MAX)
309 {
310 response.Printf(".%u", minor);
311 if (update != UINT32_MAX)
312 response.Printf(".%u", update);
313 }
314 response.PutChar(';');
315 }
316 }
317
318 std::string s;
319 if (Host::GetOSBuildString (s))
320 {
321 response.PutCString ("os_build:");
322 response.PutCStringAsRawHex8(s.c_str());
323 response.PutChar(';');
324 }
325 if (Host::GetOSKernelDescription (s))
326 {
327 response.PutCString ("os_kernel:");
328 response.PutCStringAsRawHex8(s.c_str());
329 response.PutChar(';');
330 }
331 if (Host::GetHostname (s))
332 {
333 response.PutCString ("hostname:");
334 response.PutCStringAsRawHex8(s.c_str());
335 response.PutChar(';');
336 }
337
Greg Clayton37a0a242012-04-11 00:24:49 +0000338 return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
Greg Clayton576d8832011-03-22 04:00:09 +0000339}
Greg Clayton1cb64962011-03-24 04:28:38 +0000340
Greg Clayton32e0a752011-03-30 18:16:51 +0000341static void
Greg Clayton8b82f082011-04-12 05:54:46 +0000342CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
Greg Clayton32e0a752011-03-30 18:16:51 +0000343{
Daniel Malead01b2952012-11-29 21:49:15 +0000344 response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
Greg Clayton32e0a752011-03-30 18:16:51 +0000345 proc_info.GetProcessID(),
346 proc_info.GetParentProcessID(),
Greg Clayton8b82f082011-04-12 05:54:46 +0000347 proc_info.GetUserID(),
348 proc_info.GetGroupID(),
Greg Clayton32e0a752011-03-30 18:16:51 +0000349 proc_info.GetEffectiveUserID(),
350 proc_info.GetEffectiveGroupID());
351 response.PutCString ("name:");
352 response.PutCStringAsRawHex8(proc_info.GetName());
353 response.PutChar(';');
354 const ArchSpec &proc_arch = proc_info.GetArchitecture();
355 if (proc_arch.IsValid())
356 {
357 const llvm::Triple &proc_triple = proc_arch.GetTriple();
358 response.PutCString("triple:");
359 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
360 response.PutChar(';');
361 }
362}
Greg Clayton1cb64962011-03-24 04:28:38 +0000363
364bool
Greg Clayton32e0a752011-03-30 18:16:51 +0000365GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
Greg Clayton1cb64962011-03-24 04:28:38 +0000366{
Greg Clayton32e0a752011-03-30 18:16:51 +0000367 // Packet format: "qProcessInfoPID:%i" where %i is the pid
Greg Clayton8b82f082011-04-12 05:54:46 +0000368 packet.SetFilePos(::strlen ("qProcessInfoPID:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000369 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
370 if (pid != LLDB_INVALID_PROCESS_ID)
371 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000372 ProcessInstanceInfo proc_info;
Greg Clayton32e0a752011-03-30 18:16:51 +0000373 if (Host::GetProcessInfo(pid, proc_info))
374 {
375 StreamString response;
376 CreateProcessInfoResponse (proc_info, response);
Greg Clayton37a0a242012-04-11 00:24:49 +0000377 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000378 }
379 }
380 return SendErrorResponse (1);
381}
382
383bool
384GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
385{
386 m_proc_infos_index = 0;
387 m_proc_infos.Clear();
388
Greg Clayton8b82f082011-04-12 05:54:46 +0000389 ProcessInstanceInfoMatch match_info;
390 packet.SetFilePos(::strlen ("qfProcessInfo"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000391 if (packet.GetChar() == ':')
392 {
393
394 std::string key;
395 std::string value;
396 while (packet.GetNameColonValue(key, value))
397 {
398 bool success = true;
399 if (key.compare("name") == 0)
400 {
401 StringExtractor extractor;
402 extractor.GetStringRef().swap(value);
403 extractor.GetHexByteString (value);
Greg Clayton144f3a92011-11-15 03:53:30 +0000404 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
Greg Clayton32e0a752011-03-30 18:16:51 +0000405 }
406 else if (key.compare("name_match") == 0)
407 {
408 if (value.compare("equals") == 0)
409 {
410 match_info.SetNameMatchType (eNameMatchEquals);
411 }
412 else if (value.compare("starts_with") == 0)
413 {
414 match_info.SetNameMatchType (eNameMatchStartsWith);
415 }
416 else if (value.compare("ends_with") == 0)
417 {
418 match_info.SetNameMatchType (eNameMatchEndsWith);
419 }
420 else if (value.compare("contains") == 0)
421 {
422 match_info.SetNameMatchType (eNameMatchContains);
423 }
424 else if (value.compare("regex") == 0)
425 {
426 match_info.SetNameMatchType (eNameMatchRegularExpression);
427 }
428 else
429 {
430 success = false;
431 }
432 }
433 else if (key.compare("pid") == 0)
434 {
435 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
436 }
437 else if (key.compare("parent_pid") == 0)
438 {
439 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
440 }
441 else if (key.compare("uid") == 0)
442 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000443 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton32e0a752011-03-30 18:16:51 +0000444 }
445 else if (key.compare("gid") == 0)
446 {
Greg Clayton8b82f082011-04-12 05:54:46 +0000447 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
Greg Clayton32e0a752011-03-30 18:16:51 +0000448 }
449 else if (key.compare("euid") == 0)
450 {
451 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
452 }
453 else if (key.compare("egid") == 0)
454 {
455 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
456 }
457 else if (key.compare("all_users") == 0)
458 {
459 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
460 }
461 else if (key.compare("triple") == 0)
462 {
Greg Claytoneb0103f2011-04-07 22:46:35 +0000463 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
Greg Clayton32e0a752011-03-30 18:16:51 +0000464 }
465 else
466 {
467 success = false;
468 }
469
470 if (!success)
471 return SendErrorResponse (2);
472 }
473 }
474
475 if (Host::FindProcesses (match_info, m_proc_infos))
476 {
477 // We found something, return the first item by calling the get
478 // subsequent process info packet handler...
479 return Handle_qsProcessInfo (packet);
480 }
481 return SendErrorResponse (3);
482}
483
484bool
485GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
486{
487 if (m_proc_infos_index < m_proc_infos.GetSize())
488 {
489 StreamString response;
490 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
491 ++m_proc_infos_index;
Greg Clayton37a0a242012-04-11 00:24:49 +0000492 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000493 }
494 return SendErrorResponse (4);
495}
496
497bool
498GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
499{
500 // Packet format: "qUserName:%i" where %i is the uid
Greg Clayton8b82f082011-04-12 05:54:46 +0000501 packet.SetFilePos(::strlen ("qUserName:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000502 uint32_t uid = packet.GetU32 (UINT32_MAX);
503 if (uid != UINT32_MAX)
504 {
505 std::string name;
506 if (Host::GetUserName (uid, name))
507 {
508 StreamString response;
509 response.PutCStringAsRawHex8 (name.c_str());
Greg Clayton37a0a242012-04-11 00:24:49 +0000510 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000511 }
512 }
513 return SendErrorResponse (5);
514
515}
516
517bool
518GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
519{
520 // Packet format: "qGroupName:%i" where %i is the gid
Greg Clayton8b82f082011-04-12 05:54:46 +0000521 packet.SetFilePos(::strlen ("qGroupName:"));
Greg Clayton32e0a752011-03-30 18:16:51 +0000522 uint32_t gid = packet.GetU32 (UINT32_MAX);
523 if (gid != UINT32_MAX)
524 {
525 std::string name;
526 if (Host::GetGroupName (gid, name))
527 {
528 StreamString response;
529 response.PutCStringAsRawHex8 (name.c_str());
Greg Clayton37a0a242012-04-11 00:24:49 +0000530 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton32e0a752011-03-30 18:16:51 +0000531 }
532 }
533 return SendErrorResponse (6);
534}
535
536bool
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000537GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
538{
Greg Clayton8b82f082011-04-12 05:54:46 +0000539 packet.SetFilePos(::strlen ("qSpeedTest:"));
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000540
541 std::string key;
542 std::string value;
543 bool success = packet.GetNameColonValue(key, value);
544 if (success && key.compare("response_size") == 0)
545 {
546 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
547 if (success)
548 {
549 if (response_size == 0)
550 return SendOKResponse();
551 StreamString response;
552 uint32_t bytes_left = response_size;
553 response.PutCString("data:");
554 while (bytes_left > 0)
555 {
556 if (bytes_left >= 26)
557 {
558 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
559 bytes_left -= 26;
560 }
561 else
562 {
563 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
564 bytes_left = 0;
565 }
566 }
Greg Clayton37a0a242012-04-11 00:24:49 +0000567 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton9b1e1cd2011-04-04 18:18:57 +0000568 }
569 }
570 return SendErrorResponse (7);
571}
Greg Clayton8b82f082011-04-12 05:54:46 +0000572
573
574static void *
575AcceptPortFromInferior (void *arg)
576{
577 const char *connect_url = (const char *)arg;
578 ConnectionFileDescriptor file_conn;
579 Error error;
580 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
581 {
582 char pid_str[256];
583 ::memset (pid_str, 0, sizeof(pid_str));
584 ConnectionStatus status;
Bill Wendlinged24dcc2012-04-03 07:50:11 +0000585 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
Greg Clayton8b82f082011-04-12 05:54:46 +0000586 if (pid_str_len > 0)
587 {
588 int pid = atoi (pid_str);
589 return (void *)(intptr_t)pid;
590 }
591 }
592 return NULL;
593}
594//
595//static bool
596//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
597//{
598// const int time_delta_usecs = 100000;
599// const int num_retries = timeout_in_seconds/time_delta_usecs;
600// for (int i=0; i<num_retries; i++)
601// {
602// struct proc_bsdinfo bsd_info;
603// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
604// (uint64_t) 0,
605// &bsd_info,
606// PROC_PIDTBSDINFO_SIZE);
607//
608// switch (error)
609// {
610// case EINVAL:
611// case ENOTSUP:
612// case ESRCH:
613// case EPERM:
614// return false;
615//
616// default:
617// break;
618//
619// case 0:
620// if (bsd_info.pbi_status == SSTOP)
621// return true;
622// }
623// ::usleep (time_delta_usecs);
624// }
625// return false;
626//}
627
628bool
629GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
630{
631 // The 'A' packet is the most over designed packet ever here with
632 // redundant argument indexes, redundant argument lengths and needed hex
633 // encoded argument string values. Really all that is needed is a comma
634 // separated hex encoded argument value list, but we will stay true to the
635 // documented version of the 'A' packet here...
636
637 packet.SetFilePos(1); // Skip the 'A'
638 bool success = true;
639 while (success && packet.GetBytesLeft() > 0)
640 {
641 // Decode the decimal argument string length. This length is the
642 // number of hex nibbles in the argument string value.
643 const uint32_t arg_len = packet.GetU32(UINT32_MAX);
644 if (arg_len == UINT32_MAX)
645 success = false;
646 else
647 {
648 // Make sure the argument hex string length is followed by a comma
649 if (packet.GetChar() != ',')
650 success = false;
651 else
652 {
653 // Decode the argument index. We ignore this really becuase
654 // who would really send down the arguments in a random order???
655 const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
656 if (arg_idx == UINT32_MAX)
657 success = false;
658 else
659 {
660 // Make sure the argument index is followed by a comma
661 if (packet.GetChar() != ',')
662 success = false;
663 else
664 {
665 // Decode the argument string value from hex bytes
666 // back into a UTF8 string and make sure the length
667 // matches the one supplied in the packet
668 std::string arg;
669 if (packet.GetHexByteString(arg) != (arg_len / 2))
670 success = false;
671 else
672 {
673 // If there are any bytes lft
674 if (packet.GetBytesLeft())
675 {
676 if (packet.GetChar() != ',')
677 success = false;
678 }
679
680 if (success)
681 {
682 if (arg_idx == 0)
683 m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
684 m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
685 }
686 }
687 }
688 }
689 }
690 }
691 }
692
693 if (success)
694 {
695 m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
696 m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
697 if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
698 {
699 return SendOKResponse ();
700 }
701 }
702 return SendErrorResponse (8);
703}
704
705bool
706GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
707{
708 lldb::pid_t pid = m_process_launch_info.GetProcessID();
709 StreamString response;
Daniel Malead01b2952012-11-29 21:49:15 +0000710 response.Printf("QC%" PRIx64, pid);
Greg Clayton8b82f082011-04-12 05:54:46 +0000711 if (m_is_platform)
712 {
713 // If we launch a process and this GDB server is acting as a platform,
714 // then we need to clear the process launch state so we can start
715 // launching another process. In order to launch a process a bunch or
716 // packets need to be sent: environment packets, working directory,
717 // disable ASLR, and many more settings. When we launch a process we
718 // then need to know when to clear this information. Currently we are
719 // selecting the 'qC' packet as that packet which seems to make the most
720 // sense.
721 if (pid != LLDB_INVALID_PROCESS_ID)
722 {
723 m_process_launch_info.Clear();
724 }
725 }
Greg Clayton37a0a242012-04-11 00:24:49 +0000726 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton8b82f082011-04-12 05:54:46 +0000727}
728
729bool
Daniel Maleae0f8f572013-08-26 23:57:52 +0000730GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
731{
732 Mutex::Locker locker (m_spawned_pids_mutex);
733 return m_spawned_pids.erase(pid) > 0;
734}
735bool
736GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
737 lldb::pid_t pid,
738 bool exited,
739 int signal, // Zero for no signal
740 int status) // Exit value of process if signal is zero
741{
742 GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
743 server->DebugserverProcessReaped (pid);
744 return true;
745}
746
747bool
Greg Clayton8b82f082011-04-12 05:54:46 +0000748GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
749{
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000750#ifdef _WIN32
751 // No unix sockets on windows
752 return false;
753#else
Greg Clayton8b82f082011-04-12 05:54:46 +0000754 // Spawn a local debugserver as a platform so we can then attach or launch
755 // a process...
756
757 if (m_is_platform)
758 {
759 // Sleep and wait a bit for debugserver to start to listen...
760 ConnectionFileDescriptor file_conn;
761 char connect_url[PATH_MAX];
762 Error error;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000763 std::string hostname;
764 char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
Greg Clayton8b82f082011-04-12 05:54:46 +0000765 if (::mktemp (unix_socket_name) == NULL)
766 {
767 error.SetErrorString ("failed to make temporary path for a unix socket");
768 }
769 else
770 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000771 packet.SetFilePos(::strlen ("qLaunchGDBServer:"));
772 std::string name;
773 std::string value;
774 uint16_t port = UINT16_MAX;
775 while (packet.GetNameColonValue(name, value))
776 {
777 if (name.compare ("host") == 0)
778 hostname.swap(value);
779 else if (name.compare ("port") == 0)
780 port = Args::StringToUInt32(value.c_str(), 0, 0);
781 }
782 if (port == UINT16_MAX)
783 port = GetAndUpdateNextPort();
784
Greg Clayton8b82f082011-04-12 05:54:46 +0000785 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
786 // Spawn a new thread to accept the port that gets bound after
787 // binding to port 0 (zero).
Michael Sartain338803f2013-08-27 18:59:54 +0000788 lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000789
790 if (port == 0)
791 {
792 accept_thread = Host::ThreadCreate (unix_socket_name,
793 AcceptPortFromInferior,
794 connect_url,
795 &error);
796 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000797
798 if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
799 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000800 // Spawn a debugserver and try to get the port it listens to.
Greg Clayton8b82f082011-04-12 05:54:46 +0000801 ProcessLaunchInfo debugserver_launch_info;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000802 StreamString host_and_port;
803 if (hostname.empty())
804 hostname = "localhost";
805 host_and_port.Printf("%s:%u", hostname.c_str(), port);
806 const char *host_and_port_cstr = host_and_port.GetString().c_str();
807 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
808 if (log)
809 log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
810 error = StartDebugserverProcess (host_and_port_cstr,
Greg Clayton8b82f082011-04-12 05:54:46 +0000811 unix_socket_name,
812 debugserver_launch_info);
813
814 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000815
816 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
817 {
818 {
819 Mutex::Locker locker (m_spawned_pids_mutex);
820 m_spawned_pids.insert(debugserver_pid);
821 }
822 Host::StartMonitoringChildProcess (ReapDebugserverProcess, this, debugserver_pid, false);
823 }
824
Greg Clayton8b82f082011-04-12 05:54:46 +0000825 if (error.Success())
826 {
827 bool success = false;
828
Daniel Maleae0f8f572013-08-26 23:57:52 +0000829 if (accept_thread)
Greg Clayton8b82f082011-04-12 05:54:46 +0000830 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000831 thread_result_t accept_thread_result = NULL;
832 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
Greg Clayton8b82f082011-04-12 05:54:46 +0000833 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000834 if (accept_thread_result)
835 {
836 port = (intptr_t)accept_thread_result;
837 char response[256];
838 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
839 assert (response_len < sizeof(response));
840 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
841 success = SendPacketNoLock (response, response_len) > 0;
842 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000843 }
844 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000845 else
846 {
847 char response[256];
848 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
849 assert (response_len < sizeof(response));
850 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
851 success = SendPacketNoLock (response, response_len) > 0;
852
853 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000854 ::unlink (unix_socket_name);
855
856 if (!success)
857 {
858 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
859 ::kill (debugserver_pid, SIGINT);
860 }
861 return success;
862 }
863 }
864 }
865 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000866 return SendErrorResponse (9);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000867#endif
Greg Clayton8b82f082011-04-12 05:54:46 +0000868}
869
870bool
Daniel Maleae0f8f572013-08-26 23:57:52 +0000871GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
872{
873 // Spawn a local debugserver as a platform so we can then attach or launch
874 // a process...
875
876 if (m_is_platform)
877 {
878 packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
879
880 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
881
882 // Scope for locker
883 {
884 Mutex::Locker locker (m_spawned_pids_mutex);
885 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
886 return SendErrorResponse (10);
887 }
Virgile Belloae12a362013-08-27 16:21:49 +0000888 Host::Kill (pid, SIGTERM);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000889
890 for (size_t i=0; i<10; ++i)
891 {
892 // Scope for locker
893 {
894 Mutex::Locker locker (m_spawned_pids_mutex);
895 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
896 return true;
897 }
898 usleep (10000);
899 }
900
901 // Scope for locker
902 {
903 Mutex::Locker locker (m_spawned_pids_mutex);
904 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
905 return true;
906 }
Virgile Belloae12a362013-08-27 16:21:49 +0000907 Host::Kill (pid, SIGKILL);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000908
909 for (size_t i=0; i<10; ++i)
910 {
911 // Scope for locker
912 {
913 Mutex::Locker locker (m_spawned_pids_mutex);
914 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
915 return true;
916 }
917 usleep (10000);
918 }
919 }
920 return SendErrorResponse (10);
921}
922
923bool
Greg Clayton8b82f082011-04-12 05:54:46 +0000924GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
925{
926 if (m_process_launch_error.Success())
927 return SendOKResponse();
928 StreamString response;
929 response.PutChar('E');
930 response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
Greg Clayton37a0a242012-04-11 00:24:49 +0000931 return SendPacketNoLock (response.GetData(), response.GetSize());
Greg Clayton8b82f082011-04-12 05:54:46 +0000932}
933
934bool
935GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
936{
937 packet.SetFilePos(::strlen ("QEnvironment:"));
938 const uint32_t bytes_left = packet.GetBytesLeft();
939 if (bytes_left > 0)
940 {
941 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
942 return SendOKResponse ();
943 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000944 return SendErrorResponse (11);
945}
946
947bool
948GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
949{
950 packet.SetFilePos(::strlen ("QLaunchArch:"));
951 const uint32_t bytes_left = packet.GetBytesLeft();
952 if (bytes_left > 0)
953 {
954 const char* arch_triple = packet.Peek();
955 ArchSpec arch_spec(arch_triple,NULL);
956 m_process_launch_info.SetArchitecture(arch_spec);
957 return SendOKResponse();
958 }
959 return SendErrorResponse(12);
Greg Clayton8b82f082011-04-12 05:54:46 +0000960}
961
962bool
963GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
964{
965 packet.SetFilePos(::strlen ("QSetDisableASLR:"));
966 if (packet.GetU32(0))
967 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
968 else
969 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
970 return SendOKResponse ();
971}
972
973bool
974GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
975{
976 packet.SetFilePos(::strlen ("QSetWorkingDir:"));
977 std::string path;
978 packet.GetHexByteString(path);
979 m_process_launch_info.SwapWorkingDirectory (path);
980 return SendOKResponse ();
981}
982
983bool
984GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
985{
986 packet.SetFilePos(::strlen ("QSetSTDIN:"));
987 ProcessLaunchInfo::FileAction file_action;
988 std::string path;
989 packet.GetHexByteString(path);
990 const bool read = false;
991 const bool write = true;
992 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
993 {
994 m_process_launch_info.AppendFileAction(file_action);
995 return SendOKResponse ();
996 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000997 return SendErrorResponse (13);
Greg Clayton8b82f082011-04-12 05:54:46 +0000998}
999
1000bool
1001GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
1002{
1003 packet.SetFilePos(::strlen ("QSetSTDOUT:"));
1004 ProcessLaunchInfo::FileAction file_action;
1005 std::string path;
1006 packet.GetHexByteString(path);
1007 const bool read = true;
1008 const bool write = false;
1009 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
1010 {
1011 m_process_launch_info.AppendFileAction(file_action);
1012 return SendOKResponse ();
1013 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001014 return SendErrorResponse (14);
Greg Clayton8b82f082011-04-12 05:54:46 +00001015}
1016
1017bool
1018GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
1019{
1020 packet.SetFilePos(::strlen ("QSetSTDERR:"));
1021 ProcessLaunchInfo::FileAction file_action;
1022 std::string path;
1023 packet.GetHexByteString(path);
1024 const bool read = true;
Greg Clayton9845a8d2012-03-06 04:01:04 +00001025 const bool write = false;
Greg Clayton8b82f082011-04-12 05:54:46 +00001026 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
1027 {
1028 m_process_launch_info.AppendFileAction(file_action);
1029 return SendOKResponse ();
1030 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001031 return SendErrorResponse (15);
Greg Clayton8b82f082011-04-12 05:54:46 +00001032}
1033
Greg Clayton9b1e1cd2011-04-04 18:18:57 +00001034bool
Greg Clayton32e0a752011-03-30 18:16:51 +00001035GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
1036{
1037 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton1cb64962011-03-24 04:28:38 +00001038 SendOKResponse ();
1039 m_send_acks = false;
1040 return true;
1041}
Daniel Maleae0f8f572013-08-26 23:57:52 +00001042
1043bool
1044GDBRemoteCommunicationServer::Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet)
1045{
1046 packet.SetFilePos(::strlen("qPlatform_IO_MkDir:"));
1047 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
1048 if (packet.GetChar() != ',')
1049 return false;
1050 std::string path;
1051 packet.GetHexByteString(path);
1052 uint32_t retcode = Host::MakeDirectory(path.c_str(),mode);
1053 StreamString response;
1054 response.PutHex32(retcode);
1055 SendPacketNoLock(response.GetData(), response.GetSize());
1056 return true;
1057}
1058
1059bool
1060GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
1061{
1062 packet.SetFilePos(::strlen("vFile:open:"));
1063 std::string path;
1064 packet.GetHexByteStringTerminatedBy(path,',');
1065 if (path.size() == 0)
1066 return false;
1067 if (packet.GetChar() != ',')
1068 return false;
1069 uint32_t flags = packet.GetHexMaxU32(false, UINT32_MAX);
1070 if (packet.GetChar() != ',')
1071 return false;
1072 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
1073 Error error;
1074 int fd = ::open (path.c_str(), flags, mode);
1075 const int save_errno = fd == -1 ? errno : 0;
1076 StreamString response;
1077 response.PutChar('F');
1078 response.Printf("%i", fd);
1079 if (save_errno)
1080 response.Printf(",%i", save_errno);
1081 SendPacketNoLock(response.GetData(), response.GetSize());
1082 return true;
1083}
1084
1085bool
1086GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
1087{
1088 packet.SetFilePos(::strlen("vFile:close:"));
1089 int fd = packet.GetS32(-1);
1090 Error error;
1091 int err = -1;
1092 int save_errno = 0;
1093 if (fd >= 0)
1094 {
1095 err = close(fd);
1096 save_errno = err == -1 ? errno : 0;
1097 }
1098 else
1099 {
1100 save_errno = EINVAL;
1101 }
1102 StreamString response;
1103 response.PutChar('F');
1104 response.Printf("%i", err);
1105 if (save_errno)
1106 response.Printf(",%i", save_errno);
1107 SendPacketNoLock(response.GetData(), response.GetSize());
1108 return true;
1109}
1110
1111bool
1112GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
1113{
Virgile Belloae12a362013-08-27 16:21:49 +00001114#ifdef _WIN32
1115 // Not implemented on Windows
1116 return false;
1117#else
Daniel Maleae0f8f572013-08-26 23:57:52 +00001118 StreamGDBRemote response;
1119 packet.SetFilePos(::strlen("vFile:pread:"));
1120 int fd = packet.GetS32(-1);
1121 if (packet.GetChar() != ',')
1122 return false;
1123 uint64_t count = packet.GetU64(UINT64_MAX);
1124 if (packet.GetChar() != ',')
1125 return false;
1126 uint64_t offset = packet.GetU64(UINT32_MAX);
1127 if (count == UINT64_MAX)
1128 {
1129 response.Printf("F-1:%i", EINVAL);
1130 SendPacketNoLock(response.GetData(), response.GetSize());
1131 return true;
1132 }
1133 std::string buffer(count, 0);
1134 const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
1135 const int save_errno = bytes_read == -1 ? errno : 0;
1136 response.PutChar('F');
1137 response.Printf("%zi", bytes_read);
1138 if (save_errno)
1139 response.Printf(",%i", save_errno);
1140 else
1141 {
1142 response.PutChar(';');
1143 response.PutEscapedBytes(&buffer[0], bytes_read);
1144 }
1145 SendPacketNoLock(response.GetData(), response.GetSize());
1146 return true;
Virgile Belloae12a362013-08-27 16:21:49 +00001147#endif
Daniel Maleae0f8f572013-08-26 23:57:52 +00001148}
1149
1150bool
1151GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
1152{
Virgile Belloae12a362013-08-27 16:21:49 +00001153#ifdef _WIN32
1154 // Not implemented on Windows
1155 return false;
1156#else
Daniel Maleae0f8f572013-08-26 23:57:52 +00001157 packet.SetFilePos(::strlen("vFile:pwrite:"));
1158
1159 StreamGDBRemote response;
1160 response.PutChar('F');
1161
1162 int fd = packet.GetU32(UINT32_MAX);
1163 if (packet.GetChar() != ',')
1164 return false;
1165 off_t offset = packet.GetU64(UINT32_MAX);
1166 if (packet.GetChar() != ',')
1167 return false;
1168 std::string buffer;
1169 if (packet.GetEscapedBinaryData(buffer))
1170 {
1171 const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
1172 const int save_errno = bytes_written == -1 ? errno : 0;
1173 response.Printf("%zi", bytes_written);
1174 if (save_errno)
1175 response.Printf(",%i", save_errno);
1176 }
1177 else
1178 {
1179 response.Printf ("-1,%i", EINVAL);
1180 }
1181
1182 SendPacketNoLock(response.GetData(), response.GetSize());
1183 return true;
Virgile Belloae12a362013-08-27 16:21:49 +00001184#endif
Daniel Maleae0f8f572013-08-26 23:57:52 +00001185}
1186
1187bool
1188GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
1189{
1190 packet.SetFilePos(::strlen("vFile:size:"));
1191 std::string path;
1192 packet.GetHexByteString(path);
1193 if (path.empty())
1194 return false;
1195 lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
1196 StreamString response;
1197 response.PutChar('F');
1198 response.PutHex64(retcode);
1199 if (retcode == UINT64_MAX)
1200 {
1201 response.PutChar(',');
1202 response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
1203 }
1204 SendPacketNoLock(response.GetData(), response.GetSize());
1205 return true;
1206}
1207
1208bool
1209GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
1210{
1211 packet.SetFilePos(::strlen("vFile:mode:"));
1212 std::string path;
1213 packet.GetHexByteString(path);
1214 if (path.empty())
1215 return false;
1216 Error error;
1217 const uint32_t mode = File::GetPermissions(path.c_str(), error);
1218 StreamString response;
1219 response.Printf("F%u", mode);
1220 if (mode == 0 || error.Fail())
1221 response.Printf(",%i", (int)error.GetError());
1222 SendPacketNoLock(response.GetData(), response.GetSize());
1223 return true;
1224}
1225
1226bool
1227GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
1228{
1229 packet.SetFilePos(::strlen("vFile:exists:"));
1230 std::string path;
1231 packet.GetHexByteString(path);
1232 if (path.empty())
1233 return false;
1234 bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
1235 StreamString response;
1236 response.PutChar('F');
1237 response.PutChar(',');
1238 if (retcode)
1239 response.PutChar('1');
1240 else
1241 response.PutChar('0');
1242 SendPacketNoLock(response.GetData(), response.GetSize());
1243 return true;
1244}
1245
1246bool
1247GDBRemoteCommunicationServer::Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet)
1248{
1249 packet.SetFilePos(::strlen("qPlatform_RunCommand:"));
1250 std::string path;
1251 std::string working_dir;
1252 packet.GetHexByteStringTerminatedBy(path,',');
1253 if (path.size() == 0)
1254 return false;
1255 if (packet.GetChar() != ',')
1256 return false;
Daniel Maleabb247fb2013-08-27 21:01:01 +00001257 // FIXME: add timeout to qPlatform_RunCommand packet
1258 // uint32_t timeout = packet.GetHexMaxU32(false, 32);
1259 uint32_t timeout = 10;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001260 if (packet.GetChar() == ',')
1261 packet.GetHexByteString(working_dir);
1262 int status, signo;
1263 std::string output;
1264 Error err = Host::RunShellCommand(path.c_str(),
1265 working_dir.empty() ? NULL : working_dir.c_str(),
1266 &status, &signo, &output, timeout);
1267 StreamGDBRemote response;
1268 if (err.Fail())
1269 {
1270 response.PutCString("F,");
1271 response.PutHex32(UINT32_MAX);
1272 }
1273 else
1274 {
1275 response.PutCString("F,");
1276 response.PutHex32(status);
1277 response.PutChar(',');
1278 response.PutHex32(signo);
1279 response.PutChar(',');
1280 response.PutEscapedBytes(output.c_str(), output.size());
1281 }
1282 SendPacketNoLock(response.GetData(), response.GetSize());
1283 return true;
1284}
1285
1286bool
1287GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
1288{
1289 return false;
1290}
1291
1292bool
1293GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
1294{
1295 packet.SetFilePos(::strlen("vFile:exists:"));
1296 std::string path;
1297 packet.GetHexByteString(path);
1298 if (path.size() == 0)
1299 return false;
1300 uint64_t a,b;
1301 StreamGDBRemote response;
1302 if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
1303 {
1304 response.PutCString("F,");
1305 response.PutCString("x");
1306 }
1307 else
1308 {
1309 response.PutCString("F,");
1310 response.PutHex64(a);
1311 response.PutHex64(b);
1312 }
1313 SendPacketNoLock(response.GetData(), response.GetSize());
1314 return true;
1315}