ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
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 
62 using namespace etiss::plugin::gdb;
63 
64 Connection::Connection() : pending_break_(false), packproc_(*this) {}
66 
68 {
69  return packproc_;
70 }
71 
72 PacketProtocol::PacketProtocol(Connection &connection) : con(connection)
73 {
74  cfg_noack_ = false;
75 }
76 
77 size_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 }
92 int 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 }
123 size_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 }
144 bool 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;
170  tryReadPacket();
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  }
179  tryReadPacket();
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 
297 std::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 }
306 bool 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__ int
__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
Definition: GDBConnection.h:76
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