blob: ea6842b999ac23c8d469fd81b49b2f9a451a2f33 [file] [log] [blame]
Greg Clayton61d043b2011-03-22 04:00:09 +00001//===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10
11#include "GDBRemoteCommunicationServer.h"
12
13// C Includes
14// C++ Includes
15// Other libraries and framework includes
16#include "llvm/ADT/Triple.h"
17#include "lldb/Interpreter/Args.h"
18#include "lldb/Core/ConnectionFileDescriptor.h"
19#include "lldb/Core/Log.h"
20#include "lldb/Core/State.h"
21#include "lldb/Core/StreamString.h"
22#include "lldb/Host/Host.h"
23#include "lldb/Host/TimeValue.h"
24
25// Project includes
26#include "Utility/StringExtractorGDBRemote.h"
27#include "ProcessGDBRemote.h"
28#include "ProcessGDBRemoteLog.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33//----------------------------------------------------------------------
34// GDBRemoteCommunicationServer constructor
35//----------------------------------------------------------------------
36GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() :
37 GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet"),
Greg Clayton58e26e02011-03-24 04:28:38 +000038 m_async_thread (LLDB_INVALID_HOST_THREAD)
Greg Clayton61d043b2011-03-22 04:00:09 +000039{
40}
41
42//----------------------------------------------------------------------
43// Destructor
44//----------------------------------------------------------------------
45GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
46{
47}
48
49
50//void *
51//GDBRemoteCommunicationServer::AsyncThread (void *arg)
52//{
53// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
54//
55// LogSP log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
56// if (log)
57// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
58//
59// StringExtractorGDBRemote packet;
60//
61// while ()
62// {
63// if (packet.
64// }
65//
66// if (log)
67// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
68//
69// process->m_async_thread = LLDB_INVALID_HOST_THREAD;
70// return NULL;
71//}
72//
73bool
Greg Claytoncb8977d2011-03-23 00:09:55 +000074GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr,
Greg Clayton58e26e02011-03-24 04:28:38 +000075 Error &error,
Greg Claytoncb8977d2011-03-23 00:09:55 +000076 bool &interrupt,
77 bool &quit)
Greg Clayton61d043b2011-03-22 04:00:09 +000078{
79 StringExtractorGDBRemote packet;
Greg Claytoncb8977d2011-03-23 00:09:55 +000080 if (WaitForPacketNoLock (packet, timeout_ptr))
Greg Clayton61d043b2011-03-22 04:00:09 +000081 {
82 const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
83 switch (packet_type)
84 {
85 case StringExtractorGDBRemote::eServerPacketType_nack:
86 case StringExtractorGDBRemote::eServerPacketType_ack:
87 break;
88
89 case StringExtractorGDBRemote::eServerPacketType_invalid:
Greg Clayton58e26e02011-03-24 04:28:38 +000090 error.SetErrorString("invalid packet");
Greg Claytoncb8977d2011-03-23 00:09:55 +000091 quit = true;
92 break;
93
94 case StringExtractorGDBRemote::eServerPacketType_interrupt:
Greg Clayton58e26e02011-03-24 04:28:38 +000095 error.SetErrorString("interrupt received");
Greg Claytoncb8977d2011-03-23 00:09:55 +000096 interrupt = true;
97 break;
98
Greg Clayton61d043b2011-03-22 04:00:09 +000099 case StringExtractorGDBRemote::eServerPacketType_unimplemented:
Greg Clayton24bc5d92011-03-30 18:16:51 +0000100 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000101
102 case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
Greg Clayton24bc5d92011-03-30 18:16:51 +0000103 return Handle_qHostInfo (packet);
104
105 case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
106 return Handle_qProcessInfoPID (packet);
107
108 case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
109 return Handle_qfProcessInfo (packet);
110
111 case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
112 return Handle_qsProcessInfo (packet);
113
114 case StringExtractorGDBRemote::eServerPacketType_qUserName:
115 return Handle_qUserName (packet);
116
117 case StringExtractorGDBRemote::eServerPacketType_qGroupName:
118 return Handle_qGroupName (packet);
119
Greg Clayton58e26e02011-03-24 04:28:38 +0000120 case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
Greg Clayton24bc5d92011-03-30 18:16:51 +0000121 return Handle_QStartNoAckMode (packet);
Greg Clayton61d043b2011-03-22 04:00:09 +0000122 }
123 return true;
124 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000125 else
126 {
127 if (!IsConnected())
128 error.SetErrorString("lost connection");
129 else
130 error.SetErrorString("timeout");
131 }
132
Greg Clayton61d043b2011-03-22 04:00:09 +0000133 return false;
134}
135
136size_t
Greg Clayton24bc5d92011-03-30 18:16:51 +0000137GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
Greg Clayton61d043b2011-03-22 04:00:09 +0000138{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000139 // TODO: Log the packet we aren't handling...
Greg Clayton61d043b2011-03-22 04:00:09 +0000140 return SendPacket ("");
141}
142
Greg Clayton58e26e02011-03-24 04:28:38 +0000143size_t
Greg Clayton24bc5d92011-03-30 18:16:51 +0000144GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
145{
146 char packet[16];
147 int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
148 assert (packet_len < sizeof(packet));
149 return SendPacket (packet, packet_len);
150}
151
152
153size_t
Greg Clayton58e26e02011-03-24 04:28:38 +0000154GDBRemoteCommunicationServer::SendOKResponse ()
155{
156 return SendPacket ("OK");
157}
158
159bool
160GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
161{
162 if (StartReadThread(error_ptr))
163 return GetAck();
164 return false;
165}
Greg Clayton61d043b2011-03-22 04:00:09 +0000166
167bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000168GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
Greg Clayton61d043b2011-03-22 04:00:09 +0000169{
170 StreamString response;
171
172 // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
173
174 ArchSpec host_arch (Host::GetArchitecture ());
Greg Clayton61d043b2011-03-22 04:00:09 +0000175 const llvm::Triple &host_triple = host_arch.GetTriple();
Greg Clayton58e26e02011-03-24 04:28:38 +0000176 response.PutCString("triple:");
177 response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
178 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
Greg Clayton61d043b2011-03-22 04:00:09 +0000179
Greg Clayton58e26e02011-03-24 04:28:38 +0000180 uint32_t cpu = host_arch.GetMachOCPUType();
181 uint32_t sub = host_arch.GetMachOCPUSubType();
182 if (cpu != LLDB_INVALID_CPUTYPE)
183 response.Printf ("cputype:%u;", cpu);
184 if (sub != LLDB_INVALID_CPUTYPE)
185 response.Printf ("cpusubtype:%u;", sub);
186
Greg Clayton61d043b2011-03-22 04:00:09 +0000187 switch (lldb::endian::InlHostByteOrder())
188 {
189 case eByteOrderBig: response.PutCString ("endian:big;"); break;
190 case eByteOrderLittle: response.PutCString ("endian:little;"); break;
191 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
192 default: response.PutCString ("endian:unknown;"); break;
193 }
194
Greg Clayton58e26e02011-03-24 04:28:38 +0000195 uint32_t major = UINT32_MAX;
196 uint32_t minor = UINT32_MAX;
197 uint32_t update = UINT32_MAX;
198 if (Host::GetOSVersion (major, minor, update))
199 {
200 if (major != UINT32_MAX)
201 {
202 response.Printf("os_version:%u", major);
203 if (minor != UINT32_MAX)
204 {
205 response.Printf(".%u", minor);
206 if (update != UINT32_MAX)
207 response.Printf(".%u", update);
208 }
209 response.PutChar(';');
210 }
211 }
212
213 std::string s;
214 if (Host::GetOSBuildString (s))
215 {
216 response.PutCString ("os_build:");
217 response.PutCStringAsRawHex8(s.c_str());
218 response.PutChar(';');
219 }
220 if (Host::GetOSKernelDescription (s))
221 {
222 response.PutCString ("os_kernel:");
223 response.PutCStringAsRawHex8(s.c_str());
224 response.PutChar(';');
225 }
226 if (Host::GetHostname (s))
227 {
228 response.PutCString ("hostname:");
229 response.PutCStringAsRawHex8(s.c_str());
230 response.PutChar(';');
231 }
232
Greg Clayton24bc5d92011-03-30 18:16:51 +0000233 return SendPacket (response) > 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000234}
Greg Clayton58e26e02011-03-24 04:28:38 +0000235
Greg Clayton24bc5d92011-03-30 18:16:51 +0000236static void
237CreateProcessInfoResponse (const ProcessInfo &proc_info, StreamString &response)
238{
239 response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;",
240 proc_info.GetProcessID(),
241 proc_info.GetParentProcessID(),
242 proc_info.GetRealUserID(),
243 proc_info.GetRealGroupID(),
244 proc_info.GetEffectiveUserID(),
245 proc_info.GetEffectiveGroupID());
246 response.PutCString ("name:");
247 response.PutCStringAsRawHex8(proc_info.GetName());
248 response.PutChar(';');
249 const ArchSpec &proc_arch = proc_info.GetArchitecture();
250 if (proc_arch.IsValid())
251 {
252 const llvm::Triple &proc_triple = proc_arch.GetTriple();
253 response.PutCString("triple:");
254 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
255 response.PutChar(';');
256 }
257}
Greg Clayton58e26e02011-03-24 04:28:38 +0000258
259bool
Greg Clayton24bc5d92011-03-30 18:16:51 +0000260GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
Greg Clayton58e26e02011-03-24 04:28:38 +0000261{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000262 // Packet format: "qProcessInfoPID:%i" where %i is the pid
263 packet.SetFilePos(strlen ("qProcessInfoPID:"));
264 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
265 if (pid != LLDB_INVALID_PROCESS_ID)
266 {
267 ProcessInfo proc_info;
268 if (Host::GetProcessInfo(pid, proc_info))
269 {
270 StreamString response;
271 CreateProcessInfoResponse (proc_info, response);
272 return SendPacket (response);
273 }
274 }
275 return SendErrorResponse (1);
276}
277
278bool
279GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
280{
281 m_proc_infos_index = 0;
282 m_proc_infos.Clear();
283
284 ProcessInfoMatch match_info;
285 packet.SetFilePos(strlen ("qfProcessInfo"));
286 if (packet.GetChar() == ':')
287 {
288
289 std::string key;
290 std::string value;
291 while (packet.GetNameColonValue(key, value))
292 {
293 bool success = true;
294 if (key.compare("name") == 0)
295 {
296 StringExtractor extractor;
297 extractor.GetStringRef().swap(value);
298 extractor.GetHexByteString (value);
299 match_info.GetProcessInfo().SetName (value.c_str());
300 }
301 else if (key.compare("name_match") == 0)
302 {
303 if (value.compare("equals") == 0)
304 {
305 match_info.SetNameMatchType (eNameMatchEquals);
306 }
307 else if (value.compare("starts_with") == 0)
308 {
309 match_info.SetNameMatchType (eNameMatchStartsWith);
310 }
311 else if (value.compare("ends_with") == 0)
312 {
313 match_info.SetNameMatchType (eNameMatchEndsWith);
314 }
315 else if (value.compare("contains") == 0)
316 {
317 match_info.SetNameMatchType (eNameMatchContains);
318 }
319 else if (value.compare("regex") == 0)
320 {
321 match_info.SetNameMatchType (eNameMatchRegularExpression);
322 }
323 else
324 {
325 success = false;
326 }
327 }
328 else if (key.compare("pid") == 0)
329 {
330 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
331 }
332 else if (key.compare("parent_pid") == 0)
333 {
334 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
335 }
336 else if (key.compare("uid") == 0)
337 {
338 match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
339 }
340 else if (key.compare("gid") == 0)
341 {
342 match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
343 }
344 else if (key.compare("euid") == 0)
345 {
346 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
347 }
348 else if (key.compare("egid") == 0)
349 {
350 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
351 }
352 else if (key.compare("all_users") == 0)
353 {
354 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
355 }
356 else if (key.compare("triple") == 0)
357 {
358 match_info.GetProcessInfo().GetArchitecture().SetTriple(value.c_str());
359 }
360 else
361 {
362 success = false;
363 }
364
365 if (!success)
366 return SendErrorResponse (2);
367 }
368 }
369
370 if (Host::FindProcesses (match_info, m_proc_infos))
371 {
372 // We found something, return the first item by calling the get
373 // subsequent process info packet handler...
374 return Handle_qsProcessInfo (packet);
375 }
376 return SendErrorResponse (3);
377}
378
379bool
380GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
381{
382 if (m_proc_infos_index < m_proc_infos.GetSize())
383 {
384 StreamString response;
385 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
386 ++m_proc_infos_index;
387 return SendPacket (response);
388 }
389 return SendErrorResponse (4);
390}
391
392bool
393GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
394{
395 // Packet format: "qUserName:%i" where %i is the uid
396 packet.SetFilePos(strlen ("qUserName:"));
397 uint32_t uid = packet.GetU32 (UINT32_MAX);
398 if (uid != UINT32_MAX)
399 {
400 std::string name;
401 if (Host::GetUserName (uid, name))
402 {
403 StreamString response;
404 response.PutCStringAsRawHex8 (name.c_str());
405 return SendPacket (response);
406 }
407 }
408 return SendErrorResponse (5);
409
410}
411
412bool
413GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
414{
415 // Packet format: "qGroupName:%i" where %i is the gid
416 packet.SetFilePos(strlen ("qGroupName:"));
417 uint32_t gid = packet.GetU32 (UINT32_MAX);
418 if (gid != UINT32_MAX)
419 {
420 std::string name;
421 if (Host::GetGroupName (gid, name))
422 {
423 StreamString response;
424 response.PutCStringAsRawHex8 (name.c_str());
425 return SendPacket (response);
426 }
427 }
428 return SendErrorResponse (6);
429}
430
431bool
432GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
433{
434 // Send response first before changing m_send_acks to we ack this packet
Greg Clayton58e26e02011-03-24 04:28:38 +0000435 SendOKResponse ();
436 m_send_acks = false;
437 return true;
438}