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