ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
GDBConnection.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
16
18#include "etiss/jit/types.h"
19#include <iostream>
20
21#include <chrono>
22#include <thread>
23
24using namespace etiss::plugin::gdb;
25
26Connection::Connection() : pending_break_(false), packproc_(*this) {}
28
33
34PacketProtocol::PacketProtocol(Connection &connection) : con(connection)
35{
36 cfg_noack_ = false;
37}
38
39size_t PacketProtocol_findUE(std::string &buffer, char c)
40{
41 size_t cur = buffer.find(c);
42 if (cur == 0)
43 return cur;
44 while (cur != std::string::npos)
45 {
46 if (buffer[cur - 1] != '}' && (cur <= 1 || buffer[cur - 2] != '}'))
47 {
48 return cur;
49 }
50 cur = buffer.find(c, cur);
51 }
52 return cur;
53}
54int PacketProtocol_findResponse(std::string &buffer)
55{
56 size_t pos = 0;
57 while (buffer.length() > pos)
58 {
59 if (buffer[pos] == '+' || buffer[pos] == '-')
60 {
61 int ret = (int)buffer[pos];
62 buffer[pos] = ' ';
63 return ret;
64 }
65 else if (buffer[pos] == '%' || buffer[pos] == '$')
66 {
67 std::string substr = buffer.substr(pos);
68 size_t cpos = PacketProtocol_findUE(substr, '#');
69 if (cpos == std::string::npos)
70 return 0;
71 pos = pos + cpos + 3;
72 }
73 else if (buffer[pos] != ' ')
74 { // previously removed ack
75 pos++;
76 }
77 else
78 {
79 std::cout << "ERROR: gdb transmission corrupted; aborting" << stream_code_info << std::endl;
80 return '+';
81 }
82 }
83 return 0;
84}
85size_t PacketProtocol_getPacketStart(std::string &buffer)
86{
87 size_t dol = PacketProtocol_findUE(buffer, '$');
88 size_t per = PacketProtocol_findUE(buffer, '%');
89 if (dol == std::string::npos && per == std::string::npos)
90 {
91 return std::string::npos;
92 }
93 else if (dol == std::string::npos)
94 {
95 return per;
96 }
97 else if (per == std::string::npos)
98 {
99 return dol;
100 }
101 else
102 {
103 return dol < per ? dol : per;
104 }
105}
106bool PacketProtocol_startsWith(const std::string &str, const std::string &prefix)
107{
108 if (prefix.length() > str.length())
109 return false;
110 return str.substr(0, prefix.length()) == prefix;
111}
113{ // filter function to handle some commands internally
114 while (_available(block))
115 {
116 if (command == "QStartNoAckMode")
117 {
118 snd("OK", false);
119 cfg_noack_ = true;
120 }
121 else
122 {
123 return true;
124 }
125 }
126 return false;
127}
129{
130 if (command.length() > 0) // pending command
131 return true;
133 if (command.length() > 0) // pending command
134 return true;
135 do
136 {
137 if (block || con.available())
138 {
139 buffer.append(con.rcv());
140 }
142 if (command.length() > 0) // pending command
143 return true;
144 } while (block);
145 return false;
146}
147
149{
150 if (!command.empty())
151 return;
152 if (con.pendingBREAK())
153 {
154 command = "W";
155 con.clearBREAK();
156 return;
157 }
158 if (buffer.length() > 0 && buffer[0] != '$' && buffer[0] != '%')
159 {
160 unsigned pos = 0; // may not be 1
161 while (buffer.length() > pos && buffer[pos] != '$' && buffer[pos] != '%')
162 { // filter non packet symbols (like +,-,SPACE)
163 pos++;
164 }
165 buffer = pos >= buffer.length() ? "" : buffer.substr(pos);
166 }
167 if (buffer.length() >= 4)
168 {
169 // find packet data end
170 size_t diamond = PacketProtocol_findUE(buffer, '#');
171 if (diamond == std::string::npos)
172 return;
173 // check present packet length
174 if (buffer.length() < diamond + 1 + 2)
175 {
176 return;
177 }
178 // generate checksum
179 std::string tmp = buffer.substr(1, diamond - 1);
180 uint8_t chksm = 0;
181 for (unsigned i = 0; i < tmp.length(); i++)
182 {
183 chksm = chksm + (uint8_t)tmp[i];
184 }
185 uint8_t ochksm = hex::toByte(buffer[diamond + 1], buffer[diamond + 2]);
186 // store message type
187 command_isnotification = buffer[0] != '$';
188 // remove packet from buffer
189 buffer = (diamond + 3 >= buffer.length()) ? "" : buffer.substr(diamond + 3);
190 // verify packet
191 if (chksm != ochksm)
192 {
194 con.snd("-");
195 return;
196 }
197 else
198 {
200 con.snd("+");
201 }
202 if (tmp.find('}') == std::string::npos && tmp.find('*') == std::string::npos)
203 { // no escaped characters
204 command = tmp;
205 }
206 else
207 { // parse string
208 command = tmp;
209 tmp = "";
210 // expand *
211 for (unsigned i = 0; i < command.length(); i++)
212 {
213 if (i >= 1 && command[i] == '*' && command[i - 1] != '}')
214 {
215 if (i + 1 < command.length())
216 {
217 for (int j = 0; j < (int)command[i + 1] - 29; j++)
218 {
219 tmp.push_back(command[i - 1]);
220 }
221 }
222 else
223 {
224 // format error
225 }
226 i++;
227 }
228 else
229 {
230 tmp.push_back(command[i]);
231 }
232 }
233 // translate escaped sequences
234 command = "";
235 for (unsigned i = 0; i < tmp.length(); i++)
236 {
237 if (tmp[i] == '}')
238 {
239 if (i + 1 < tmp.length())
240 {
241 command.push_back(tmp[++i] ^ 0x20);
242 }
243 else
244 {
245 std::cout << "ERROR: PacketProtocol::available() or its parser functions contain an error"
246 << stream_code_info << std::endl;
247 command.push_back(tmp[i]); // should not happen
248 }
249 }
250 else
251 {
252 command.push_back(tmp[i]);
253 }
254 }
255 }
256 }
257}
258
259std::string PacketProtocol::rcv(bool &isnotification)
260{
261 if (command.length() <= 0)
262 available(true);
263 std::string ret = command;
264 isnotification = command_isnotification;
265 command = "";
266 return ret;
267}
268bool PacketProtocol::snd(std::string answer, bool isnotification)
269{
270 std::string pack = isnotification ? "%" : "$";
271 for (unsigned i = 0; i < answer.length(); i++)
272 {
273 if (answer[i] == '}' || answer[i] == '#' || answer[i] == '$' || answer[i] == '%' || answer[i] == '*')
274 {
275 pack.push_back('}');
276 pack.push_back(answer[i] ^ 0x20);
277 }
278 else
279 {
280 pack.push_back(answer[i]);
281 }
282 }
283 pack.push_back('#');
284 uint8_t chksm = 0;
285 for (unsigned i = 1; i < pack.length() - 1; i++)
286 {
287 chksm = chksm + (uint8_t)pack[i];
288 }
289 pack.append(hex::fromByte(chksm));
290 con.snd(pack);
291 // wait for response
292 if (!isnotification && !cfg_noack_)
293 {
294 while (true)
295 {
296 if (con.available())
297 {
298 buffer.append(con.rcv());
299 }
301 if (ack == '+')
302 {
303 return true;
304 }
305 else if (ack == '-')
306 {
307 con.snd(pack);
308 }
309 else if (ack != 0)
310 {
311 std::cout << "ERROR: gdp protocol implementation contains an error" << stream_code_info << std::endl;
312 return false;
313 }
314 std::this_thread::sleep_for(std::chrono::milliseconds(1));
315 }
316 }
317 return true;
318}
320{
321 return false;
322}
324{
325 return pending_break_;
326}
328{
329 pending_break_ = false;
330}
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:41
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:57
std::string fromByte(uint8_t byte)
converts a byte to a hex string (without "0x" prefix);
Definition Hex.cpp:62
#define false
Definition stdbool.h:17