1 //===-- StringExtractorGDBRemote.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 // C Includes 11 #include <string.h> 12 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "Utility/StringExtractorGDBRemote.h" 17 18 StringExtractorGDBRemote::ResponseType 19 StringExtractorGDBRemote::GetResponseType () const 20 { 21 if (m_packet.empty()) 22 return eUnsupported; 23 24 switch (m_packet[0]) 25 { 26 case 'E': 27 if (m_packet.size() == 3 && 28 isxdigit(m_packet[1]) && 29 isxdigit(m_packet[2])) 30 return eError; 31 break; 32 33 case 'O': 34 if (m_packet.size() == 2 && m_packet[1] == 'K') 35 return eOK; 36 break; 37 38 case '+': 39 if (m_packet.size() == 1) 40 return eAck; 41 break; 42 43 case '-': 44 if (m_packet.size() == 1) 45 return eNack; 46 break; 47 } 48 return eResponse; 49 } 50 51 StringExtractorGDBRemote::ServerPacketType 52 StringExtractorGDBRemote::GetServerPacketType () const 53 { 54 #define PACKET_MATCHES(s) ((packet_size == (sizeof(s)-1)) && (strcmp((packet_cstr),(s)) == 0)) 55 #define PACKET_STARTS_WITH(s) ((packet_size >= (sizeof(s)-1)) && ::strncmp(packet_cstr, s, (sizeof(s)-1))==0) 56 57 // Empty is not a supported packet... 58 if (m_packet.empty()) 59 return eServerPacketType_invalid; 60 61 const size_t packet_size = m_packet.size(); 62 const char *packet_cstr = m_packet.c_str(); 63 switch (m_packet[0]) 64 { 65 66 case '%': 67 return eServerPacketType_notify; 68 69 case '\x03': 70 if (packet_size == 1) return eServerPacketType_interrupt; 71 break; 72 73 case '-': 74 if (packet_size == 1) return eServerPacketType_nack; 75 break; 76 77 case '+': 78 if (packet_size == 1) return eServerPacketType_ack; 79 break; 80 81 case 'A': 82 return eServerPacketType_A; 83 84 case 'Q': 85 86 switch (packet_cstr[1]) 87 { 88 case 'E': 89 if (PACKET_STARTS_WITH ("QEnvironment:")) return eServerPacketType_QEnvironment; 90 if (PACKET_STARTS_WITH ("QEnvironmentHexEncoded:")) return eServerPacketType_QEnvironmentHexEncoded; 91 break; 92 93 case 'S': 94 if (PACKET_MATCHES ("QStartNoAckMode")) return eServerPacketType_QStartNoAckMode; 95 if (PACKET_STARTS_WITH ("QSaveRegisterState")) return eServerPacketType_QSaveRegisterState; 96 if (PACKET_STARTS_WITH ("QSetDisableASLR:")) return eServerPacketType_QSetDisableASLR; 97 if (PACKET_STARTS_WITH ("QSetDetachOnError:")) return eServerPacketType_QSetDetachOnError; 98 if (PACKET_STARTS_WITH ("QSetSTDIN:")) return eServerPacketType_QSetSTDIN; 99 if (PACKET_STARTS_WITH ("QSetSTDOUT:")) return eServerPacketType_QSetSTDOUT; 100 if (PACKET_STARTS_WITH ("QSetSTDERR:")) return eServerPacketType_QSetSTDERR; 101 if (PACKET_STARTS_WITH ("QSetWorkingDir:")) return eServerPacketType_QSetWorkingDir; 102 if (PACKET_STARTS_WITH ("QSetLogging:")) return eServerPacketType_QSetLogging; 103 if (PACKET_STARTS_WITH ("QSetMaxPacketSize:")) return eServerPacketType_QSetMaxPacketSize; 104 if (PACKET_STARTS_WITH ("QSetMaxPayloadSize:")) return eServerPacketType_QSetMaxPayloadSize; 105 if (PACKET_STARTS_WITH ("QSetEnableAsyncProfiling;")) return eServerPacketType_QSetEnableAsyncProfiling; 106 if (PACKET_STARTS_WITH ("QSyncThreadState:")) return eServerPacketType_QSyncThreadState; 107 break; 108 109 case 'L': 110 if (PACKET_STARTS_WITH ("QLaunchArch:")) return eServerPacketType_QLaunchArch; 111 if (PACKET_MATCHES("QListThreadsInStopReply")) return eServerPacketType_QListThreadsInStopReply; 112 break; 113 114 case 'R': 115 if (PACKET_STARTS_WITH ("QRestoreRegisterState:")) return eServerPacketType_QRestoreRegisterState; 116 break; 117 118 case 'T': 119 if (PACKET_MATCHES ("QThreadSuffixSupported")) return eServerPacketType_QThreadSuffixSupported; 120 break; 121 } 122 break; 123 124 case 'q': 125 switch (packet_cstr[1]) 126 { 127 case 's': 128 if (PACKET_MATCHES ("qsProcessInfo")) return eServerPacketType_qsProcessInfo; 129 if (PACKET_MATCHES ("qsThreadInfo")) return eServerPacketType_qsThreadInfo; 130 break; 131 132 case 'f': 133 if (PACKET_STARTS_WITH ("qfProcessInfo")) return eServerPacketType_qfProcessInfo; 134 if (PACKET_STARTS_WITH ("qfThreadInfo")) return eServerPacketType_qfThreadInfo; 135 break; 136 137 case 'C': 138 if (packet_size == 2) return eServerPacketType_qC; 139 break; 140 141 case 'E': 142 if (PACKET_STARTS_WITH ("qEcho:")) return eServerPacketType_qEcho; 143 break; 144 145 case 'F': 146 if (PACKET_STARTS_WITH ("qFileLoadAddress:")) return eServerPacketType_qFileLoadAddress; 147 break; 148 149 case 'G': 150 if (PACKET_STARTS_WITH ("qGroupName:")) return eServerPacketType_qGroupName; 151 if (PACKET_MATCHES ("qGetWorkingDir")) return eServerPacketType_qGetWorkingDir; 152 if (PACKET_MATCHES ("qGetPid")) return eServerPacketType_qGetPid; 153 if (PACKET_STARTS_WITH ("qGetProfileData;")) return eServerPacketType_qGetProfileData; 154 if (PACKET_MATCHES ("qGDBServerVersion")) return eServerPacketType_qGDBServerVersion; 155 break; 156 157 case 'H': 158 if (PACKET_MATCHES ("qHostInfo")) return eServerPacketType_qHostInfo; 159 break; 160 161 case 'K': 162 if (PACKET_STARTS_WITH ("qKillSpawnedProcess")) return eServerPacketType_qKillSpawnedProcess; 163 break; 164 165 case 'L': 166 if (PACKET_STARTS_WITH ("qLaunchGDBServer")) return eServerPacketType_qLaunchGDBServer; 167 if (PACKET_MATCHES ("qLaunchSuccess")) return eServerPacketType_qLaunchSuccess; 168 break; 169 170 case 'M': 171 if (PACKET_STARTS_WITH ("qMemoryRegionInfo:")) return eServerPacketType_qMemoryRegionInfo; 172 if (PACKET_MATCHES ("qMemoryRegionInfo")) return eServerPacketType_qMemoryRegionInfoSupported; 173 if (PACKET_STARTS_WITH ("qModuleInfo:")) return eServerPacketType_qModuleInfo; 174 break; 175 176 case 'P': 177 if (PACKET_STARTS_WITH ("qProcessInfoPID:")) return eServerPacketType_qProcessInfoPID; 178 if (PACKET_STARTS_WITH ("qPlatform_shell:")) return eServerPacketType_qPlatform_shell; 179 if (PACKET_STARTS_WITH ("qPlatform_mkdir:")) return eServerPacketType_qPlatform_mkdir; 180 if (PACKET_STARTS_WITH ("qPlatform_chmod:")) return eServerPacketType_qPlatform_chmod; 181 if (PACKET_MATCHES ("qProcessInfo")) return eServerPacketType_qProcessInfo; 182 break; 183 184 case 'Q': 185 if (PACKET_MATCHES ("qQueryGDBServer")) return eServerPacketType_qQueryGDBServer; 186 break; 187 188 case 'R': 189 if (PACKET_STARTS_WITH ("qRcmd,")) return eServerPacketType_qRcmd; 190 if (PACKET_STARTS_WITH ("qRegisterInfo")) return eServerPacketType_qRegisterInfo; 191 break; 192 193 case 'S': 194 if (PACKET_STARTS_WITH ("qSpeedTest:")) return eServerPacketType_qSpeedTest; 195 if (PACKET_MATCHES ("qShlibInfoAddr")) return eServerPacketType_qShlibInfoAddr; 196 if (PACKET_MATCHES ("qStepPacketSupported")) return eServerPacketType_qStepPacketSupported; 197 if (PACKET_STARTS_WITH ("qSupported")) return eServerPacketType_qSupported; 198 if (PACKET_MATCHES ("qSyncThreadStateSupported")) return eServerPacketType_qSyncThreadStateSupported; 199 break; 200 201 case 'T': 202 if (PACKET_STARTS_WITH ("qThreadExtraInfo,")) return eServerPacketType_qThreadExtraInfo; 203 if (PACKET_STARTS_WITH ("qThreadStopInfo")) return eServerPacketType_qThreadStopInfo; 204 break; 205 206 case 'U': 207 if (PACKET_STARTS_WITH ("qUserName:")) return eServerPacketType_qUserName; 208 break; 209 210 case 'V': 211 if (PACKET_MATCHES ("qVAttachOrWaitSupported")) return eServerPacketType_qVAttachOrWaitSupported; 212 break; 213 214 case 'W': 215 if (PACKET_STARTS_WITH ("qWatchpointSupportInfo:")) return eServerPacketType_qWatchpointSupportInfo; 216 if (PACKET_MATCHES ("qWatchpointSupportInfo")) return eServerPacketType_qWatchpointSupportInfoSupported; 217 break; 218 219 case 'X': 220 if (PACKET_STARTS_WITH ("qXfer:auxv:read::")) return eServerPacketType_qXfer_auxv_read; 221 break; 222 } 223 break; 224 225 case 'j': 226 if (PACKET_MATCHES("jSignalsInfo")) return eServerPacketType_jSignalsInfo; 227 if (PACKET_MATCHES("jThreadsInfo")) return eServerPacketType_jThreadsInfo; 228 break; 229 230 case 'v': 231 if (PACKET_STARTS_WITH("vFile:")) 232 { 233 if (PACKET_STARTS_WITH("vFile:open:")) return eServerPacketType_vFile_open; 234 else if (PACKET_STARTS_WITH("vFile:close:")) return eServerPacketType_vFile_close; 235 else if (PACKET_STARTS_WITH("vFile:pread")) return eServerPacketType_vFile_pread; 236 else if (PACKET_STARTS_WITH("vFile:pwrite")) return eServerPacketType_vFile_pwrite; 237 else if (PACKET_STARTS_WITH("vFile:size")) return eServerPacketType_vFile_size; 238 else if (PACKET_STARTS_WITH("vFile:exists")) return eServerPacketType_vFile_exists; 239 else if (PACKET_STARTS_WITH("vFile:stat")) return eServerPacketType_vFile_stat; 240 else if (PACKET_STARTS_WITH("vFile:mode")) return eServerPacketType_vFile_mode; 241 else if (PACKET_STARTS_WITH("vFile:MD5")) return eServerPacketType_vFile_md5; 242 else if (PACKET_STARTS_WITH("vFile:symlink")) return eServerPacketType_vFile_symlink; 243 else if (PACKET_STARTS_WITH("vFile:unlink")) return eServerPacketType_vFile_unlink; 244 245 } else { 246 if (PACKET_STARTS_WITH ("vAttach;")) return eServerPacketType_vAttach; 247 if (PACKET_STARTS_WITH ("vAttachWait;")) return eServerPacketType_vAttachWait; 248 if (PACKET_STARTS_WITH ("vAttachOrWait;")) return eServerPacketType_vAttachOrWait; 249 if (PACKET_STARTS_WITH ("vAttachName;")) return eServerPacketType_vAttachName; 250 if (PACKET_STARTS_WITH("vCont;")) return eServerPacketType_vCont; 251 if (PACKET_MATCHES ("vCont?")) return eServerPacketType_vCont_actions; 252 } 253 break; 254 case '_': 255 switch (packet_cstr[1]) 256 { 257 case 'M': 258 return eServerPacketType__M; 259 260 case 'm': 261 return eServerPacketType__m; 262 } 263 break; 264 265 case '?': 266 if (packet_size == 1) return eServerPacketType_stop_reason; 267 break; 268 269 case 'c': 270 return eServerPacketType_c; 271 272 case 'C': 273 return eServerPacketType_C; 274 275 case 'D': 276 if (packet_size == 1) return eServerPacketType_D; 277 break; 278 279 case 'g': 280 if (packet_size == 1) return eServerPacketType_g; 281 break; 282 283 case 'G': 284 return eServerPacketType_G; 285 286 case 'H': 287 return eServerPacketType_H; 288 289 case 'I': 290 return eServerPacketType_I; 291 292 case 'k': 293 if (packet_size == 1) return eServerPacketType_k; 294 break; 295 296 case 'm': 297 return eServerPacketType_m; 298 299 case 'M': 300 return eServerPacketType_M; 301 302 case 'p': 303 return eServerPacketType_p; 304 305 case 'P': 306 return eServerPacketType_P; 307 308 case 's': 309 if (packet_size == 1) return eServerPacketType_s; 310 break; 311 312 case 'S': 313 return eServerPacketType_S; 314 315 case 'x': 316 return eServerPacketType_x; 317 318 case 'X': 319 return eServerPacketType_X; 320 321 case 'T': 322 return eServerPacketType_T; 323 324 case 'z': 325 if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4') 326 return eServerPacketType_z; 327 break; 328 329 case 'Z': 330 if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4') 331 return eServerPacketType_Z; 332 break; 333 } 334 return eServerPacketType_unimplemented; 335 } 336 337 bool 338 StringExtractorGDBRemote::IsOKResponse() const 339 { 340 return GetResponseType () == eOK; 341 } 342 343 344 bool 345 StringExtractorGDBRemote::IsUnsupportedResponse() const 346 { 347 return GetResponseType () == eUnsupported; 348 } 349 350 bool 351 StringExtractorGDBRemote::IsNormalResponse() const 352 { 353 return GetResponseType () == eResponse; 354 } 355 356 bool 357 StringExtractorGDBRemote::IsErrorResponse() const 358 { 359 return GetResponseType () == eError && 360 m_packet.size() == 3 && 361 isxdigit(m_packet[1]) && 362 isxdigit(m_packet[2]); 363 } 364 365 uint8_t 366 StringExtractorGDBRemote::GetError () 367 { 368 if (GetResponseType() == eError) 369 { 370 SetFilePos(1); 371 return GetHexU8(255); 372 } 373 return 0; 374 } 375 376 size_t 377 StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str) 378 { 379 // Just get the data bytes in the string as GDBRemoteCommunication::CheckForPacket() 380 // already removes any 0x7d escaped characters. If any 0x7d characters are left in 381 // the packet, then they are supposed to be there... 382 str.clear(); 383 const size_t bytes_left = GetBytesLeft(); 384 if (bytes_left > 0) 385 { 386 str.assign(m_packet, m_index, bytes_left); 387 m_index += bytes_left; 388 } 389 return str.size(); 390 } 391 392 static bool 393 OKErrorNotSupportedResponseValidator(void *, const StringExtractorGDBRemote &response) 394 { 395 switch (response.GetResponseType()) 396 { 397 case StringExtractorGDBRemote::eOK: 398 case StringExtractorGDBRemote::eError: 399 case StringExtractorGDBRemote::eUnsupported: 400 return true; 401 402 case StringExtractorGDBRemote::eAck: 403 case StringExtractorGDBRemote::eNack: 404 case StringExtractorGDBRemote::eResponse: 405 break; 406 } 407 return false; 408 } 409 410 static bool 411 JSONResponseValidator(void *, const StringExtractorGDBRemote &response) 412 { 413 switch (response.GetResponseType()) 414 { 415 case StringExtractorGDBRemote::eUnsupported: 416 case StringExtractorGDBRemote::eError: 417 return true; // Accept unsupported or EXX as valid responses 418 419 case StringExtractorGDBRemote::eOK: 420 case StringExtractorGDBRemote::eAck: 421 case StringExtractorGDBRemote::eNack: 422 break; 423 424 case StringExtractorGDBRemote::eResponse: 425 // JSON that is returned in from JSON query packets is currently always 426 // either a dictionary which starts with a '{', or an array which 427 // starts with a '['. This is a quick validator to just make sure the 428 // response could be valid JSON without having to validate all of the 429 // JSON content. 430 switch (response.GetStringRef()[0]) 431 { 432 case '{': return true; 433 case '[': return true; 434 default: 435 break; 436 } 437 break; 438 } 439 return false; 440 } 441 442 static bool 443 ASCIIHexBytesResponseValidator(void *, const StringExtractorGDBRemote &response) 444 { 445 switch (response.GetResponseType()) 446 { 447 case StringExtractorGDBRemote::eUnsupported: 448 case StringExtractorGDBRemote::eError: 449 return true; // Accept unsupported or EXX as valid responses 450 451 case StringExtractorGDBRemote::eOK: 452 case StringExtractorGDBRemote::eAck: 453 case StringExtractorGDBRemote::eNack: 454 break; 455 456 case StringExtractorGDBRemote::eResponse: 457 { 458 uint32_t valid_count = 0; 459 for (const char ch : response.GetStringRef()) 460 { 461 if (!isxdigit(ch)) 462 { 463 return false; 464 } 465 if (++valid_count >= 16) 466 break; // Don't validate all the characters in case the packet is very large 467 } 468 return true; 469 } 470 break; 471 } 472 return false; 473 } 474 475 void 476 StringExtractorGDBRemote::CopyResponseValidator(const StringExtractorGDBRemote& rhs) 477 { 478 m_validator = rhs.m_validator; 479 m_validator_baton = rhs.m_validator_baton; 480 } 481 482 void 483 StringExtractorGDBRemote::SetResponseValidator(ResponseValidatorCallback callback, void *baton) 484 { 485 m_validator = callback; 486 m_validator_baton = baton; 487 } 488 489 void 490 StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() 491 { 492 m_validator = OKErrorNotSupportedResponseValidator; 493 m_validator_baton = nullptr; 494 } 495 496 void 497 StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() 498 { 499 m_validator = ASCIIHexBytesResponseValidator; 500 m_validator_baton = nullptr; 501 } 502 503 void 504 StringExtractorGDBRemote::SetResponseValidatorToJSON() 505 { 506 m_validator = JSONResponseValidator; 507 m_validator_baton = nullptr; 508 } 509 510 bool 511 StringExtractorGDBRemote::ValidateResponse() const 512 { 513 // If we have a validator callback, try to validate the callback 514 if (m_validator) 515 return m_validator(m_validator_baton, *this); 516 else 517 return true; // No validator, so response is valid 518 } 519 520 521