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             break;
121 
122         case 'H':
123             if (PACKET_MATCHES ("qHostInfo"))                   return eServerPacketType_qHostInfo;
124             break;
125 
126         case 'K':
127             if (PACKET_STARTS_WITH ("qKillSpawnedProcess"))     return eServerPacketType_qKillSpawnedProcess;
128             break;
129 
130         case 'L':
131             if (PACKET_STARTS_WITH ("qLaunchGDBServer"))        return eServerPacketType_qLaunchGDBServer;
132             if (PACKET_MATCHES ("qLaunchSuccess"))              return eServerPacketType_qLaunchSuccess;
133             break;
134 
135         case 'P':
136             if (PACKET_STARTS_WITH ("qProcessInfoPID:"))                 return eServerPacketType_qProcessInfoPID;
137             if (PACKET_STARTS_WITH ("qPlatform_RunCommand:"))            return eServerPacketType_qPlatform_RunCommand;
138             if (PACKET_STARTS_WITH ("qPlatform_IO_MkDir:"))              return eServerPacketType_qPlatform_IO_MkDir;
139             break;
140 
141 
142         case 'S':
143             if (PACKET_STARTS_WITH ("qSpeedTest:"))             return eServerPacketType_qSpeedTest;
144             break;
145 
146         case 'U':
147             if (PACKET_STARTS_WITH ("qUserName:"))              return eServerPacketType_qUserName;
148             break;
149         }
150         break;
151     case 'v':
152             if (PACKET_STARTS_WITH("vFile:"))
153             {
154                 if (PACKET_STARTS_WITH("vFile:open:"))               return eServerPacketType_vFile_Open;
155                 else if (PACKET_STARTS_WITH("vFile:close:"))         return eServerPacketType_vFile_Close;
156                 else if (PACKET_STARTS_WITH("vFile:pread"))          return eServerPacketType_vFile_pRead;
157                 else if (PACKET_STARTS_WITH("vFile:pwrite"))         return eServerPacketType_vFile_pWrite;
158                 else if (PACKET_STARTS_WITH("vFile:size"))           return eServerPacketType_vFile_Size;
159                 else if (PACKET_STARTS_WITH("vFile:exists"))         return eServerPacketType_vFile_Exists;
160                 else if (PACKET_STARTS_WITH("vFile:stat"))           return eServerPacketType_vFile_Stat;
161                 else if (PACKET_STARTS_WITH("vFile:mode"))           return eServerPacketType_vFile_Mode;
162                 else if (PACKET_STARTS_WITH("vFile:MD5"))            return eServerPacketType_vFile_MD5;
163 
164             }
165             break;
166     }
167     return eServerPacketType_unimplemented;
168 }
169 
170 bool
171 StringExtractorGDBRemote::IsOKResponse() const
172 {
173     return GetResponseType () == eOK;
174 }
175 
176 
177 bool
178 StringExtractorGDBRemote::IsUnsupportedResponse() const
179 {
180     return GetResponseType () == eUnsupported;
181 }
182 
183 bool
184 StringExtractorGDBRemote::IsNormalResponse() const
185 {
186     return GetResponseType () == eResponse;
187 }
188 
189 bool
190 StringExtractorGDBRemote::IsErrorResponse() const
191 {
192     return GetResponseType () == eError &&
193            m_packet.size() == 3 &&
194            isxdigit(m_packet[1]) &&
195            isxdigit(m_packet[2]);
196 }
197 
198 uint8_t
199 StringExtractorGDBRemote::GetError ()
200 {
201     if (GetResponseType() == eError)
202     {
203         SetFilePos(1);
204         return GetHexU8(255);
205     }
206     return 0;
207 }
208 
209 size_t
210 StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str)
211 {
212     str.clear();
213     char ch;
214     while (GetBytesLeft())
215     {
216         ch = GetChar();
217         if (ch == 0x7d)
218             ch = (GetChar() ^ 0x20);
219         str.append(1,ch);
220     }
221     return str.size();
222 }
223 
224