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
19
20StringExtractorGDBRemote::ResponseType
21StringExtractorGDBRemote::GetResponseType () const
22{
23    if (m_packet.empty())
24        return eUnsupported;
25
26    switch (m_packet[0])
27    {
28    case 'E':
29        if (m_packet.size() == 3 &&
30            isxdigit(m_packet[1]) &&
31            isxdigit(m_packet[2]))
32            return eError;
33        break;
34
35    case 'O':
36        if (m_packet.size() == 2 && m_packet[1] == 'K')
37            return eOK;
38        break;
39
40    case '+':
41        if (m_packet.size() == 1)
42            return eAck;
43        break;
44
45    case '-':
46        if (m_packet.size() == 1)
47            return eNack;
48        break;
49    }
50    return eResponse;
51}
52
53StringExtractorGDBRemote::ServerPacketType
54StringExtractorGDBRemote::GetServerPacketType () const
55{
56#define PACKET_MATCHES(s) ((packet_size == (sizeof(s)-1)) && (strcmp((packet_cstr),(s)) == 0))
57#define PACKET_STARTS_WITH(s) ((packet_size >= (sizeof(s)-1)) && ::strncmp(packet_cstr, s, (sizeof(s)-1))==0)
58
59    // Empty is not a supported packet...
60    if (m_packet.empty())
61        return eServerPacketType_invalid;
62
63    const size_t packet_size = m_packet.size();
64    const char *packet_cstr = m_packet.c_str();
65    switch (m_packet[0])
66    {
67    case '\x03':
68        if (packet_size == 1) return eServerPacketType_interrupt;
69        break;
70
71    case '-':
72        if (packet_size == 1) return eServerPacketType_nack;
73        break;
74
75    case '+':
76        if (packet_size == 1) return eServerPacketType_ack;
77        break;
78
79    case 'A':
80        return eServerPacketType_A;
81
82    case 'Q':
83
84        switch (packet_cstr[1])
85        {
86        case 'E':
87            if (PACKET_STARTS_WITH ("QEnvironment:"))           return eServerPacketType_QEnvironment;
88            if (PACKET_STARTS_WITH ("QEnvironmentHexEncoded:")) return eServerPacketType_QEnvironmentHexEncoded;
89            break;
90
91        case 'S':
92            if (PACKET_MATCHES ("QStartNoAckMode"))               return eServerPacketType_QStartNoAckMode;
93            if (PACKET_STARTS_WITH ("QSaveRegisterState"))        return eServerPacketType_QSaveRegisterState;
94            if (PACKET_STARTS_WITH ("QSetDisableASLR:"))          return eServerPacketType_QSetDisableASLR;
95            if (PACKET_STARTS_WITH ("QSetSTDIN:"))                return eServerPacketType_QSetSTDIN;
96            if (PACKET_STARTS_WITH ("QSetSTDOUT:"))               return eServerPacketType_QSetSTDOUT;
97            if (PACKET_STARTS_WITH ("QSetSTDERR:"))               return eServerPacketType_QSetSTDERR;
98            if (PACKET_STARTS_WITH ("QSetWorkingDir:"))           return eServerPacketType_QSetWorkingDir;
99            if (PACKET_STARTS_WITH ("QSetLogging:"))              return eServerPacketType_QSetLogging;
100            if (PACKET_STARTS_WITH ("QSetMaxPacketSize:"))        return eServerPacketType_QSetMaxPacketSize;
101            if (PACKET_STARTS_WITH ("QSetMaxPayloadSize:"))       return eServerPacketType_QSetMaxPayloadSize;
102            if (PACKET_STARTS_WITH ("QSetEnableAsyncProfiling;")) return eServerPacketType_QSetEnableAsyncProfiling;
103            if (PACKET_STARTS_WITH ("QSyncThreadState:"))         return eServerPacketType_QSyncThreadState;
104            break;
105
106        case 'L':
107            if (PACKET_STARTS_WITH ("QLaunchArch:"))              return eServerPacketType_QLaunchArch;
108            if (PACKET_MATCHES("QListThreadsInStopReply"))        return eServerPacketType_QListThreadsInStopReply;
109            break;
110
111        case 'R':
112            if (PACKET_STARTS_WITH ("QRestoreRegisterState:"))    return eServerPacketType_QRestoreRegisterState;
113            break;
114
115        case 'T':
116            if (PACKET_MATCHES ("QThreadSuffixSupported"))        return eServerPacketType_QThreadSuffixSupported;
117            break;
118        }
119        break;
120
121    case 'q':
122        switch (packet_cstr[1])
123        {
124        case 's':
125            if (PACKET_MATCHES ("qsProcessInfo"))               return eServerPacketType_qsProcessInfo;
126            if (PACKET_MATCHES ("qsThreadInfo"))                return eServerPacketType_qsThreadInfo;
127            break;
128
129        case 'f':
130            if (PACKET_STARTS_WITH ("qfProcessInfo"))           return eServerPacketType_qfProcessInfo;
131            if (PACKET_STARTS_WITH ("qfThreadInfo"))            return eServerPacketType_qfThreadInfo;
132            break;
133
134        case 'C':
135            if (packet_size == 2)                               return eServerPacketType_qC;
136            break;
137
138        case 'G':
139            if (PACKET_STARTS_WITH ("qGroupName:"))             return eServerPacketType_qGroupName;
140            if (PACKET_MATCHES ("qGetWorkingDir"))              return eServerPacketType_qGetWorkingDir;
141            if (PACKET_MATCHES ("qGetPid"))                     return eServerPacketType_qGetPid;
142            if (PACKET_STARTS_WITH ("qGetProfileData;"))        return eServerPacketType_qGetProfileData;
143            if (PACKET_MATCHES ("qGDBServerVersion"))           return eServerPacketType_qGDBServerVersion;
144            break;
145
146        case 'H':
147            if (PACKET_MATCHES ("qHostInfo"))                   return eServerPacketType_qHostInfo;
148            break;
149
150        case 'K':
151            if (PACKET_STARTS_WITH ("qKillSpawnedProcess"))     return eServerPacketType_qKillSpawnedProcess;
152            break;
153
154        case 'L':
155            if (PACKET_STARTS_WITH ("qLaunchGDBServer"))        return eServerPacketType_qLaunchGDBServer;
156            if (PACKET_MATCHES ("qLaunchSuccess"))              return eServerPacketType_qLaunchSuccess;
157            break;
158
159        case 'M':
160            if (PACKET_STARTS_WITH ("qMemoryRegionInfo:"))      return eServerPacketType_qMemoryRegionInfo;
161            if (PACKET_MATCHES ("qMemoryRegionInfo"))           return eServerPacketType_qMemoryRegionInfoSupported;
162            break;
163
164        case 'P':
165            if (PACKET_STARTS_WITH ("qProcessInfoPID:"))        return eServerPacketType_qProcessInfoPID;
166            if (PACKET_STARTS_WITH ("qPlatform_shell:"))        return eServerPacketType_qPlatform_shell;
167            if (PACKET_STARTS_WITH ("qPlatform_mkdir:"))        return eServerPacketType_qPlatform_mkdir;
168            if (PACKET_STARTS_WITH ("qPlatform_chmod:"))        return eServerPacketType_qPlatform_chmod;
169            if (PACKET_MATCHES ("qProcessInfo"))                return eServerPacketType_qProcessInfo;
170            break;
171
172        case 'R':
173            if (PACKET_STARTS_WITH ("qRcmd,"))                  return eServerPacketType_qRcmd;
174            if (PACKET_STARTS_WITH ("qRegisterInfo"))           return eServerPacketType_qRegisterInfo;
175            break;
176
177        case 'S':
178            if (PACKET_STARTS_WITH ("qSpeedTest:"))             return eServerPacketType_qSpeedTest;
179            if (PACKET_MATCHES ("qShlibInfoAddr"))              return eServerPacketType_qShlibInfoAddr;
180            if (PACKET_MATCHES ("qStepPacketSupported"))        return eServerPacketType_qStepPacketSupported;
181            if (PACKET_MATCHES ("qSyncThreadStateSupported"))   return eServerPacketType_qSyncThreadStateSupported;
182            break;
183
184        case 'T':
185            if (PACKET_STARTS_WITH ("qThreadExtraInfo,"))       return eServerPacketType_qThreadExtraInfo;
186            if (PACKET_STARTS_WITH ("qThreadStopInfo"))         return eServerPacketType_qThreadStopInfo;
187            break;
188
189        case 'U':
190            if (PACKET_STARTS_WITH ("qUserName:"))              return eServerPacketType_qUserName;
191            break;
192
193        case 'V':
194            if (PACKET_MATCHES ("qVAttachOrWaitSupported"))     return eServerPacketType_qVAttachOrWaitSupported;
195            break;
196
197        case 'W':
198            if (PACKET_STARTS_WITH ("qWatchpointSupportInfo:")) return eServerPacketType_qWatchpointSupportInfo;
199            if (PACKET_MATCHES ("qWatchpointSupportInfo"))      return eServerPacketType_qWatchpointSupportInfoSupported;
200            break;
201        }
202        break;
203    case 'v':
204            if (PACKET_STARTS_WITH("vFile:"))
205            {
206                if (PACKET_STARTS_WITH("vFile:open:"))          return eServerPacketType_vFile_open;
207                else if (PACKET_STARTS_WITH("vFile:close:"))    return eServerPacketType_vFile_close;
208                else if (PACKET_STARTS_WITH("vFile:pread"))     return eServerPacketType_vFile_pread;
209                else if (PACKET_STARTS_WITH("vFile:pwrite"))    return eServerPacketType_vFile_pwrite;
210                else if (PACKET_STARTS_WITH("vFile:size"))      return eServerPacketType_vFile_size;
211                else if (PACKET_STARTS_WITH("vFile:exists"))    return eServerPacketType_vFile_exists;
212                else if (PACKET_STARTS_WITH("vFile:stat"))      return eServerPacketType_vFile_stat;
213                else if (PACKET_STARTS_WITH("vFile:mode"))      return eServerPacketType_vFile_mode;
214                else if (PACKET_STARTS_WITH("vFile:MD5"))       return eServerPacketType_vFile_md5;
215                else if (PACKET_STARTS_WITH("vFile:symlink"))   return eServerPacketType_vFile_symlink;
216                else if (PACKET_STARTS_WITH("vFile:unlink"))    return eServerPacketType_vFile_unlink;
217
218            } else {
219              if (PACKET_STARTS_WITH ("vAttach;"))              return eServerPacketType_vAttach;
220              if (PACKET_STARTS_WITH ("vAttachWait;"))          return eServerPacketType_vAttachWait;
221              if (PACKET_STARTS_WITH ("vAttachOrWait;"))        return eServerPacketType_vAttachOrWait;
222              if (PACKET_STARTS_WITH ("vAttachName;"))          return eServerPacketType_vAttachName;
223              if (PACKET_STARTS_WITH("vCont;"))                 return eServerPacketType_vCont;
224              if (PACKET_MATCHES ("vCont?"))                    return eServerPacketType_vCont_actions;
225            }
226            break;
227      case '_':
228        switch (packet_cstr[1])
229        {
230        case 'M':
231            return eServerPacketType__M;
232
233        case 'm':
234            return eServerPacketType__m;
235        }
236        break;
237
238      case '?':
239        if (packet_size == 1) return eServerPacketType_stop_reason;
240        break;
241
242      case 'c':
243        return eServerPacketType_c;
244
245      case 'C':
246        return eServerPacketType_C;
247
248      case 'D':
249        if (packet_size == 1) return eServerPacketType_D;
250        break;
251
252      case 'g':
253        if (packet_size == 1) return eServerPacketType_g;
254        break;
255
256      case 'G':
257        return eServerPacketType_G;
258
259      case 'H':
260        return eServerPacketType_H;
261
262      case 'k':
263        if (packet_size == 1) return eServerPacketType_k;
264        break;
265
266      case 'm':
267        return eServerPacketType_m;
268
269      case 'M':
270        return eServerPacketType_M;
271
272      case 'p':
273        return eServerPacketType_p;
274
275      case 'P':
276        return eServerPacketType_P;
277
278      case 's':
279        if (packet_size == 1) return eServerPacketType_s;
280        break;
281
282      case 'S':
283        return eServerPacketType_S;
284
285      case 'T':
286        return eServerPacketType_T;
287
288      case 'z':
289        if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
290          return eServerPacketType_z;
291        break;
292
293      case 'Z':
294        if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
295          return eServerPacketType_Z;
296        break;
297    }
298    return eServerPacketType_unimplemented;
299}
300
301bool
302StringExtractorGDBRemote::IsOKResponse() const
303{
304    return GetResponseType () == eOK;
305}
306
307
308bool
309StringExtractorGDBRemote::IsUnsupportedResponse() const
310{
311    return GetResponseType () == eUnsupported;
312}
313
314bool
315StringExtractorGDBRemote::IsNormalResponse() const
316{
317    return GetResponseType () == eResponse;
318}
319
320bool
321StringExtractorGDBRemote::IsErrorResponse() const
322{
323    return GetResponseType () == eError &&
324           m_packet.size() == 3 &&
325           isxdigit(m_packet[1]) &&
326           isxdigit(m_packet[2]);
327}
328
329uint8_t
330StringExtractorGDBRemote::GetError ()
331{
332    if (GetResponseType() == eError)
333    {
334        SetFilePos(1);
335        return GetHexU8(255);
336    }
337    return 0;
338}
339
340size_t
341StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str)
342{
343    str.clear();
344    char ch;
345    while (GetBytesLeft())
346    {
347        ch = GetChar();
348        if (ch == 0x7d)
349            ch = (GetChar() ^ 0x20);
350        str.append(1,ch);
351    }
352    return str.size();
353}
354
355