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