ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
GDBConnection.cpp
Go to the documentation of this file.
1
54
56#include "etiss/jit/types.h"
57#include <iostream>
58
59#include <chrono>
60#include <thread>
61
62using namespace etiss::plugin::gdb;
63
64Connection::Connection() : pending_break_(false), packproc_(*this) {}
66
71
72PacketProtocol::PacketProtocol(Connection &connection) : con(connection)
73{
74 cfg_noack_ = false;
75}
76
77size_t PacketProtocol_findUE(std::string &buffer, char c)
78{
79 size_t cur = buffer.find(c);
80 if (cur == 0)
81 return cur;
82 while (cur != std::string::npos)
83 {
84 if (buffer[cur - 1] != '}' && (cur <= 1 || buffer[cur - 2] != '}'))
85 {
86 return cur;
87 }
88 cur = buffer.find(c, cur);
89 }
90 return cur;
91}
92int PacketProtocol_findResponse(std::string &buffer)
93{
94 size_t pos = 0;
95 while (buffer.length() > pos)
96 {
97 if (buffer[pos] == '+' || buffer[pos] == '-')
98 {
99 int ret = (int)buffer[pos];
100 buffer[pos] = ' ';
101 return ret;
102 }
103 else if (buffer[pos] == '%' || buffer[pos] == '$')
104 {
105 std::string substr = buffer.substr(pos);
106 size_t cpos = PacketProtocol_findUE(substr, '#');
107 if (cpos == std::string::npos)
108 return 0;
109 pos = pos + cpos + 3;
110 }
111 else if (buffer[pos] != ' ')
112 { // previously removed ack
113 pos++;
114 }
115 else
116 {
117 std::cout << "ERROR: gdb transmission corrupted; aborting" << stream_code_info << std::endl;
118 return '+';
119 }
120 }
121 return 0;
122}
123size_t PacketProtocol_getPacketStart(std::string &buffer)
124{
125 size_t dol = PacketProtocol_findUE(buffer, '$');
126 size_t per = PacketProtocol_findUE(buffer, '%');
127 if (dol == std::string::npos && per == std::string::npos)
128 {
129 return std::string::npos;
130 }
131 else if (dol == std::string::npos)
132 {
133 return per;
134 }
135 else if (per == std::string::npos)
136 {
137 return dol;
138 }
139 else
140 {
141 return dol < per ? dol : per;
142 }
143}
144bool PacketProtocol_startsWith(const std::string &str, const std::string &prefix)
145{
146 if (prefix.length() > str.length())
147 return false;
148 return str.substr(0, prefix.length()) == prefix;
149}
151{ // filter function to handle some commands internally
152 while (_available(block))
153 {
154 if (command == "QStartNoAckMode")
155 {
156 snd("OK", false);
157 cfg_noack_ = true;
158 }
159 else
160 {
161 return true;
162 }
163 }
164 return false;
165}
167{
168 if (command.length() > 0) // pending command
169 return true;
171 if (command.length() > 0) // pending command
172 return true;
173 do
174 {
175 if (block || con.available())
176 {
177 buffer.append(con.rcv());
178 }
180 if (command.length() > 0) // pending command
181 return true;
182 } while (block);
183 return false;
184}
185
187{
188 if (!command.empty())
189 return;
190 if (con.pendingBREAK())
191 {
192 command = "W";
193 con.clearBREAK();
194 return;
195 }
196 if (buffer.length() > 0 && buffer[0] != '$' && buffer[0] != '%')
197 {
198 unsigned pos = 0; // may not be 1
199 while (buffer.length() > pos && buffer[pos] != '$' && buffer[pos] != '%')
200 { // filter non packet symbols (like +,-,SPACE)
201 pos++;
202 }
203 buffer = pos >= buffer.length() ? "" : buffer.substr(pos);
204 }
205 if (buffer.length() >= 4)
206 {
207 // find packet data end
208 size_t diamond = PacketProtocol_findUE(buffer, '#');
209 if (diamond == std::string::npos)
210 return;
211 // check present packet length
212 if (buffer.length() < diamond + 1 + 2)
213 {
214 return;
215 }
216 // generate checksum
217 std::string tmp = buffer.substr(1, diamond - 1);
218 uint8_t chksm = 0;
219 for (unsigned i = 0; i < tmp.length(); i++)
220 {
221 chksm = chksm + (uint8_t)tmp[i];
222 }
223 uint8_t ochksm = hex::toByte(buffer[diamond + 1], buffer[diamond + 2]);
224 // store message type
225 command_isnotification = buffer[0] != '$';
226 // remove packet from buffer
227 buffer = (diamond + 3 >= buffer.length()) ? "" : buffer.substr(diamond + 3);
228 // verify packet
229 if (chksm != ochksm)
230 {
232 con.snd("-");
233 return;
234 }
235 else
236 {
238 con.snd("+");
239 }
240 if (tmp.find('}') == std::string::npos && tmp.find('*') == std::string::npos)
241 { // no escaped characters
242 command = tmp;
243 }
244 else
245 { // parse string
246 command = tmp;
247 tmp = "";
248 // expand *
249 for (unsigned i = 0; i < command.length(); i++)
250 {
251 if (i >= 1 && command[i] == '*' && command[i - 1] != '}')
252 {
253 if (i + 1 < command.length())
254 {
255 for (int j = 0; j < (int)command[i + 1] - 29; j++)
256 {
257 tmp.push_back(command[i - 1]);
258 }
259 }
260 else
261 {
262 // format error
263 }
264 i++;
265 }
266 else
267 {
268 tmp.push_back(command[i]);
269 }
270 }
271 // translate escaped sequences
272 command = "";
273 for (unsigned i = 0; i < tmp.length(); i++)
274 {
275 if (tmp[i] == '}')
276 {
277 if (i + 1 < tmp.length())
278 {
279 command.push_back(tmp[++i] ^ 0x20);
280 }
281 else
282 {
283 std::cout << "ERROR: PacketProtocol::available() or its parser functions contain an error"
284 << stream_code_info << std::endl;
285 command.push_back(tmp[i]); // should not happen
286 }
287 }
288 else
289 {
290 command.push_back(tmp[i]);
291 }
292 }
293 }
294 }
295}
296
297std::string PacketProtocol::rcv(bool &isnotification)
298{
299 if (command.length() <= 0)
300 available(true);
301 std::string ret = command;
302 isnotification = command_isnotification;
303 command = "";
304 return ret;
305}
306bool PacketProtocol::snd(std::string answer, bool isnotification)
307{
308 std::string pack = isnotification ? "%" : "$";
309 for (unsigned i = 0; i < answer.length(); i++)
310 {
311 if (answer[i] == '}' || answer[i] == '#' || answer[i] == '$' || answer[i] == '%' || answer[i] == '*')
312 {
313 pack.push_back('}');
314 pack.push_back(answer[i] ^ 0x20);
315 }
316 else
317 {
318 pack.push_back(answer[i]);
319 }
320 }
321 pack.push_back('#');
322 uint8_t chksm = 0;
323 for (unsigned i = 1; i < pack.length() - 1; i++)
324 {
325 chksm = chksm + (uint8_t)pack[i];
326 }
327 pack.append(hex::fromByte(chksm));
328 con.snd(pack);
329 // wait for response
330 if (!isnotification && !cfg_noack_)
331 {
332 while (true)
333 {
334 if (con.available())
335 {
336 buffer.append(con.rcv());
337 }
339 if (ack == '+')
340 {
341 return true;
342 }
343 else if (ack == '-')
344 {
345 con.snd(pack);
346 }
347 else if (ack != 0)
348 {
349 std::cout << "ERROR: gdp protocol implementation contains an error" << stream_code_info << std::endl;
350 return false;
351 }
352 std::this_thread::sleep_for(std::chrono::milliseconds(1));
353 }
354 }
355 return true;
356}
358{
359 return false;
360}
362{
363 return pending_break_;
364}
366{
367 pending_break_ = false;
368}
size_t PacketProtocol_getPacketStart(std::string &buffer)
size_t PacketProtocol_findUE(std::string &buffer, char c)
bool PacketProtocol_startsWith(const std::string &str, const std::string &prefix)
int PacketProtocol_findResponse(std::string &buffer)
__device__ __2f16 float c
static __inline__ uint8_t
Definition arm_mve.h:323
#define stream_code_info
Definition types.h:79
interface for gdb connections.
virtual std::string rcv()=0
virtual bool snd(std::string answer)=0
virtual PacketProtocol & getPacketProtocol()
implements gdb's packet protocol
virtual bool snd(std::string answer, bool isnotification)
virtual std::string rcv(bool &isnotification)
virtual bool available(bool block=false)
virtual bool _available(bool block)
PacketProtocol(Connection &connection)
uint8_t toByte(char h, char l)
converts 2 hex characters to a byte
Definition Hex.cpp:95
std::string fromByte(uint8_t byte)
converts a byte to a hex string (without "0x" prefix);
Definition Hex.cpp:100
#define false
Definition stdbool.h:17