15ffd83dbSDimitry Andric //===-- StringExtractorGDBRemote.cpp --------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
100b57cec5SDimitry Andric
11*5f7ddb14SDimitry Andric #include <cctype>
12*5f7ddb14SDimitry Andric #include <cstring>
13*5f7ddb14SDimitry Andric
14*5f7ddb14SDimitry Andric constexpr lldb::pid_t StringExtractorGDBRemote::AllProcesses;
15*5f7ddb14SDimitry Andric constexpr lldb::tid_t StringExtractorGDBRemote::AllThreads;
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric StringExtractorGDBRemote::ResponseType
GetResponseType() const180b57cec5SDimitry Andric StringExtractorGDBRemote::GetResponseType() const {
190b57cec5SDimitry Andric if (m_packet.empty())
200b57cec5SDimitry Andric return eUnsupported;
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric switch (m_packet[0]) {
230b57cec5SDimitry Andric case 'E':
240b57cec5SDimitry Andric if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) {
250b57cec5SDimitry Andric if (m_packet.size() == 3)
260b57cec5SDimitry Andric return eError;
270b57cec5SDimitry Andric llvm::StringRef packet_ref(m_packet);
280b57cec5SDimitry Andric if (packet_ref[3] == ';') {
290b57cec5SDimitry Andric auto err_string = packet_ref.substr(4);
300b57cec5SDimitry Andric for (auto e : err_string)
310b57cec5SDimitry Andric if (!isxdigit(e))
320b57cec5SDimitry Andric return eResponse;
330b57cec5SDimitry Andric return eError;
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric break;
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric case 'O':
390b57cec5SDimitry Andric if (m_packet.size() == 2 && m_packet[1] == 'K')
400b57cec5SDimitry Andric return eOK;
410b57cec5SDimitry Andric break;
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric case '+':
440b57cec5SDimitry Andric if (m_packet.size() == 1)
450b57cec5SDimitry Andric return eAck;
460b57cec5SDimitry Andric break;
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric case '-':
490b57cec5SDimitry Andric if (m_packet.size() == 1)
500b57cec5SDimitry Andric return eNack;
510b57cec5SDimitry Andric break;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric return eResponse;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric StringExtractorGDBRemote::ServerPacketType
GetServerPacketType() const570b57cec5SDimitry Andric StringExtractorGDBRemote::GetServerPacketType() const {
580b57cec5SDimitry Andric #define PACKET_MATCHES(s) \
590b57cec5SDimitry Andric ((packet_size == (sizeof(s) - 1)) && (strcmp((packet_cstr), (s)) == 0))
600b57cec5SDimitry Andric #define PACKET_STARTS_WITH(s) \
610b57cec5SDimitry Andric ((packet_size >= (sizeof(s) - 1)) && \
620b57cec5SDimitry Andric ::strncmp(packet_cstr, s, (sizeof(s) - 1)) == 0)
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric // Empty is not a supported packet...
650b57cec5SDimitry Andric if (m_packet.empty())
660b57cec5SDimitry Andric return eServerPacketType_invalid;
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric const size_t packet_size = m_packet.size();
690b57cec5SDimitry Andric const char *packet_cstr = m_packet.c_str();
700b57cec5SDimitry Andric switch (m_packet[0]) {
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric case '%':
730b57cec5SDimitry Andric return eServerPacketType_notify;
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric case '\x03':
760b57cec5SDimitry Andric if (packet_size == 1)
770b57cec5SDimitry Andric return eServerPacketType_interrupt;
780b57cec5SDimitry Andric break;
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric case '-':
810b57cec5SDimitry Andric if (packet_size == 1)
820b57cec5SDimitry Andric return eServerPacketType_nack;
830b57cec5SDimitry Andric break;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric case '+':
860b57cec5SDimitry Andric if (packet_size == 1)
870b57cec5SDimitry Andric return eServerPacketType_ack;
880b57cec5SDimitry Andric break;
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric case 'A':
910b57cec5SDimitry Andric return eServerPacketType_A;
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric case 'Q':
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric switch (packet_cstr[1]) {
960b57cec5SDimitry Andric case 'E':
970b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QEnvironment:"))
980b57cec5SDimitry Andric return eServerPacketType_QEnvironment;
990b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
1000b57cec5SDimitry Andric return eServerPacketType_QEnvironmentHexEncoded;
1010b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QEnableErrorStrings"))
1020b57cec5SDimitry Andric return eServerPacketType_QEnableErrorStrings;
1030b57cec5SDimitry Andric break;
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric case 'P':
1060b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QPassSignals:"))
1070b57cec5SDimitry Andric return eServerPacketType_QPassSignals;
1080b57cec5SDimitry Andric break;
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric case 'S':
1110b57cec5SDimitry Andric if (PACKET_MATCHES("QStartNoAckMode"))
1120b57cec5SDimitry Andric return eServerPacketType_QStartNoAckMode;
1130b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSaveRegisterState"))
1140b57cec5SDimitry Andric return eServerPacketType_QSaveRegisterState;
1150b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetDisableASLR:"))
1160b57cec5SDimitry Andric return eServerPacketType_QSetDisableASLR;
1170b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetDetachOnError:"))
1180b57cec5SDimitry Andric return eServerPacketType_QSetDetachOnError;
1190b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetSTDIN:"))
1200b57cec5SDimitry Andric return eServerPacketType_QSetSTDIN;
1210b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetSTDOUT:"))
1220b57cec5SDimitry Andric return eServerPacketType_QSetSTDOUT;
1230b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetSTDERR:"))
1240b57cec5SDimitry Andric return eServerPacketType_QSetSTDERR;
1250b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetWorkingDir:"))
1260b57cec5SDimitry Andric return eServerPacketType_QSetWorkingDir;
1270b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetLogging:"))
1280b57cec5SDimitry Andric return eServerPacketType_QSetLogging;
1290b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetMaxPacketSize:"))
1300b57cec5SDimitry Andric return eServerPacketType_QSetMaxPacketSize;
1310b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetMaxPayloadSize:"))
1320b57cec5SDimitry Andric return eServerPacketType_QSetMaxPayloadSize;
1330b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSetEnableAsyncProfiling;"))
1340b57cec5SDimitry Andric return eServerPacketType_QSetEnableAsyncProfiling;
1350b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QSyncThreadState:"))
1360b57cec5SDimitry Andric return eServerPacketType_QSyncThreadState;
1370b57cec5SDimitry Andric break;
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric case 'L':
1400b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QLaunchArch:"))
1410b57cec5SDimitry Andric return eServerPacketType_QLaunchArch;
1420b57cec5SDimitry Andric if (PACKET_MATCHES("QListThreadsInStopReply"))
1430b57cec5SDimitry Andric return eServerPacketType_QListThreadsInStopReply;
1440b57cec5SDimitry Andric break;
1450b57cec5SDimitry Andric
146*5f7ddb14SDimitry Andric case 'M':
147*5f7ddb14SDimitry Andric if (PACKET_STARTS_WITH("QMemTags"))
148*5f7ddb14SDimitry Andric return eServerPacketType_QMemTags;
149*5f7ddb14SDimitry Andric break;
150*5f7ddb14SDimitry Andric
1510b57cec5SDimitry Andric case 'R':
1520b57cec5SDimitry Andric if (PACKET_STARTS_WITH("QRestoreRegisterState:"))
1530b57cec5SDimitry Andric return eServerPacketType_QRestoreRegisterState;
1540b57cec5SDimitry Andric break;
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric case 'T':
1570b57cec5SDimitry Andric if (PACKET_MATCHES("QThreadSuffixSupported"))
1580b57cec5SDimitry Andric return eServerPacketType_QThreadSuffixSupported;
1590b57cec5SDimitry Andric break;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric break;
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric case 'q':
1640b57cec5SDimitry Andric switch (packet_cstr[1]) {
1650b57cec5SDimitry Andric case 's':
1660b57cec5SDimitry Andric if (PACKET_MATCHES("qsProcessInfo"))
1670b57cec5SDimitry Andric return eServerPacketType_qsProcessInfo;
1680b57cec5SDimitry Andric if (PACKET_MATCHES("qsThreadInfo"))
1690b57cec5SDimitry Andric return eServerPacketType_qsThreadInfo;
1700b57cec5SDimitry Andric break;
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric case 'f':
1730b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qfProcessInfo"))
1740b57cec5SDimitry Andric return eServerPacketType_qfProcessInfo;
1750b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qfThreadInfo"))
1760b57cec5SDimitry Andric return eServerPacketType_qfThreadInfo;
1770b57cec5SDimitry Andric break;
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric case 'C':
1800b57cec5SDimitry Andric if (packet_size == 2)
1810b57cec5SDimitry Andric return eServerPacketType_qC;
1820b57cec5SDimitry Andric break;
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric case 'E':
1850b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qEcho:"))
1860b57cec5SDimitry Andric return eServerPacketType_qEcho;
1870b57cec5SDimitry Andric break;
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric case 'F':
1900b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qFileLoadAddress:"))
1910b57cec5SDimitry Andric return eServerPacketType_qFileLoadAddress;
1920b57cec5SDimitry Andric break;
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric case 'G':
1950b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qGroupName:"))
1960b57cec5SDimitry Andric return eServerPacketType_qGroupName;
1970b57cec5SDimitry Andric if (PACKET_MATCHES("qGetWorkingDir"))
1980b57cec5SDimitry Andric return eServerPacketType_qGetWorkingDir;
1990b57cec5SDimitry Andric if (PACKET_MATCHES("qGetPid"))
2000b57cec5SDimitry Andric return eServerPacketType_qGetPid;
2010b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qGetProfileData;"))
2020b57cec5SDimitry Andric return eServerPacketType_qGetProfileData;
2030b57cec5SDimitry Andric if (PACKET_MATCHES("qGDBServerVersion"))
2040b57cec5SDimitry Andric return eServerPacketType_qGDBServerVersion;
2050b57cec5SDimitry Andric break;
2060b57cec5SDimitry Andric
2070b57cec5SDimitry Andric case 'H':
2080b57cec5SDimitry Andric if (PACKET_MATCHES("qHostInfo"))
2090b57cec5SDimitry Andric return eServerPacketType_qHostInfo;
2100b57cec5SDimitry Andric break;
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric case 'K':
2130b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qKillSpawnedProcess"))
2140b57cec5SDimitry Andric return eServerPacketType_qKillSpawnedProcess;
2150b57cec5SDimitry Andric break;
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric case 'L':
2180b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qLaunchGDBServer"))
2190b57cec5SDimitry Andric return eServerPacketType_qLaunchGDBServer;
2200b57cec5SDimitry Andric if (PACKET_MATCHES("qLaunchSuccess"))
2210b57cec5SDimitry Andric return eServerPacketType_qLaunchSuccess;
2220b57cec5SDimitry Andric break;
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric case 'M':
2250b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qMemoryRegionInfo:"))
2260b57cec5SDimitry Andric return eServerPacketType_qMemoryRegionInfo;
2270b57cec5SDimitry Andric if (PACKET_MATCHES("qMemoryRegionInfo"))
2280b57cec5SDimitry Andric return eServerPacketType_qMemoryRegionInfoSupported;
2290b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qModuleInfo:"))
2300b57cec5SDimitry Andric return eServerPacketType_qModuleInfo;
231*5f7ddb14SDimitry Andric if (PACKET_STARTS_WITH("qMemTags:"))
232*5f7ddb14SDimitry Andric return eServerPacketType_qMemTags;
2330b57cec5SDimitry Andric break;
2340b57cec5SDimitry Andric
2350b57cec5SDimitry Andric case 'P':
2360b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qProcessInfoPID:"))
2370b57cec5SDimitry Andric return eServerPacketType_qProcessInfoPID;
2380b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qPlatform_shell:"))
2390b57cec5SDimitry Andric return eServerPacketType_qPlatform_shell;
2400b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qPlatform_mkdir:"))
2410b57cec5SDimitry Andric return eServerPacketType_qPlatform_mkdir;
2420b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qPlatform_chmod:"))
2430b57cec5SDimitry Andric return eServerPacketType_qPlatform_chmod;
2440b57cec5SDimitry Andric if (PACKET_MATCHES("qProcessInfo"))
2450b57cec5SDimitry Andric return eServerPacketType_qProcessInfo;
246af732203SDimitry Andric if (PACKET_STARTS_WITH("qPathComplete:"))
247af732203SDimitry Andric return eServerPacketType_qPathComplete;
2480b57cec5SDimitry Andric break;
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric case 'Q':
2510b57cec5SDimitry Andric if (PACKET_MATCHES("qQueryGDBServer"))
2520b57cec5SDimitry Andric return eServerPacketType_qQueryGDBServer;
2530b57cec5SDimitry Andric break;
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric case 'R':
2560b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qRcmd,"))
2570b57cec5SDimitry Andric return eServerPacketType_qRcmd;
2580b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qRegisterInfo"))
2590b57cec5SDimitry Andric return eServerPacketType_qRegisterInfo;
2600b57cec5SDimitry Andric break;
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric case 'S':
2630b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qSpeedTest:"))
2640b57cec5SDimitry Andric return eServerPacketType_qSpeedTest;
2650b57cec5SDimitry Andric if (PACKET_MATCHES("qShlibInfoAddr"))
2660b57cec5SDimitry Andric return eServerPacketType_qShlibInfoAddr;
2670b57cec5SDimitry Andric if (PACKET_MATCHES("qStepPacketSupported"))
2680b57cec5SDimitry Andric return eServerPacketType_qStepPacketSupported;
2690b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qSupported"))
2700b57cec5SDimitry Andric return eServerPacketType_qSupported;
2710b57cec5SDimitry Andric if (PACKET_MATCHES("qSyncThreadStateSupported"))
2720b57cec5SDimitry Andric return eServerPacketType_qSyncThreadStateSupported;
2730b57cec5SDimitry Andric break;
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andric case 'T':
2760b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qThreadExtraInfo,"))
2770b57cec5SDimitry Andric return eServerPacketType_qThreadExtraInfo;
2780b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qThreadStopInfo"))
2790b57cec5SDimitry Andric return eServerPacketType_qThreadStopInfo;
2800b57cec5SDimitry Andric break;
2810b57cec5SDimitry Andric
2820b57cec5SDimitry Andric case 'U':
2830b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qUserName:"))
2840b57cec5SDimitry Andric return eServerPacketType_qUserName;
2850b57cec5SDimitry Andric break;
2860b57cec5SDimitry Andric
2870b57cec5SDimitry Andric case 'V':
2880b57cec5SDimitry Andric if (PACKET_MATCHES("qVAttachOrWaitSupported"))
2890b57cec5SDimitry Andric return eServerPacketType_qVAttachOrWaitSupported;
2900b57cec5SDimitry Andric break;
2910b57cec5SDimitry Andric
2920b57cec5SDimitry Andric case 'W':
2930b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qWatchpointSupportInfo:"))
2940b57cec5SDimitry Andric return eServerPacketType_qWatchpointSupportInfo;
2950b57cec5SDimitry Andric if (PACKET_MATCHES("qWatchpointSupportInfo"))
2960b57cec5SDimitry Andric return eServerPacketType_qWatchpointSupportInfoSupported;
2970b57cec5SDimitry Andric break;
2980b57cec5SDimitry Andric
2990b57cec5SDimitry Andric case 'X':
3000b57cec5SDimitry Andric if (PACKET_STARTS_WITH("qXfer:"))
3010b57cec5SDimitry Andric return eServerPacketType_qXfer;
3020b57cec5SDimitry Andric break;
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric break;
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric case 'j':
3070b57cec5SDimitry Andric if (PACKET_STARTS_WITH("jModulesInfo:"))
3080b57cec5SDimitry Andric return eServerPacketType_jModulesInfo;
3090b57cec5SDimitry Andric if (PACKET_MATCHES("jSignalsInfo"))
3100b57cec5SDimitry Andric return eServerPacketType_jSignalsInfo;
3110b57cec5SDimitry Andric if (PACKET_MATCHES("jThreadsInfo"))
3120b57cec5SDimitry Andric return eServerPacketType_jThreadsInfo;
313*5f7ddb14SDimitry Andric
314*5f7ddb14SDimitry Andric if (PACKET_MATCHES("jLLDBTraceSupported"))
315*5f7ddb14SDimitry Andric return eServerPacketType_jLLDBTraceSupported;
316*5f7ddb14SDimitry Andric if (PACKET_STARTS_WITH("jLLDBTraceStop:"))
317*5f7ddb14SDimitry Andric return eServerPacketType_jLLDBTraceStop;
318*5f7ddb14SDimitry Andric if (PACKET_STARTS_WITH("jLLDBTraceStart:"))
319*5f7ddb14SDimitry Andric return eServerPacketType_jLLDBTraceStart;
320*5f7ddb14SDimitry Andric if (PACKET_STARTS_WITH("jLLDBTraceGetState:"))
321*5f7ddb14SDimitry Andric return eServerPacketType_jLLDBTraceGetState;
322*5f7ddb14SDimitry Andric if (PACKET_STARTS_WITH("jLLDBTraceGetBinaryData:"))
323*5f7ddb14SDimitry Andric return eServerPacketType_jLLDBTraceGetBinaryData;
3240b57cec5SDimitry Andric break;
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric case 'v':
3270b57cec5SDimitry Andric if (PACKET_STARTS_WITH("vFile:")) {
3280b57cec5SDimitry Andric if (PACKET_STARTS_WITH("vFile:open:"))
3290b57cec5SDimitry Andric return eServerPacketType_vFile_open;
3300b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:close:"))
3310b57cec5SDimitry Andric return eServerPacketType_vFile_close;
3320b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:pread"))
3330b57cec5SDimitry Andric return eServerPacketType_vFile_pread;
3340b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:pwrite"))
3350b57cec5SDimitry Andric return eServerPacketType_vFile_pwrite;
3360b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:size"))
3370b57cec5SDimitry Andric return eServerPacketType_vFile_size;
3380b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:exists"))
3390b57cec5SDimitry Andric return eServerPacketType_vFile_exists;
3400b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:stat"))
3410b57cec5SDimitry Andric return eServerPacketType_vFile_stat;
3420b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:mode"))
3430b57cec5SDimitry Andric return eServerPacketType_vFile_mode;
3440b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:MD5"))
3450b57cec5SDimitry Andric return eServerPacketType_vFile_md5;
3460b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:symlink"))
3470b57cec5SDimitry Andric return eServerPacketType_vFile_symlink;
3480b57cec5SDimitry Andric else if (PACKET_STARTS_WITH("vFile:unlink"))
3490b57cec5SDimitry Andric return eServerPacketType_vFile_unlink;
3500b57cec5SDimitry Andric
3510b57cec5SDimitry Andric } else {
3520b57cec5SDimitry Andric if (PACKET_STARTS_WITH("vAttach;"))
3530b57cec5SDimitry Andric return eServerPacketType_vAttach;
3540b57cec5SDimitry Andric if (PACKET_STARTS_WITH("vAttachWait;"))
3550b57cec5SDimitry Andric return eServerPacketType_vAttachWait;
3560b57cec5SDimitry Andric if (PACKET_STARTS_WITH("vAttachOrWait;"))
3570b57cec5SDimitry Andric return eServerPacketType_vAttachOrWait;
3580b57cec5SDimitry Andric if (PACKET_STARTS_WITH("vAttachName;"))
3590b57cec5SDimitry Andric return eServerPacketType_vAttachName;
3600b57cec5SDimitry Andric if (PACKET_STARTS_WITH("vCont;"))
3610b57cec5SDimitry Andric return eServerPacketType_vCont;
3620b57cec5SDimitry Andric if (PACKET_MATCHES("vCont?"))
3630b57cec5SDimitry Andric return eServerPacketType_vCont_actions;
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric break;
3660b57cec5SDimitry Andric case '_':
3670b57cec5SDimitry Andric switch (packet_cstr[1]) {
3680b57cec5SDimitry Andric case 'M':
3690b57cec5SDimitry Andric return eServerPacketType__M;
3700b57cec5SDimitry Andric
3710b57cec5SDimitry Andric case 'm':
3720b57cec5SDimitry Andric return eServerPacketType__m;
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric break;
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric case '?':
3770b57cec5SDimitry Andric if (packet_size == 1)
3780b57cec5SDimitry Andric return eServerPacketType_stop_reason;
3790b57cec5SDimitry Andric break;
3800b57cec5SDimitry Andric
3810b57cec5SDimitry Andric case 'c':
3820b57cec5SDimitry Andric return eServerPacketType_c;
3830b57cec5SDimitry Andric
3840b57cec5SDimitry Andric case 'C':
3850b57cec5SDimitry Andric return eServerPacketType_C;
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric case 'D':
3880b57cec5SDimitry Andric return eServerPacketType_D;
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric case 'g':
3910b57cec5SDimitry Andric return eServerPacketType_g;
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andric case 'G':
3940b57cec5SDimitry Andric return eServerPacketType_G;
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric case 'H':
3970b57cec5SDimitry Andric return eServerPacketType_H;
3980b57cec5SDimitry Andric
3990b57cec5SDimitry Andric case 'I':
4000b57cec5SDimitry Andric return eServerPacketType_I;
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric case 'k':
4030b57cec5SDimitry Andric if (packet_size == 1)
4040b57cec5SDimitry Andric return eServerPacketType_k;
4050b57cec5SDimitry Andric break;
4060b57cec5SDimitry Andric
4070b57cec5SDimitry Andric case 'm':
4080b57cec5SDimitry Andric return eServerPacketType_m;
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric case 'M':
4110b57cec5SDimitry Andric return eServerPacketType_M;
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric case 'p':
4140b57cec5SDimitry Andric return eServerPacketType_p;
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric case 'P':
4170b57cec5SDimitry Andric return eServerPacketType_P;
4180b57cec5SDimitry Andric
4190b57cec5SDimitry Andric case 's':
4200b57cec5SDimitry Andric if (packet_size == 1)
4210b57cec5SDimitry Andric return eServerPacketType_s;
4220b57cec5SDimitry Andric break;
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric case 'S':
4250b57cec5SDimitry Andric return eServerPacketType_S;
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric case 'x':
4280b57cec5SDimitry Andric return eServerPacketType_x;
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric case 'X':
4310b57cec5SDimitry Andric return eServerPacketType_X;
4320b57cec5SDimitry Andric
4330b57cec5SDimitry Andric case 'T':
4340b57cec5SDimitry Andric return eServerPacketType_T;
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric case 'z':
4370b57cec5SDimitry Andric if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
4380b57cec5SDimitry Andric return eServerPacketType_z;
4390b57cec5SDimitry Andric break;
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andric case 'Z':
4420b57cec5SDimitry Andric if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
4430b57cec5SDimitry Andric return eServerPacketType_Z;
4440b57cec5SDimitry Andric break;
4450b57cec5SDimitry Andric }
4460b57cec5SDimitry Andric return eServerPacketType_unimplemented;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric
IsOKResponse() const4490b57cec5SDimitry Andric bool StringExtractorGDBRemote::IsOKResponse() const {
4500b57cec5SDimitry Andric return GetResponseType() == eOK;
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric
IsUnsupportedResponse() const4530b57cec5SDimitry Andric bool StringExtractorGDBRemote::IsUnsupportedResponse() const {
4540b57cec5SDimitry Andric return GetResponseType() == eUnsupported;
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric
IsNormalResponse() const4570b57cec5SDimitry Andric bool StringExtractorGDBRemote::IsNormalResponse() const {
4580b57cec5SDimitry Andric return GetResponseType() == eResponse;
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric
IsErrorResponse() const4610b57cec5SDimitry Andric bool StringExtractorGDBRemote::IsErrorResponse() const {
4620b57cec5SDimitry Andric return GetResponseType() == eError && isxdigit(m_packet[1]) &&
4630b57cec5SDimitry Andric isxdigit(m_packet[2]);
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric
GetError()4660b57cec5SDimitry Andric uint8_t StringExtractorGDBRemote::GetError() {
4670b57cec5SDimitry Andric if (GetResponseType() == eError) {
4680b57cec5SDimitry Andric SetFilePos(1);
4690b57cec5SDimitry Andric return GetHexU8(255);
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric return 0;
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric
GetStatus()4740b57cec5SDimitry Andric lldb_private::Status StringExtractorGDBRemote::GetStatus() {
4750b57cec5SDimitry Andric lldb_private::Status error;
4760b57cec5SDimitry Andric if (GetResponseType() == eError) {
4770b57cec5SDimitry Andric SetFilePos(1);
4780b57cec5SDimitry Andric uint8_t errc = GetHexU8(255);
4790b57cec5SDimitry Andric error.SetError(errc, lldb::eErrorTypeGeneric);
4800b57cec5SDimitry Andric
4810b57cec5SDimitry Andric error.SetErrorStringWithFormat("Error %u", errc);
4820b57cec5SDimitry Andric std::string error_messg;
4830b57cec5SDimitry Andric if (GetChar() == ';') {
4840b57cec5SDimitry Andric GetHexByteString(error_messg);
4850b57cec5SDimitry Andric error.SetErrorString(error_messg);
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric return error;
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric
GetEscapedBinaryData(std::string & str)4910b57cec5SDimitry Andric size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
4920b57cec5SDimitry Andric // Just get the data bytes in the string as
4930b57cec5SDimitry Andric // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
4940b57cec5SDimitry Andric // characters. If any 0x7d characters are left in the packet, then they are
4950b57cec5SDimitry Andric // supposed to be there...
4960b57cec5SDimitry Andric str.clear();
4970b57cec5SDimitry Andric const size_t bytes_left = GetBytesLeft();
4980b57cec5SDimitry Andric if (bytes_left > 0) {
4990b57cec5SDimitry Andric str.assign(m_packet, m_index, bytes_left);
5000b57cec5SDimitry Andric m_index += bytes_left;
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric return str.size();
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric
5050b57cec5SDimitry Andric static bool
OKErrorNotSupportedResponseValidator(void *,const StringExtractorGDBRemote & response)5060b57cec5SDimitry Andric OKErrorNotSupportedResponseValidator(void *,
5070b57cec5SDimitry Andric const StringExtractorGDBRemote &response) {
5080b57cec5SDimitry Andric switch (response.GetResponseType()) {
5090b57cec5SDimitry Andric case StringExtractorGDBRemote::eOK:
5100b57cec5SDimitry Andric case StringExtractorGDBRemote::eError:
5110b57cec5SDimitry Andric case StringExtractorGDBRemote::eUnsupported:
5120b57cec5SDimitry Andric return true;
5130b57cec5SDimitry Andric
5140b57cec5SDimitry Andric case StringExtractorGDBRemote::eAck:
5150b57cec5SDimitry Andric case StringExtractorGDBRemote::eNack:
5160b57cec5SDimitry Andric case StringExtractorGDBRemote::eResponse:
5170b57cec5SDimitry Andric break;
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric return false;
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric
JSONResponseValidator(void *,const StringExtractorGDBRemote & response)5220b57cec5SDimitry Andric static bool JSONResponseValidator(void *,
5230b57cec5SDimitry Andric const StringExtractorGDBRemote &response) {
5240b57cec5SDimitry Andric switch (response.GetResponseType()) {
5250b57cec5SDimitry Andric case StringExtractorGDBRemote::eUnsupported:
5260b57cec5SDimitry Andric case StringExtractorGDBRemote::eError:
5270b57cec5SDimitry Andric return true; // Accept unsupported or EXX as valid responses
5280b57cec5SDimitry Andric
5290b57cec5SDimitry Andric case StringExtractorGDBRemote::eOK:
5300b57cec5SDimitry Andric case StringExtractorGDBRemote::eAck:
5310b57cec5SDimitry Andric case StringExtractorGDBRemote::eNack:
5320b57cec5SDimitry Andric break;
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric case StringExtractorGDBRemote::eResponse:
5350b57cec5SDimitry Andric // JSON that is returned in from JSON query packets is currently always
5360b57cec5SDimitry Andric // either a dictionary which starts with a '{', or an array which starts
5370b57cec5SDimitry Andric // with a '['. This is a quick validator to just make sure the response
5380b57cec5SDimitry Andric // could be valid JSON without having to validate all of the
5390b57cec5SDimitry Andric // JSON content.
5400b57cec5SDimitry Andric switch (response.GetStringRef()[0]) {
5410b57cec5SDimitry Andric case '{':
5420b57cec5SDimitry Andric return true;
5430b57cec5SDimitry Andric case '[':
5440b57cec5SDimitry Andric return true;
5450b57cec5SDimitry Andric default:
5460b57cec5SDimitry Andric break;
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric break;
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric return false;
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric
5530b57cec5SDimitry Andric static bool
ASCIIHexBytesResponseValidator(void *,const StringExtractorGDBRemote & response)5540b57cec5SDimitry Andric ASCIIHexBytesResponseValidator(void *,
5550b57cec5SDimitry Andric const StringExtractorGDBRemote &response) {
5560b57cec5SDimitry Andric switch (response.GetResponseType()) {
5570b57cec5SDimitry Andric case StringExtractorGDBRemote::eUnsupported:
5580b57cec5SDimitry Andric case StringExtractorGDBRemote::eError:
5590b57cec5SDimitry Andric return true; // Accept unsupported or EXX as valid responses
5600b57cec5SDimitry Andric
5610b57cec5SDimitry Andric case StringExtractorGDBRemote::eOK:
5620b57cec5SDimitry Andric case StringExtractorGDBRemote::eAck:
5630b57cec5SDimitry Andric case StringExtractorGDBRemote::eNack:
5640b57cec5SDimitry Andric break;
5650b57cec5SDimitry Andric
5660b57cec5SDimitry Andric case StringExtractorGDBRemote::eResponse: {
5670b57cec5SDimitry Andric uint32_t valid_count = 0;
5680b57cec5SDimitry Andric for (const char ch : response.GetStringRef()) {
5690b57cec5SDimitry Andric if (!isxdigit(ch)) {
5700b57cec5SDimitry Andric return false;
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric if (++valid_count >= 16)
5730b57cec5SDimitry Andric break; // Don't validate all the characters in case the packet is very
5740b57cec5SDimitry Andric // large
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric return true;
5770b57cec5SDimitry Andric } break;
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric return false;
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric
CopyResponseValidator(const StringExtractorGDBRemote & rhs)5820b57cec5SDimitry Andric void StringExtractorGDBRemote::CopyResponseValidator(
5830b57cec5SDimitry Andric const StringExtractorGDBRemote &rhs) {
5840b57cec5SDimitry Andric m_validator = rhs.m_validator;
5850b57cec5SDimitry Andric m_validator_baton = rhs.m_validator_baton;
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric
SetResponseValidator(ResponseValidatorCallback callback,void * baton)5880b57cec5SDimitry Andric void StringExtractorGDBRemote::SetResponseValidator(
5890b57cec5SDimitry Andric ResponseValidatorCallback callback, void *baton) {
5900b57cec5SDimitry Andric m_validator = callback;
5910b57cec5SDimitry Andric m_validator_baton = baton;
5920b57cec5SDimitry Andric }
5930b57cec5SDimitry Andric
SetResponseValidatorToOKErrorNotSupported()5940b57cec5SDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() {
5950b57cec5SDimitry Andric m_validator = OKErrorNotSupportedResponseValidator;
5960b57cec5SDimitry Andric m_validator_baton = nullptr;
5970b57cec5SDimitry Andric }
5980b57cec5SDimitry Andric
SetResponseValidatorToASCIIHexBytes()5990b57cec5SDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() {
6000b57cec5SDimitry Andric m_validator = ASCIIHexBytesResponseValidator;
6010b57cec5SDimitry Andric m_validator_baton = nullptr;
6020b57cec5SDimitry Andric }
6030b57cec5SDimitry Andric
SetResponseValidatorToJSON()6040b57cec5SDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToJSON() {
6050b57cec5SDimitry Andric m_validator = JSONResponseValidator;
6060b57cec5SDimitry Andric m_validator_baton = nullptr;
6070b57cec5SDimitry Andric }
6080b57cec5SDimitry Andric
ValidateResponse() const6090b57cec5SDimitry Andric bool StringExtractorGDBRemote::ValidateResponse() const {
6100b57cec5SDimitry Andric // If we have a validator callback, try to validate the callback
6110b57cec5SDimitry Andric if (m_validator)
6120b57cec5SDimitry Andric return m_validator(m_validator_baton, *this);
6130b57cec5SDimitry Andric else
6140b57cec5SDimitry Andric return true; // No validator, so response is valid
6150b57cec5SDimitry Andric }
616*5f7ddb14SDimitry Andric
617*5f7ddb14SDimitry Andric llvm::Optional<std::pair<lldb::pid_t, lldb::tid_t>>
GetPidTid(lldb::pid_t default_pid)618*5f7ddb14SDimitry Andric StringExtractorGDBRemote::GetPidTid(lldb::pid_t default_pid) {
619*5f7ddb14SDimitry Andric llvm::StringRef view = llvm::StringRef(m_packet).substr(m_index);
620*5f7ddb14SDimitry Andric size_t initial_length = view.size();
621*5f7ddb14SDimitry Andric lldb::pid_t pid = default_pid;
622*5f7ddb14SDimitry Andric lldb::tid_t tid;
623*5f7ddb14SDimitry Andric
624*5f7ddb14SDimitry Andric if (view.consume_front("p")) {
625*5f7ddb14SDimitry Andric // process identifier
626*5f7ddb14SDimitry Andric if (view.consume_front("-1")) {
627*5f7ddb14SDimitry Andric // -1 is a special case
628*5f7ddb14SDimitry Andric pid = AllProcesses;
629*5f7ddb14SDimitry Andric } else if (view.consumeInteger(16, pid) || pid == 0) {
630*5f7ddb14SDimitry Andric // not a valid hex integer OR unsupported pid 0
631*5f7ddb14SDimitry Andric m_index = UINT64_MAX;
632*5f7ddb14SDimitry Andric return llvm::None;
633*5f7ddb14SDimitry Andric }
634*5f7ddb14SDimitry Andric
635*5f7ddb14SDimitry Andric // "." must follow if we expect TID too; otherwise, we assume -1
636*5f7ddb14SDimitry Andric if (!view.consume_front(".")) {
637*5f7ddb14SDimitry Andric // update m_index
638*5f7ddb14SDimitry Andric m_index += initial_length - view.size();
639*5f7ddb14SDimitry Andric
640*5f7ddb14SDimitry Andric return {{pid, AllThreads}};
641*5f7ddb14SDimitry Andric }
642*5f7ddb14SDimitry Andric }
643*5f7ddb14SDimitry Andric
644*5f7ddb14SDimitry Andric // thread identifier
645*5f7ddb14SDimitry Andric if (view.consume_front("-1")) {
646*5f7ddb14SDimitry Andric // -1 is a special case
647*5f7ddb14SDimitry Andric tid = AllThreads;
648*5f7ddb14SDimitry Andric } else if (view.consumeInteger(16, tid) || tid == 0 || pid == AllProcesses) {
649*5f7ddb14SDimitry Andric // not a valid hex integer OR tid 0 OR pid -1 + a specific tid
650*5f7ddb14SDimitry Andric m_index = UINT64_MAX;
651*5f7ddb14SDimitry Andric return llvm::None;
652*5f7ddb14SDimitry Andric }
653*5f7ddb14SDimitry Andric
654*5f7ddb14SDimitry Andric // update m_index
655*5f7ddb14SDimitry Andric m_index += initial_length - view.size();
656*5f7ddb14SDimitry Andric
657*5f7ddb14SDimitry Andric return {{pid, tid}};
658*5f7ddb14SDimitry Andric }
659