1 //===-- 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 30 using namespace lldb; 31 using namespace lldb_private; 32 33 //---------------------------------------------------------------------- 34 // GDBRemoteCommunicationServer constructor 35 //---------------------------------------------------------------------- 36 GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() : 37 GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet"), 38 m_async_thread (LLDB_INVALID_HOST_THREAD) 39 { 40 } 41 42 //---------------------------------------------------------------------- 43 // Destructor 44 //---------------------------------------------------------------------- 45 GDBRemoteCommunicationServer::~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 // 73 bool 74 GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr, 75 Error &error, 76 bool &interrupt, 77 bool &quit) 78 { 79 StringExtractorGDBRemote packet; 80 if (WaitForPacketNoLock (packet, timeout_ptr)) 81 { 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: 90 error.SetErrorString("invalid packet"); 91 quit = true; 92 break; 93 94 case StringExtractorGDBRemote::eServerPacketType_interrupt: 95 error.SetErrorString("interrupt received"); 96 interrupt = true; 97 break; 98 99 case StringExtractorGDBRemote::eServerPacketType_unimplemented: 100 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0; 101 102 case StringExtractorGDBRemote::eServerPacketType_qHostInfo: 103 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 120 case StringExtractorGDBRemote::eServerPacketType_qSpeedTest: 121 return Handle_qSpeedTest (packet); 122 case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: 123 return Handle_QStartNoAckMode (packet); 124 } 125 return true; 126 } 127 else 128 { 129 if (!IsConnected()) 130 error.SetErrorString("lost connection"); 131 else 132 error.SetErrorString("timeout"); 133 } 134 135 return false; 136 } 137 138 size_t 139 GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) 140 { 141 // TODO: Log the packet we aren't handling... 142 return SendPacket (""); 143 } 144 145 size_t 146 GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err) 147 { 148 char packet[16]; 149 int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err); 150 assert (packet_len < sizeof(packet)); 151 return SendPacket (packet, packet_len); 152 } 153 154 155 size_t 156 GDBRemoteCommunicationServer::SendOKResponse () 157 { 158 return SendPacket ("OK"); 159 } 160 161 bool 162 GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr) 163 { 164 if (StartReadThread(error_ptr)) 165 return GetAck(); 166 return false; 167 } 168 169 bool 170 GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet) 171 { 172 StreamString response; 173 174 // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 175 176 ArchSpec host_arch (Host::GetArchitecture ()); 177 const llvm::Triple &host_triple = host_arch.GetTriple(); 178 response.PutCString("triple:"); 179 response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); 180 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); 181 182 uint32_t cpu = host_arch.GetMachOCPUType(); 183 uint32_t sub = host_arch.GetMachOCPUSubType(); 184 if (cpu != LLDB_INVALID_CPUTYPE) 185 response.Printf ("cputype:%u;", cpu); 186 if (sub != LLDB_INVALID_CPUTYPE) 187 response.Printf ("cpusubtype:%u;", sub); 188 189 switch (lldb::endian::InlHostByteOrder()) 190 { 191 case eByteOrderBig: response.PutCString ("endian:big;"); break; 192 case eByteOrderLittle: response.PutCString ("endian:little;"); break; 193 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break; 194 default: response.PutCString ("endian:unknown;"); break; 195 } 196 197 uint32_t major = UINT32_MAX; 198 uint32_t minor = UINT32_MAX; 199 uint32_t update = UINT32_MAX; 200 if (Host::GetOSVersion (major, minor, update)) 201 { 202 if (major != UINT32_MAX) 203 { 204 response.Printf("os_version:%u", major); 205 if (minor != UINT32_MAX) 206 { 207 response.Printf(".%u", minor); 208 if (update != UINT32_MAX) 209 response.Printf(".%u", update); 210 } 211 response.PutChar(';'); 212 } 213 } 214 215 std::string s; 216 if (Host::GetOSBuildString (s)) 217 { 218 response.PutCString ("os_build:"); 219 response.PutCStringAsRawHex8(s.c_str()); 220 response.PutChar(';'); 221 } 222 if (Host::GetOSKernelDescription (s)) 223 { 224 response.PutCString ("os_kernel:"); 225 response.PutCStringAsRawHex8(s.c_str()); 226 response.PutChar(';'); 227 } 228 if (Host::GetHostname (s)) 229 { 230 response.PutCString ("hostname:"); 231 response.PutCStringAsRawHex8(s.c_str()); 232 response.PutChar(';'); 233 } 234 235 return SendPacket (response) > 0; 236 } 237 238 static void 239 CreateProcessInfoResponse (const ProcessInfo &proc_info, StreamString &response) 240 { 241 response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;", 242 proc_info.GetProcessID(), 243 proc_info.GetParentProcessID(), 244 proc_info.GetRealUserID(), 245 proc_info.GetRealGroupID(), 246 proc_info.GetEffectiveUserID(), 247 proc_info.GetEffectiveGroupID()); 248 response.PutCString ("name:"); 249 response.PutCStringAsRawHex8(proc_info.GetName()); 250 response.PutChar(';'); 251 const ArchSpec &proc_arch = proc_info.GetArchitecture(); 252 if (proc_arch.IsValid()) 253 { 254 const llvm::Triple &proc_triple = proc_arch.GetTriple(); 255 response.PutCString("triple:"); 256 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); 257 response.PutChar(';'); 258 } 259 } 260 261 bool 262 GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet) 263 { 264 // Packet format: "qProcessInfoPID:%i" where %i is the pid 265 packet.SetFilePos(strlen ("qProcessInfoPID:")); 266 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID); 267 if (pid != LLDB_INVALID_PROCESS_ID) 268 { 269 ProcessInfo proc_info; 270 if (Host::GetProcessInfo(pid, proc_info)) 271 { 272 StreamString response; 273 CreateProcessInfoResponse (proc_info, response); 274 return SendPacket (response); 275 } 276 } 277 return SendErrorResponse (1); 278 } 279 280 bool 281 GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet) 282 { 283 m_proc_infos_index = 0; 284 m_proc_infos.Clear(); 285 286 ProcessInfoMatch match_info; 287 packet.SetFilePos(strlen ("qfProcessInfo")); 288 if (packet.GetChar() == ':') 289 { 290 291 std::string key; 292 std::string value; 293 while (packet.GetNameColonValue(key, value)) 294 { 295 bool success = true; 296 if (key.compare("name") == 0) 297 { 298 StringExtractor extractor; 299 extractor.GetStringRef().swap(value); 300 extractor.GetHexByteString (value); 301 match_info.GetProcessInfo().SetName (value.c_str()); 302 } 303 else if (key.compare("name_match") == 0) 304 { 305 if (value.compare("equals") == 0) 306 { 307 match_info.SetNameMatchType (eNameMatchEquals); 308 } 309 else if (value.compare("starts_with") == 0) 310 { 311 match_info.SetNameMatchType (eNameMatchStartsWith); 312 } 313 else if (value.compare("ends_with") == 0) 314 { 315 match_info.SetNameMatchType (eNameMatchEndsWith); 316 } 317 else if (value.compare("contains") == 0) 318 { 319 match_info.SetNameMatchType (eNameMatchContains); 320 } 321 else if (value.compare("regex") == 0) 322 { 323 match_info.SetNameMatchType (eNameMatchRegularExpression); 324 } 325 else 326 { 327 success = false; 328 } 329 } 330 else if (key.compare("pid") == 0) 331 { 332 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 333 } 334 else if (key.compare("parent_pid") == 0) 335 { 336 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 337 } 338 else if (key.compare("uid") == 0) 339 { 340 match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 341 } 342 else if (key.compare("gid") == 0) 343 { 344 match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 345 } 346 else if (key.compare("euid") == 0) 347 { 348 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 349 } 350 else if (key.compare("egid") == 0) 351 { 352 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 353 } 354 else if (key.compare("all_users") == 0) 355 { 356 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success)); 357 } 358 else if (key.compare("triple") == 0) 359 { 360 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL); 361 } 362 else 363 { 364 success = false; 365 } 366 367 if (!success) 368 return SendErrorResponse (2); 369 } 370 } 371 372 if (Host::FindProcesses (match_info, m_proc_infos)) 373 { 374 // We found something, return the first item by calling the get 375 // subsequent process info packet handler... 376 return Handle_qsProcessInfo (packet); 377 } 378 return SendErrorResponse (3); 379 } 380 381 bool 382 GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet) 383 { 384 if (m_proc_infos_index < m_proc_infos.GetSize()) 385 { 386 StreamString response; 387 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); 388 ++m_proc_infos_index; 389 return SendPacket (response); 390 } 391 return SendErrorResponse (4); 392 } 393 394 bool 395 GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet) 396 { 397 // Packet format: "qUserName:%i" where %i is the uid 398 packet.SetFilePos(strlen ("qUserName:")); 399 uint32_t uid = packet.GetU32 (UINT32_MAX); 400 if (uid != UINT32_MAX) 401 { 402 std::string name; 403 if (Host::GetUserName (uid, name)) 404 { 405 StreamString response; 406 response.PutCStringAsRawHex8 (name.c_str()); 407 return SendPacket (response); 408 } 409 } 410 return SendErrorResponse (5); 411 412 } 413 414 bool 415 GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet) 416 { 417 // Packet format: "qGroupName:%i" where %i is the gid 418 packet.SetFilePos(strlen ("qGroupName:")); 419 uint32_t gid = packet.GetU32 (UINT32_MAX); 420 if (gid != UINT32_MAX) 421 { 422 std::string name; 423 if (Host::GetGroupName (gid, name)) 424 { 425 StreamString response; 426 response.PutCStringAsRawHex8 (name.c_str()); 427 return SendPacket (response); 428 } 429 } 430 return SendErrorResponse (6); 431 } 432 433 bool 434 GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet) 435 { 436 packet.SetFilePos(strlen ("qSpeedTest:")); 437 438 std::string key; 439 std::string value; 440 bool success = packet.GetNameColonValue(key, value); 441 if (success && key.compare("response_size") == 0) 442 { 443 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); 444 if (success) 445 { 446 if (response_size == 0) 447 return SendOKResponse(); 448 StreamString response; 449 uint32_t bytes_left = response_size; 450 response.PutCString("data:"); 451 while (bytes_left > 0) 452 { 453 if (bytes_left >= 26) 454 { 455 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 456 bytes_left -= 26; 457 } 458 else 459 { 460 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 461 bytes_left = 0; 462 } 463 } 464 return SendPacket (response); 465 } 466 } 467 return SendErrorResponse (7); 468 } 469 bool 470 GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet) 471 { 472 // Send response first before changing m_send_acks to we ack this packet 473 SendOKResponse (); 474 m_send_acks = false; 475 return true; 476 } 477