1 //===-- StringExtractorGDBRemote.cpp --------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "lldb/Utility/StringExtractorGDBRemote.h"
10
11 #include <cctype>
12 #include <cstring>
13
14 constexpr lldb::pid_t StringExtractorGDBRemote::AllProcesses;
15 constexpr lldb::tid_t StringExtractorGDBRemote::AllThreads;
16
17 StringExtractorGDBRemote::ResponseType
GetResponseType() const18 StringExtractorGDBRemote::GetResponseType() const {
19 if (m_packet.empty())
20 return eUnsupported;
21
22 switch (m_packet[0]) {
23 case 'E':
24 if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) {
25 if (m_packet.size() == 3)
26 return eError;
27 llvm::StringRef packet_ref(m_packet);
28 if (packet_ref[3] == ';') {
29 auto err_string = packet_ref.substr(4);
30 for (auto e : err_string)
31 if (!isxdigit(e))
32 return eResponse;
33 return eError;
34 }
35 }
36 break;
37
38 case 'O':
39 if (m_packet.size() == 2 && m_packet[1] == 'K')
40 return eOK;
41 break;
42
43 case '+':
44 if (m_packet.size() == 1)
45 return eAck;
46 break;
47
48 case '-':
49 if (m_packet.size() == 1)
50 return eNack;
51 break;
52 }
53 return eResponse;
54 }
55
56 StringExtractorGDBRemote::ServerPacketType
GetServerPacketType() const57 StringExtractorGDBRemote::GetServerPacketType() const {
58 #define PACKET_MATCHES(s) \
59 ((packet_size == (sizeof(s) - 1)) && (strcmp((packet_cstr), (s)) == 0))
60 #define PACKET_STARTS_WITH(s) \
61 ((packet_size >= (sizeof(s) - 1)) && \
62 ::strncmp(packet_cstr, s, (sizeof(s) - 1)) == 0)
63
64 // Empty is not a supported packet...
65 if (m_packet.empty())
66 return eServerPacketType_invalid;
67
68 const size_t packet_size = m_packet.size();
69 const char *packet_cstr = m_packet.c_str();
70 switch (m_packet[0]) {
71
72 case '%':
73 return eServerPacketType_notify;
74
75 case '\x03':
76 if (packet_size == 1)
77 return eServerPacketType_interrupt;
78 break;
79
80 case '-':
81 if (packet_size == 1)
82 return eServerPacketType_nack;
83 break;
84
85 case '+':
86 if (packet_size == 1)
87 return eServerPacketType_ack;
88 break;
89
90 case 'A':
91 return eServerPacketType_A;
92
93 case 'Q':
94
95 switch (packet_cstr[1]) {
96 case 'E':
97 if (PACKET_STARTS_WITH("QEnvironment:"))
98 return eServerPacketType_QEnvironment;
99 if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
100 return eServerPacketType_QEnvironmentHexEncoded;
101 if (PACKET_STARTS_WITH("QEnableErrorStrings"))
102 return eServerPacketType_QEnableErrorStrings;
103 break;
104
105 case 'P':
106 if (PACKET_STARTS_WITH("QPassSignals:"))
107 return eServerPacketType_QPassSignals;
108 break;
109
110 case 'S':
111 if (PACKET_MATCHES("QStartNoAckMode"))
112 return eServerPacketType_QStartNoAckMode;
113 if (PACKET_STARTS_WITH("QSaveRegisterState"))
114 return eServerPacketType_QSaveRegisterState;
115 if (PACKET_STARTS_WITH("QSetDisableASLR:"))
116 return eServerPacketType_QSetDisableASLR;
117 if (PACKET_STARTS_WITH("QSetDetachOnError:"))
118 return eServerPacketType_QSetDetachOnError;
119 if (PACKET_STARTS_WITH("QSetSTDIN:"))
120 return eServerPacketType_QSetSTDIN;
121 if (PACKET_STARTS_WITH("QSetSTDOUT:"))
122 return eServerPacketType_QSetSTDOUT;
123 if (PACKET_STARTS_WITH("QSetSTDERR:"))
124 return eServerPacketType_QSetSTDERR;
125 if (PACKET_STARTS_WITH("QSetWorkingDir:"))
126 return eServerPacketType_QSetWorkingDir;
127 if (PACKET_STARTS_WITH("QSetLogging:"))
128 return eServerPacketType_QSetLogging;
129 if (PACKET_STARTS_WITH("QSetIgnoredExceptions"))
130 return eServerPacketType_QSetIgnoredExceptions;
131 if (PACKET_STARTS_WITH("QSetMaxPacketSize:"))
132 return eServerPacketType_QSetMaxPacketSize;
133 if (PACKET_STARTS_WITH("QSetMaxPayloadSize:"))
134 return eServerPacketType_QSetMaxPayloadSize;
135 if (PACKET_STARTS_WITH("QSetEnableAsyncProfiling;"))
136 return eServerPacketType_QSetEnableAsyncProfiling;
137 if (PACKET_STARTS_WITH("QSyncThreadState:"))
138 return eServerPacketType_QSyncThreadState;
139 break;
140
141 case 'L':
142 if (PACKET_STARTS_WITH("QLaunchArch:"))
143 return eServerPacketType_QLaunchArch;
144 if (PACKET_MATCHES("QListThreadsInStopReply"))
145 return eServerPacketType_QListThreadsInStopReply;
146 break;
147
148 case 'M':
149 if (PACKET_STARTS_WITH("QMemTags"))
150 return eServerPacketType_QMemTags;
151 break;
152
153 case 'N':
154 if (PACKET_STARTS_WITH("QNonStop:"))
155 return eServerPacketType_QNonStop;
156 break;
157
158 case 'R':
159 if (PACKET_STARTS_WITH("QRestoreRegisterState:"))
160 return eServerPacketType_QRestoreRegisterState;
161 break;
162
163 case 'T':
164 if (PACKET_MATCHES("QThreadSuffixSupported"))
165 return eServerPacketType_QThreadSuffixSupported;
166 break;
167 }
168 break;
169
170 case 'q':
171 switch (packet_cstr[1]) {
172 case 's':
173 if (PACKET_MATCHES("qsProcessInfo"))
174 return eServerPacketType_qsProcessInfo;
175 if (PACKET_MATCHES("qsThreadInfo"))
176 return eServerPacketType_qsThreadInfo;
177 break;
178
179 case 'f':
180 if (PACKET_STARTS_WITH("qfProcessInfo"))
181 return eServerPacketType_qfProcessInfo;
182 if (PACKET_STARTS_WITH("qfThreadInfo"))
183 return eServerPacketType_qfThreadInfo;
184 break;
185
186 case 'C':
187 if (packet_size == 2)
188 return eServerPacketType_qC;
189 break;
190
191 case 'E':
192 if (PACKET_STARTS_WITH("qEcho:"))
193 return eServerPacketType_qEcho;
194 break;
195
196 case 'F':
197 if (PACKET_STARTS_WITH("qFileLoadAddress:"))
198 return eServerPacketType_qFileLoadAddress;
199 break;
200
201 case 'G':
202 if (PACKET_STARTS_WITH("qGroupName:"))
203 return eServerPacketType_qGroupName;
204 if (PACKET_MATCHES("qGetWorkingDir"))
205 return eServerPacketType_qGetWorkingDir;
206 if (PACKET_MATCHES("qGetPid"))
207 return eServerPacketType_qGetPid;
208 if (PACKET_STARTS_WITH("qGetProfileData;"))
209 return eServerPacketType_qGetProfileData;
210 if (PACKET_MATCHES("qGDBServerVersion"))
211 return eServerPacketType_qGDBServerVersion;
212 break;
213
214 case 'H':
215 if (PACKET_MATCHES("qHostInfo"))
216 return eServerPacketType_qHostInfo;
217 break;
218
219 case 'K':
220 if (PACKET_STARTS_WITH("qKillSpawnedProcess"))
221 return eServerPacketType_qKillSpawnedProcess;
222 break;
223
224 case 'L':
225 if (PACKET_STARTS_WITH("qLaunchGDBServer"))
226 return eServerPacketType_qLaunchGDBServer;
227 if (PACKET_MATCHES("qLaunchSuccess"))
228 return eServerPacketType_qLaunchSuccess;
229 break;
230
231 case 'M':
232 if (PACKET_STARTS_WITH("qMemoryRegionInfo:"))
233 return eServerPacketType_qMemoryRegionInfo;
234 if (PACKET_MATCHES("qMemoryRegionInfo"))
235 return eServerPacketType_qMemoryRegionInfoSupported;
236 if (PACKET_STARTS_WITH("qModuleInfo:"))
237 return eServerPacketType_qModuleInfo;
238 if (PACKET_STARTS_WITH("qMemTags:"))
239 return eServerPacketType_qMemTags;
240 break;
241
242 case 'P':
243 if (PACKET_STARTS_WITH("qProcessInfoPID:"))
244 return eServerPacketType_qProcessInfoPID;
245 if (PACKET_STARTS_WITH("qPlatform_shell:"))
246 return eServerPacketType_qPlatform_shell;
247 if (PACKET_STARTS_WITH("qPlatform_mkdir:"))
248 return eServerPacketType_qPlatform_mkdir;
249 if (PACKET_STARTS_WITH("qPlatform_chmod:"))
250 return eServerPacketType_qPlatform_chmod;
251 if (PACKET_MATCHES("qProcessInfo"))
252 return eServerPacketType_qProcessInfo;
253 if (PACKET_STARTS_WITH("qPathComplete:"))
254 return eServerPacketType_qPathComplete;
255 break;
256
257 case 'Q':
258 if (PACKET_MATCHES("qQueryGDBServer"))
259 return eServerPacketType_qQueryGDBServer;
260 break;
261
262 case 'R':
263 if (PACKET_STARTS_WITH("qRcmd,"))
264 return eServerPacketType_qRcmd;
265 if (PACKET_STARTS_WITH("qRegisterInfo"))
266 return eServerPacketType_qRegisterInfo;
267 break;
268
269 case 'S':
270 if (PACKET_STARTS_WITH("qSaveCore"))
271 return eServerPacketType_qLLDBSaveCore;
272 if (PACKET_STARTS_WITH("qSpeedTest:"))
273 return eServerPacketType_qSpeedTest;
274 if (PACKET_MATCHES("qShlibInfoAddr"))
275 return eServerPacketType_qShlibInfoAddr;
276 if (PACKET_MATCHES("qStepPacketSupported"))
277 return eServerPacketType_qStepPacketSupported;
278 if (PACKET_STARTS_WITH("qSupported"))
279 return eServerPacketType_qSupported;
280 if (PACKET_MATCHES("qSyncThreadStateSupported"))
281 return eServerPacketType_qSyncThreadStateSupported;
282 break;
283
284 case 'T':
285 if (PACKET_STARTS_WITH("qThreadExtraInfo,"))
286 return eServerPacketType_qThreadExtraInfo;
287 if (PACKET_STARTS_WITH("qThreadStopInfo"))
288 return eServerPacketType_qThreadStopInfo;
289 break;
290
291 case 'U':
292 if (PACKET_STARTS_WITH("qUserName:"))
293 return eServerPacketType_qUserName;
294 break;
295
296 case 'V':
297 if (PACKET_MATCHES("qVAttachOrWaitSupported"))
298 return eServerPacketType_qVAttachOrWaitSupported;
299 break;
300
301 case 'W':
302 if (PACKET_STARTS_WITH("qWatchpointSupportInfo:"))
303 return eServerPacketType_qWatchpointSupportInfo;
304 if (PACKET_MATCHES("qWatchpointSupportInfo"))
305 return eServerPacketType_qWatchpointSupportInfoSupported;
306 break;
307
308 case 'X':
309 if (PACKET_STARTS_WITH("qXfer:"))
310 return eServerPacketType_qXfer;
311 break;
312 }
313 break;
314
315 case 'j':
316 if (PACKET_STARTS_WITH("jModulesInfo:"))
317 return eServerPacketType_jModulesInfo;
318 if (PACKET_MATCHES("jSignalsInfo"))
319 return eServerPacketType_jSignalsInfo;
320 if (PACKET_MATCHES("jThreadsInfo"))
321 return eServerPacketType_jThreadsInfo;
322
323 if (PACKET_MATCHES("jLLDBTraceSupported"))
324 return eServerPacketType_jLLDBTraceSupported;
325 if (PACKET_STARTS_WITH("jLLDBTraceStop:"))
326 return eServerPacketType_jLLDBTraceStop;
327 if (PACKET_STARTS_WITH("jLLDBTraceStart:"))
328 return eServerPacketType_jLLDBTraceStart;
329 if (PACKET_STARTS_WITH("jLLDBTraceGetState:"))
330 return eServerPacketType_jLLDBTraceGetState;
331 if (PACKET_STARTS_WITH("jLLDBTraceGetBinaryData:"))
332 return eServerPacketType_jLLDBTraceGetBinaryData;
333 break;
334
335 case 'v':
336 if (PACKET_STARTS_WITH("vFile:")) {
337 if (PACKET_STARTS_WITH("vFile:open:"))
338 return eServerPacketType_vFile_open;
339 else if (PACKET_STARTS_WITH("vFile:close:"))
340 return eServerPacketType_vFile_close;
341 else if (PACKET_STARTS_WITH("vFile:pread"))
342 return eServerPacketType_vFile_pread;
343 else if (PACKET_STARTS_WITH("vFile:pwrite"))
344 return eServerPacketType_vFile_pwrite;
345 else if (PACKET_STARTS_WITH("vFile:size"))
346 return eServerPacketType_vFile_size;
347 else if (PACKET_STARTS_WITH("vFile:exists"))
348 return eServerPacketType_vFile_exists;
349 else if (PACKET_STARTS_WITH("vFile:fstat"))
350 return eServerPacketType_vFile_fstat;
351 else if (PACKET_STARTS_WITH("vFile:stat"))
352 return eServerPacketType_vFile_stat;
353 else if (PACKET_STARTS_WITH("vFile:mode"))
354 return eServerPacketType_vFile_mode;
355 else if (PACKET_STARTS_WITH("vFile:MD5"))
356 return eServerPacketType_vFile_md5;
357 else if (PACKET_STARTS_WITH("vFile:symlink"))
358 return eServerPacketType_vFile_symlink;
359 else if (PACKET_STARTS_WITH("vFile:unlink"))
360 return eServerPacketType_vFile_unlink;
361
362 } else {
363 if (PACKET_STARTS_WITH("vAttach;"))
364 return eServerPacketType_vAttach;
365 if (PACKET_STARTS_WITH("vAttachWait;"))
366 return eServerPacketType_vAttachWait;
367 if (PACKET_STARTS_WITH("vAttachOrWait;"))
368 return eServerPacketType_vAttachOrWait;
369 if (PACKET_STARTS_WITH("vAttachName;"))
370 return eServerPacketType_vAttachName;
371 if (PACKET_STARTS_WITH("vCont;"))
372 return eServerPacketType_vCont;
373 if (PACKET_MATCHES("vCont?"))
374 return eServerPacketType_vCont_actions;
375 if (PACKET_STARTS_WITH("vKill;"))
376 return eServerPacketType_vKill;
377 if (PACKET_STARTS_WITH("vRun;"))
378 return eServerPacketType_vRun;
379 if (PACKET_MATCHES("vStopped"))
380 return eServerPacketType_vStopped;
381 if (PACKET_MATCHES("vCtrlC"))
382 return eServerPacketType_vCtrlC;
383 if (PACKET_MATCHES("vStdio"))
384 return eServerPacketType_vStdio;
385 break;
386
387 }
388 break;
389 case '_':
390 switch (packet_cstr[1]) {
391 case 'M':
392 return eServerPacketType__M;
393
394 case 'm':
395 return eServerPacketType__m;
396 }
397 break;
398
399 case '?':
400 if (packet_size == 1)
401 return eServerPacketType_stop_reason;
402 break;
403
404 case 'c':
405 return eServerPacketType_c;
406
407 case 'C':
408 return eServerPacketType_C;
409
410 case 'D':
411 return eServerPacketType_D;
412
413 case 'g':
414 return eServerPacketType_g;
415
416 case 'G':
417 return eServerPacketType_G;
418
419 case 'H':
420 return eServerPacketType_H;
421
422 case 'I':
423 return eServerPacketType_I;
424
425 case 'k':
426 if (packet_size == 1)
427 return eServerPacketType_k;
428 break;
429
430 case 'm':
431 return eServerPacketType_m;
432
433 case 'M':
434 return eServerPacketType_M;
435
436 case 'p':
437 return eServerPacketType_p;
438
439 case 'P':
440 return eServerPacketType_P;
441
442 case 's':
443 if (packet_size == 1)
444 return eServerPacketType_s;
445 break;
446
447 case 'S':
448 return eServerPacketType_S;
449
450 case 'x':
451 return eServerPacketType_x;
452
453 case 'X':
454 return eServerPacketType_X;
455
456 case 'T':
457 return eServerPacketType_T;
458
459 case 'z':
460 if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
461 return eServerPacketType_z;
462 break;
463
464 case 'Z':
465 if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
466 return eServerPacketType_Z;
467 break;
468 }
469 return eServerPacketType_unimplemented;
470 }
471
IsOKResponse() const472 bool StringExtractorGDBRemote::IsOKResponse() const {
473 return GetResponseType() == eOK;
474 }
475
IsUnsupportedResponse() const476 bool StringExtractorGDBRemote::IsUnsupportedResponse() const {
477 return GetResponseType() == eUnsupported;
478 }
479
IsNormalResponse() const480 bool StringExtractorGDBRemote::IsNormalResponse() const {
481 return GetResponseType() == eResponse;
482 }
483
IsErrorResponse() const484 bool StringExtractorGDBRemote::IsErrorResponse() const {
485 return GetResponseType() == eError && isxdigit(m_packet[1]) &&
486 isxdigit(m_packet[2]);
487 }
488
GetError()489 uint8_t StringExtractorGDBRemote::GetError() {
490 if (GetResponseType() == eError) {
491 SetFilePos(1);
492 return GetHexU8(255);
493 }
494 return 0;
495 }
496
GetStatus()497 lldb_private::Status StringExtractorGDBRemote::GetStatus() {
498 lldb_private::Status error;
499 if (GetResponseType() == eError) {
500 SetFilePos(1);
501 uint8_t errc = GetHexU8(255);
502 error.SetError(errc, lldb::eErrorTypeGeneric);
503
504 error.SetErrorStringWithFormat("Error %u", errc);
505 std::string error_messg;
506 if (GetChar() == ';') {
507 GetHexByteString(error_messg);
508 error.SetErrorString(error_messg);
509 }
510 }
511 return error;
512 }
513
GetEscapedBinaryData(std::string & str)514 size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
515 // Just get the data bytes in the string as
516 // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
517 // characters. If any 0x7d characters are left in the packet, then they are
518 // supposed to be there...
519 str.clear();
520 const size_t bytes_left = GetBytesLeft();
521 if (bytes_left > 0) {
522 str.assign(m_packet, m_index, bytes_left);
523 m_index += bytes_left;
524 }
525 return str.size();
526 }
527
528 static bool
OKErrorNotSupportedResponseValidator(void *,const StringExtractorGDBRemote & response)529 OKErrorNotSupportedResponseValidator(void *,
530 const StringExtractorGDBRemote &response) {
531 switch (response.GetResponseType()) {
532 case StringExtractorGDBRemote::eOK:
533 case StringExtractorGDBRemote::eError:
534 case StringExtractorGDBRemote::eUnsupported:
535 return true;
536
537 case StringExtractorGDBRemote::eAck:
538 case StringExtractorGDBRemote::eNack:
539 case StringExtractorGDBRemote::eResponse:
540 break;
541 }
542 return false;
543 }
544
JSONResponseValidator(void *,const StringExtractorGDBRemote & response)545 static bool JSONResponseValidator(void *,
546 const StringExtractorGDBRemote &response) {
547 switch (response.GetResponseType()) {
548 case StringExtractorGDBRemote::eUnsupported:
549 case StringExtractorGDBRemote::eError:
550 return true; // Accept unsupported or EXX as valid responses
551
552 case StringExtractorGDBRemote::eOK:
553 case StringExtractorGDBRemote::eAck:
554 case StringExtractorGDBRemote::eNack:
555 break;
556
557 case StringExtractorGDBRemote::eResponse:
558 // JSON that is returned in from JSON query packets is currently always
559 // either a dictionary which starts with a '{', or an array which starts
560 // with a '['. This is a quick validator to just make sure the response
561 // could be valid JSON without having to validate all of the
562 // JSON content.
563 switch (response.GetStringRef()[0]) {
564 case '{':
565 return true;
566 case '[':
567 return true;
568 default:
569 break;
570 }
571 break;
572 }
573 return false;
574 }
575
576 static bool
ASCIIHexBytesResponseValidator(void *,const StringExtractorGDBRemote & response)577 ASCIIHexBytesResponseValidator(void *,
578 const StringExtractorGDBRemote &response) {
579 switch (response.GetResponseType()) {
580 case StringExtractorGDBRemote::eUnsupported:
581 case StringExtractorGDBRemote::eError:
582 return true; // Accept unsupported or EXX as valid responses
583
584 case StringExtractorGDBRemote::eOK:
585 case StringExtractorGDBRemote::eAck:
586 case StringExtractorGDBRemote::eNack:
587 break;
588
589 case StringExtractorGDBRemote::eResponse: {
590 uint32_t valid_count = 0;
591 for (const char ch : response.GetStringRef()) {
592 if (!isxdigit(ch)) {
593 return false;
594 }
595 if (++valid_count >= 16)
596 break; // Don't validate all the characters in case the packet is very
597 // large
598 }
599 return true;
600 } break;
601 }
602 return false;
603 }
604
CopyResponseValidator(const StringExtractorGDBRemote & rhs)605 void StringExtractorGDBRemote::CopyResponseValidator(
606 const StringExtractorGDBRemote &rhs) {
607 m_validator = rhs.m_validator;
608 m_validator_baton = rhs.m_validator_baton;
609 }
610
SetResponseValidator(ResponseValidatorCallback callback,void * baton)611 void StringExtractorGDBRemote::SetResponseValidator(
612 ResponseValidatorCallback callback, void *baton) {
613 m_validator = callback;
614 m_validator_baton = baton;
615 }
616
SetResponseValidatorToOKErrorNotSupported()617 void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() {
618 m_validator = OKErrorNotSupportedResponseValidator;
619 m_validator_baton = nullptr;
620 }
621
SetResponseValidatorToASCIIHexBytes()622 void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() {
623 m_validator = ASCIIHexBytesResponseValidator;
624 m_validator_baton = nullptr;
625 }
626
SetResponseValidatorToJSON()627 void StringExtractorGDBRemote::SetResponseValidatorToJSON() {
628 m_validator = JSONResponseValidator;
629 m_validator_baton = nullptr;
630 }
631
ValidateResponse() const632 bool StringExtractorGDBRemote::ValidateResponse() const {
633 // If we have a validator callback, try to validate the callback
634 if (m_validator)
635 return m_validator(m_validator_baton, *this);
636 else
637 return true; // No validator, so response is valid
638 }
639
640 llvm::Optional<std::pair<lldb::pid_t, lldb::tid_t>>
GetPidTid(lldb::pid_t default_pid)641 StringExtractorGDBRemote::GetPidTid(lldb::pid_t default_pid) {
642 llvm::StringRef view = llvm::StringRef(m_packet).substr(m_index);
643 size_t initial_length = view.size();
644 lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
645 lldb::tid_t tid;
646
647 if (view.consume_front("p")) {
648 // process identifier
649 if (view.consume_front("-1")) {
650 // -1 is a special case
651 pid = AllProcesses;
652 } else if (view.consumeInteger(16, pid) || pid == 0) {
653 // not a valid hex integer OR unsupported pid 0
654 m_index = UINT64_MAX;
655 return llvm::None;
656 }
657
658 // "." must follow if we expect TID too; otherwise, we assume -1
659 if (!view.consume_front(".")) {
660 // update m_index
661 m_index += initial_length - view.size();
662
663 return {{pid, AllThreads}};
664 }
665 }
666
667 // thread identifier
668 if (view.consume_front("-1")) {
669 // -1 is a special case
670 tid = AllThreads;
671 } else if (view.consumeInteger(16, tid) || tid == 0 || pid == AllProcesses) {
672 // not a valid hex integer OR tid 0 OR pid -1 + a specific tid
673 m_index = UINT64_MAX;
674 return llvm::None;
675 }
676
677 // update m_index
678 m_index += initial_length - view.size();
679
680 return {{pid != LLDB_INVALID_PROCESS_ID ? pid : default_pid, tid}};
681 }
682