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 
20 StringExtractorGDBRemote::ResponseType
21 StringExtractorGDBRemote::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 
53 StringExtractorGDBRemote::ServerPacketType
54 StringExtractorGDBRemote::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         switch (packet_cstr[1])
84         {
85         case 'E':
86             if (PACKET_STARTS_WITH ("QEnvironment:"))           return eServerPacketType_QEnvironment;
87             break;
88 
89         case 'S':
90             if (PACKET_MATCHES ("QStartNoAckMode"))             return eServerPacketType_QStartNoAckMode;
91             else if (PACKET_STARTS_WITH ("QSetDisableASLR:"))   return eServerPacketType_QSetDisableASLR;
92             else if (PACKET_STARTS_WITH ("QSetSTDIN:"))         return eServerPacketType_QSetSTDIN;
93             else if (PACKET_STARTS_WITH ("QSetSTDOUT:"))        return eServerPacketType_QSetSTDOUT;
94             else if (PACKET_STARTS_WITH ("QSetSTDERR:"))        return eServerPacketType_QSetSTDERR;
95             else if (PACKET_STARTS_WITH ("QSetWorkingDir:"))    return eServerPacketType_QSetWorkingDir;
96             break;
97         case 'L':
98             if (PACKET_STARTS_WITH ("QLaunchArch:"))            return eServerPacketType_QLaunchArch;
99             break;
100         }
101         break;
102 
103     case 'q':
104         switch (packet_cstr[1])
105         {
106         case 's':
107             if (PACKET_MATCHES ("qsProcessInfo"))               return eServerPacketType_qsProcessInfo;
108             break;
109 
110         case 'f':
111             if (PACKET_STARTS_WITH ("qfProcessInfo"))           return eServerPacketType_qfProcessInfo;
112             break;
113 
114         case 'C':
115             if (packet_size == 2)                               return eServerPacketType_qC;
116             break;
117 
118         case 'G':
119             if (PACKET_STARTS_WITH ("qGroupName:"))             return eServerPacketType_qGroupName;
120             if (PACKET_MATCHES ("qGetWorkingDir"))              return eServerPacketType_qGetWorkingDir;
121             break;
122 
123         case 'H':
124             if (PACKET_MATCHES ("qHostInfo"))                   return eServerPacketType_qHostInfo;
125             break;
126 
127         case 'K':
128             if (PACKET_STARTS_WITH ("qKillSpawnedProcess"))     return eServerPacketType_qKillSpawnedProcess;
129             break;
130 
131         case 'L':
132             if (PACKET_STARTS_WITH ("qLaunchGDBServer"))        return eServerPacketType_qLaunchGDBServer;
133             if (PACKET_MATCHES ("qLaunchSuccess"))              return eServerPacketType_qLaunchSuccess;
134             break;
135 
136         case 'P':
137             if (PACKET_STARTS_WITH ("qProcessInfoPID:"))        return eServerPacketType_qProcessInfoPID;
138             if (PACKET_STARTS_WITH ("qPlatform_shell:"))   return eServerPacketType_qPlatform_shell;
139             if (PACKET_STARTS_WITH ("qPlatform_mkdir:"))        return eServerPacketType_qPlatform_mkdir;
140             if (PACKET_STARTS_WITH ("qPlatform_chmod:"))        return eServerPacketType_qPlatform_chmod;
141             break;
142 
143 
144         case 'S':
145             if (PACKET_STARTS_WITH ("qSpeedTest:"))             return eServerPacketType_qSpeedTest;
146             break;
147 
148         case 'U':
149             if (PACKET_STARTS_WITH ("qUserName:"))              return eServerPacketType_qUserName;
150             break;
151         }
152         break;
153     case 'v':
154             if (PACKET_STARTS_WITH("vFile:"))
155             {
156                 if (PACKET_STARTS_WITH("vFile:open:"))          return eServerPacketType_vFile_open;
157                 else if (PACKET_STARTS_WITH("vFile:close:"))    return eServerPacketType_vFile_close;
158                 else if (PACKET_STARTS_WITH("vFile:pread"))     return eServerPacketType_vFile_pread;
159                 else if (PACKET_STARTS_WITH("vFile:pwrite"))    return eServerPacketType_vFile_pwrite;
160                 else if (PACKET_STARTS_WITH("vFile:size"))      return eServerPacketType_vFile_size;
161                 else if (PACKET_STARTS_WITH("vFile:exists"))    return eServerPacketType_vFile_exists;
162                 else if (PACKET_STARTS_WITH("vFile:stat"))      return eServerPacketType_vFile_stat;
163                 else if (PACKET_STARTS_WITH("vFile:mode"))      return eServerPacketType_vFile_mode;
164                 else if (PACKET_STARTS_WITH("vFile:MD5"))       return eServerPacketType_vFile_md5;
165                 else if (PACKET_STARTS_WITH("vFile:symlink"))   return eServerPacketType_vFile_symlink;
166                 else if (PACKET_STARTS_WITH("vFile:unlink"))    return eServerPacketType_vFile_unlink;
167 
168             }
169             break;
170     }
171     return eServerPacketType_unimplemented;
172 }
173 
174 bool
175 StringExtractorGDBRemote::IsOKResponse() const
176 {
177     return GetResponseType () == eOK;
178 }
179 
180 
181 bool
182 StringExtractorGDBRemote::IsUnsupportedResponse() const
183 {
184     return GetResponseType () == eUnsupported;
185 }
186 
187 bool
188 StringExtractorGDBRemote::IsNormalResponse() const
189 {
190     return GetResponseType () == eResponse;
191 }
192 
193 bool
194 StringExtractorGDBRemote::IsErrorResponse() const
195 {
196     return GetResponseType () == eError &&
197            m_packet.size() == 3 &&
198            isxdigit(m_packet[1]) &&
199            isxdigit(m_packet[2]);
200 }
201 
202 uint8_t
203 StringExtractorGDBRemote::GetError ()
204 {
205     if (GetResponseType() == eError)
206     {
207         SetFilePos(1);
208         return GetHexU8(255);
209     }
210     return 0;
211 }
212 
213 size_t
214 StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str)
215 {
216     str.clear();
217     char ch;
218     while (GetBytesLeft())
219     {
220         ch = GetChar();
221         if (ch == 0x7d)
222             ch = (GetChar() ^ 0x20);
223         str.append(1,ch);
224     }
225     return str.size();
226 }
227 
228