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
GetResponseType() const21 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
GetServerPacketType() const54 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         }
98         break;
99 
100     case 'q':
101         switch (packet_cstr[1])
102         {
103         case 's':
104             if (PACKET_MATCHES ("qsProcessInfo"))               return eServerPacketType_qsProcessInfo;
105             break;
106 
107         case 'f':
108             if (PACKET_STARTS_WITH ("qfProcessInfo"))           return eServerPacketType_qfProcessInfo;
109             break;
110 
111         case 'C':
112             if (packet_size == 2)                               return eServerPacketType_qC;
113             break;
114 
115         case 'G':
116             if (PACKET_STARTS_WITH ("qGroupName:"))             return eServerPacketType_qGroupName;
117             break;
118 
119         case 'H':
120             if (PACKET_MATCHES ("qHostInfo"))                   return eServerPacketType_qHostInfo;
121             break;
122 
123         case 'L':
124             if (PACKET_MATCHES ("qLaunchGDBServer"))            return eServerPacketType_qLaunchGDBServer;
125             if (PACKET_MATCHES ("qLaunchSuccess"))              return eServerPacketType_qLaunchSuccess;
126             break;
127 
128         case 'P':
129             if (PACKET_STARTS_WITH ("qProcessInfoPID:"))        return eServerPacketType_qProcessInfoPID;
130             break;
131 
132         case 'S':
133             if (PACKET_STARTS_WITH ("qSpeedTest:"))             return eServerPacketType_qSpeedTest;
134             break;
135 
136         case 'U':
137             if (PACKET_STARTS_WITH ("qUserName:"))              return eServerPacketType_qUserName;
138             break;
139         }
140         break;
141     }
142     return eServerPacketType_unimplemented;
143 }
144 
145 bool
IsOKResponse() const146 StringExtractorGDBRemote::IsOKResponse() const
147 {
148     return GetResponseType () == eOK;
149 }
150 
151 
152 bool
IsUnsupportedResponse() const153 StringExtractorGDBRemote::IsUnsupportedResponse() const
154 {
155     return GetResponseType () == eUnsupported;
156 }
157 
158 bool
IsNormalResponse() const159 StringExtractorGDBRemote::IsNormalResponse() const
160 {
161     return GetResponseType () == eResponse;
162 }
163 
164 bool
IsErrorResponse() const165 StringExtractorGDBRemote::IsErrorResponse() const
166 {
167     return GetResponseType () == eError &&
168            m_packet.size() == 3 &&
169            isxdigit(m_packet[1]) &&
170            isxdigit(m_packet[2]);
171 }
172 
173 uint8_t
GetError()174 StringExtractorGDBRemote::GetError ()
175 {
176     if (GetResponseType() == eError)
177     {
178         SetFilePos(1);
179         return GetHexU8(255);
180     }
181     return 0;
182 }
183