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_MATCHES("jSignalsInfo")) 283 return eServerPacketType_jSignalsInfo; 284 if (PACKET_MATCHES("jThreadsInfo")) 285 return eServerPacketType_jThreadsInfo; 286 break; 287 288 case 'v': 289 if (PACKET_STARTS_WITH("vFile:")) { 290 if (PACKET_STARTS_WITH("vFile:open:")) 291 return eServerPacketType_vFile_open; 292 else if (PACKET_STARTS_WITH("vFile:close:")) 293 return eServerPacketType_vFile_close; 294 else if (PACKET_STARTS_WITH("vFile:pread")) 295 return eServerPacketType_vFile_pread; 296 else if (PACKET_STARTS_WITH("vFile:pwrite")) 297 return eServerPacketType_vFile_pwrite; 298 else if (PACKET_STARTS_WITH("vFile:size")) 299 return eServerPacketType_vFile_size; 300 else if (PACKET_STARTS_WITH("vFile:exists")) 301 return eServerPacketType_vFile_exists; 302 else if (PACKET_STARTS_WITH("vFile:stat")) 303 return eServerPacketType_vFile_stat; 304 else if (PACKET_STARTS_WITH("vFile:mode")) 305 return eServerPacketType_vFile_mode; 306 else if (PACKET_STARTS_WITH("vFile:MD5")) 307 return eServerPacketType_vFile_md5; 308 else if (PACKET_STARTS_WITH("vFile:symlink")) 309 return eServerPacketType_vFile_symlink; 310 else if (PACKET_STARTS_WITH("vFile:unlink")) 311 return eServerPacketType_vFile_unlink; 312 313 } else { 314 if (PACKET_STARTS_WITH("vAttach;")) 315 return eServerPacketType_vAttach; 316 if (PACKET_STARTS_WITH("vAttachWait;")) 317 return eServerPacketType_vAttachWait; 318 if (PACKET_STARTS_WITH("vAttachOrWait;")) 319 return eServerPacketType_vAttachOrWait; 320 if (PACKET_STARTS_WITH("vAttachName;")) 321 return eServerPacketType_vAttachName; 322 if (PACKET_STARTS_WITH("vCont;")) 323 return eServerPacketType_vCont; 324 if (PACKET_MATCHES("vCont?")) 325 return eServerPacketType_vCont_actions; 326 } 327 break; 328 case '_': 329 switch (packet_cstr[1]) { 330 case 'M': 331 return eServerPacketType__M; 332 333 case 'm': 334 return eServerPacketType__m; 335 } 336 break; 337 338 case '?': 339 if (packet_size == 1) 340 return eServerPacketType_stop_reason; 341 break; 342 343 case 'c': 344 return eServerPacketType_c; 345 346 case 'C': 347 return eServerPacketType_C; 348 349 case 'D': 350 if (packet_size == 1) 351 return eServerPacketType_D; 352 break; 353 354 case 'g': 355 if (packet_size == 1) 356 return eServerPacketType_g; 357 break; 358 359 case 'G': 360 return eServerPacketType_G; 361 362 case 'H': 363 return eServerPacketType_H; 364 365 case 'I': 366 return eServerPacketType_I; 367 368 case 'k': 369 if (packet_size == 1) 370 return eServerPacketType_k; 371 break; 372 373 case 'm': 374 return eServerPacketType_m; 375 376 case 'M': 377 return eServerPacketType_M; 378 379 case 'p': 380 return eServerPacketType_p; 381 382 case 'P': 383 return eServerPacketType_P; 384 385 case 's': 386 if (packet_size == 1) 387 return eServerPacketType_s; 388 break; 389 390 case 'S': 391 return eServerPacketType_S; 392 393 case 'x': 394 return eServerPacketType_x; 395 396 case 'X': 397 return eServerPacketType_X; 398 399 case 'T': 400 return eServerPacketType_T; 401 402 case 'z': 403 if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4') 404 return eServerPacketType_z; 405 break; 406 407 case 'Z': 408 if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4') 409 return eServerPacketType_Z; 410 break; 411 } 412 return eServerPacketType_unimplemented; 413 } 414 415 bool StringExtractorGDBRemote::IsOKResponse() const { 416 return GetResponseType() == eOK; 417 } 418 419 bool StringExtractorGDBRemote::IsUnsupportedResponse() const { 420 return GetResponseType() == eUnsupported; 421 } 422 423 bool StringExtractorGDBRemote::IsNormalResponse() const { 424 return GetResponseType() == eResponse; 425 } 426 427 bool StringExtractorGDBRemote::IsErrorResponse() const { 428 return GetResponseType() == eError && m_packet.size() == 3 && 429 isxdigit(m_packet[1]) && isxdigit(m_packet[2]); 430 } 431 432 uint8_t StringExtractorGDBRemote::GetError() { 433 if (GetResponseType() == eError) { 434 SetFilePos(1); 435 return GetHexU8(255); 436 } 437 return 0; 438 } 439 440 size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) { 441 // Just get the data bytes in the string as 442 // GDBRemoteCommunication::CheckForPacket() 443 // already removes any 0x7d escaped characters. If any 0x7d characters are 444 // left in 445 // the packet, then they are supposed to be there... 446 str.clear(); 447 const size_t bytes_left = GetBytesLeft(); 448 if (bytes_left > 0) { 449 str.assign(m_packet, m_index, bytes_left); 450 m_index += bytes_left; 451 } 452 return str.size(); 453 } 454 455 static bool 456 OKErrorNotSupportedResponseValidator(void *, 457 const StringExtractorGDBRemote &response) { 458 switch (response.GetResponseType()) { 459 case StringExtractorGDBRemote::eOK: 460 case StringExtractorGDBRemote::eError: 461 case StringExtractorGDBRemote::eUnsupported: 462 return true; 463 464 case StringExtractorGDBRemote::eAck: 465 case StringExtractorGDBRemote::eNack: 466 case StringExtractorGDBRemote::eResponse: 467 break; 468 } 469 return false; 470 } 471 472 static bool JSONResponseValidator(void *, 473 const StringExtractorGDBRemote &response) { 474 switch (response.GetResponseType()) { 475 case StringExtractorGDBRemote::eUnsupported: 476 case StringExtractorGDBRemote::eError: 477 return true; // Accept unsupported or EXX as valid responses 478 479 case StringExtractorGDBRemote::eOK: 480 case StringExtractorGDBRemote::eAck: 481 case StringExtractorGDBRemote::eNack: 482 break; 483 484 case StringExtractorGDBRemote::eResponse: 485 // JSON that is returned in from JSON query packets is currently always 486 // either a dictionary which starts with a '{', or an array which 487 // starts with a '['. This is a quick validator to just make sure the 488 // response could be valid JSON without having to validate all of the 489 // JSON content. 490 switch (response.GetStringRef()[0]) { 491 case '{': 492 return true; 493 case '[': 494 return true; 495 default: 496 break; 497 } 498 break; 499 } 500 return false; 501 } 502 503 static bool 504 ASCIIHexBytesResponseValidator(void *, 505 const StringExtractorGDBRemote &response) { 506 switch (response.GetResponseType()) { 507 case StringExtractorGDBRemote::eUnsupported: 508 case StringExtractorGDBRemote::eError: 509 return true; // Accept unsupported or EXX as valid responses 510 511 case StringExtractorGDBRemote::eOK: 512 case StringExtractorGDBRemote::eAck: 513 case StringExtractorGDBRemote::eNack: 514 break; 515 516 case StringExtractorGDBRemote::eResponse: { 517 uint32_t valid_count = 0; 518 for (const char ch : response.GetStringRef()) { 519 if (!isxdigit(ch)) { 520 return false; 521 } 522 if (++valid_count >= 16) 523 break; // Don't validate all the characters in case the packet is very 524 // large 525 } 526 return true; 527 } break; 528 } 529 return false; 530 } 531 532 void StringExtractorGDBRemote::CopyResponseValidator( 533 const StringExtractorGDBRemote &rhs) { 534 m_validator = rhs.m_validator; 535 m_validator_baton = rhs.m_validator_baton; 536 } 537 538 void StringExtractorGDBRemote::SetResponseValidator( 539 ResponseValidatorCallback callback, void *baton) { 540 m_validator = callback; 541 m_validator_baton = baton; 542 } 543 544 void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() { 545 m_validator = OKErrorNotSupportedResponseValidator; 546 m_validator_baton = nullptr; 547 } 548 549 void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() { 550 m_validator = ASCIIHexBytesResponseValidator; 551 m_validator_baton = nullptr; 552 } 553 554 void StringExtractorGDBRemote::SetResponseValidatorToJSON() { 555 m_validator = JSONResponseValidator; 556 m_validator_baton = nullptr; 557 } 558 559 bool StringExtractorGDBRemote::ValidateResponse() const { 560 // If we have a validator callback, try to validate the callback 561 if (m_validator) 562 return m_validator(m_validator_baton, *this); 563 else 564 return true; // No validator, so response is valid 565 } 566