ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
GDBServer.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#include "etiss/Instruction.h"
17#include "etiss/CPUCore.h"
18#include "etiss/CPUArch.h"
21#include "etiss/jit/types.h"
22#include "etiss/jit/ReturnCode.h"
23#include <chrono>
24#include <cstring>
25#include <thread>
26
27using namespace etiss::plugin::gdb;
28
33
34void BreakpointDB::set(etiss::uint64 addr, etiss::uint32 val)
35{
36 if (instrbrkpt_ == 0)
37 {
38 if (val == 0)
39 return;
40 instrbrkpt_ = new etiss::uint32 ***[1 << 16];
41 memset(instrbrkpt_, 0, sizeof(etiss::uint32 * **[1 << 16]));
42 }
43 unsigned a1 = (addr) & 0xFFFF;
44 if (instrbrkpt_[a1] == 0)
45 {
46 if (val == 0)
47 return;
48 instrbrkpt_[a1] = new etiss::uint32 **[1 << 16];
49 memset(instrbrkpt_[a1], 0, sizeof(etiss::uint32 * *[1 << 16]));
50 }
51 unsigned a2 = (addr >> 16) & 0xFFFF;
52 if (instrbrkpt_[a1][a2] == 0)
53 {
54 if (val == 0)
55 return;
56 instrbrkpt_[a1][a2] = new etiss::uint32 *[1 << 16];
57 memset(instrbrkpt_[a1][a2], 0, sizeof(etiss::uint32 * [1 << 16]));
58 }
59 unsigned a3 = (addr >> 32) & 0xFFFF;
60 if (instrbrkpt_[a1][a2][a3] == 0)
61 {
62 if (val == 0)
63 return;
64 instrbrkpt_[a1][a2][a3] = new etiss::uint32[1 << 16];
65 memset(instrbrkpt_[a1][a2][a3], 0, sizeof(etiss::uint32[1 << 16]));
66 }
67 unsigned a4 = (addr >> 48) & 0xFFFF;
68 instrbrkpt_[a1][a2][a3][a4] = val;
69 if (val == 0)
70 { // cleanup
71 bool empty = true;
72 for (unsigned i = 0; i < (1 << 16); i++)
73 {
74 if (instrbrkpt_[a1][a2][a3][i] != 0)
75 {
76 empty = false;
77 break;
78 }
79 }
80 if (!empty)
81 return;
82 delete instrbrkpt_[a1][a2][a3];
83 instrbrkpt_[a1][a2][a3] = 0;
84 for (unsigned i = 0; i < (1 << 16); i++)
85 {
86 if (instrbrkpt_[a1][a2][i] != 0)
87 {
88 empty = false;
89 break;
90 }
91 }
92 if (!empty)
93 return;
94 delete instrbrkpt_[a1][a2];
95 instrbrkpt_[a1][a2] = 0;
96 for (unsigned i = 0; i < (1 << 16); i++)
97 {
98 if (instrbrkpt_[a1][i] != 0)
99 {
100 empty = false;
101 break;
102 }
103 }
104 if (!empty)
105 return;
106 delete instrbrkpt_[a1];
107 instrbrkpt_[a1] = 0;
108 for (unsigned i = 0; i < (1 << 16); i++)
109 {
110 if (instrbrkpt_[i] != 0)
111 {
112 empty = false;
113 break;
114 }
115 }
116 if (!empty)
117 return;
118 delete instrbrkpt_;
119 instrbrkpt_ = 0;
120 }
121}
122
124{
125 status_paused_ = true;
126 gdb_status_paused_ = true;
127 status_step_ = false;
128 status_pending_jump_ = false;
129 status_pending_kill_ = false;
130 status_jumpaddr_ = false;
131 arch_ = nullptr;
132 cpu_ = nullptr;
133 system_ = nullptr;
137}
138
140{
141 // check for instruction breakpoints
143 {
145 if (unlikely(bp != 0))
146 {
148 {
149 status_paused_ = true;
150 }
151 }
152 }
153 // apply single step pause
154 if (unlikely(status_step_ > 0))
155 {
156 status_paused_ = true;
157 status_step_--;
158 }
160 {
161 return RETURNCODE::CPUTERMINATED;
162 }
163 // check paused state (due to singlestep,ctrl+c)
165 {
167 { // answer pending 'c'/'s' command
168 // std::cout << "GDB: answer: " << "T"<<hex::fromByte(5) << std::endl;
169 con_.snd("T" + hex::fromByte(5), false);
170 gdb_status_paused_ = true;
171 }
172
173 while (unlikely(status_paused_))
174 {
175 handlePacket(true);
177 {
178 return RETURNCODE::CPUTERMINATED;
179 }
181 {
183 status_pending_jump_ = false;
184 }
185 }
186 }
187
188 return RETURNCODE::NOERROR;
189}
190
191etiss::int32 Server::execute()
192{
193
195 {
196 return RETURNCODE::CPUTERMINATED;
197 }
198
200 { // connections such as tcp sockets have a large overhead. to provide acceptable performance packet checks may not
201 // be performed too frequent
203 // check for BREAK event in between blocks
204 handlePacket(false);
205 }
207 {
208 return RETURNCODE::CPUTERMINATED;
209 }
210
211 return 0;
212}
213
214static void Server_finalizeInstrSet(etiss::instr::InstructionSet *set, std::string pcode)
215{
216 if (set == nullptr)
217 return;
218 set->foreach (
219 [pcode](etiss::instr::Instruction &instr)
220 {
221 instr.addCallback(
223 {
225 cp.code() = std::string("{\n"
226 "\tetiss_int32 _gdb_exception = gdb_pre_instruction(cpu,system,") +
227 pcode +
228 ");\n"
229 "\tif (_gdb_exception != 0)\n\t return _gdb_exception==-16?0:_gdb_exception;\n"
230 "}";
231 return true;
232 },
233 0);
235 });
236}
237
239{
240 std::string pcode = getPointerCode();
241 mis.foreach (
243 { vis.foreach ([pcode](etiss::instr::InstructionSet &set) { Server_finalizeInstrSet(&set, pcode); }); });
244}
245
247{
248
249 cb.fileglobalCode().insert("extern etiss_int32 gdb_pre_instruction(ETISS_CPU * ,ETISS_System * ,void * );extern "
250 "void gdb_pre_instruction_noreturn(ETISS_CPU * ,ETISS_System * ,void * );");
251}
252
253void Server::handlePacket(bool block)
254{
255
256 if (con_.available(block))
257 {
258 bool isnotification;
259 std::string command = con_.rcv(isnotification);
260 if (command.length() > 0)
261 {
262 if (!status_paused_)
263 {
265 { // answer pending 'c'/'s' command
266 // std::cout << "GDB: answer: " << "T"<<hex::fromByte(5) << std::endl;
267 con_.snd("T" + hex::fromByte(5), false);
268 gdb_status_paused_ = true;
269 }
270 status_paused_ = true;
271 }
272 bool nodbgaction = false;
273 std::string answer;
274 bool answerisnotification = false;
275 switch (command[0])
276 {
277 case 'g': // read registers
278 {
279 for (unsigned i = 0; i < arch_->getGDBCore().mappedRegisterCount(); i++)
280 {
281 std::string regname = arch_->getGDBCore().mapRegister(i);
282 auto f = plugin_core_->getStruct()->findName(regname);
283 if (!f)
284 {
285 answer = "EFF";
286 etiss::log(etiss::ERROR, "Faulty implementation of the GDBCore: Register not found", regname,
287 *plugin_core_);
288 break;
289 }
290 switch (f->width_)
291 {
292 case 1:
293 hex::fromInt(answer, (uint8_t)f->read(), arch_->getGDBCore().isLittleEndian());
294 break;
295 case 2:
296 hex::fromInt(answer, (uint16_t)f->read(), arch_->getGDBCore().isLittleEndian());
297 break;
298 case 4:
299 hex::fromInt(answer, (uint32_t)f->read(), arch_->getGDBCore().isLittleEndian());
300 break;
301 case 8:
302 hex::fromInt(answer, (uint64_t)f->read(), arch_->getGDBCore().isLittleEndian());
303 break;
304 default:
305 answer = "EFF";
306 etiss::log(etiss::ERROR, "GDB g: Invalid read length");
307 }
308 }
309 }
310 break;
311 case 'G': // write registers
312 {
313 size_t treglen = 0;
314 for (unsigned i = 0; i < arch_->getGDBCore().mappedRegisterCount(); i++)
315 {
316 auto f = plugin_core_->getStruct()->findName(arch_->getGDBCore().mapRegister(i));
317 if (!f)
318 {
319 answer = "EFF";
320 etiss::log(etiss::ERROR, "Faulty implementation of the GDBCore: Register not found",
322 break;
323 }
324 treglen += f->width_;
325 }
326 if (command.length() == (treglen * 2) + 1)
327 {
328 answer = "OK";
329 size_t off = 1;
330 for (unsigned i = 0; i < arch_->getGDBCore().mappedRegisterCount(); i++)
331 {
332 std::string regname = arch_->getGDBCore().mapRegister(i);
333 auto f = plugin_core_->getStruct()->findName(regname);
334 if (!f)
335 {
336 answer = "EFF";
337 etiss::log(etiss::ERROR, "Faulty implementation of the GDBCore: Register not found",
338 regname, *plugin_core_);
339 break;
340 }
341 switch (f->width_)
342 {
343 case 1:
344 f->write(hex::toInt<uint8_t>(command, arch_->getGDBCore().isLittleEndian(), off));
345 break;
346 case 2:
347 f->write(hex::toInt<uint16_t>(command, arch_->getGDBCore().isLittleEndian(), off));
348 break;
349 case 4:
350 f->write(hex::toInt<uint32_t>(command, arch_->getGDBCore().isLittleEndian(), off));
351 break;
352 case 8:
353 f->write(hex::toInt<uint64_t>(command, arch_->getGDBCore().isLittleEndian(), off));
354 break;
355 default:
356 answer = "EFF";
357 etiss::log(etiss::ERROR, "GDB G: Invalid write length");
358 }
359 off += f->width_ * 2;
360 }
361 }
362 else
363 {
364 answer = "E11";
365 }
366 }
367 break;
368 case 'P': // write a register
369 {
370 const size_t off = 1;
371 unsigned regIndex = 0;
372 std::string valToWrite;
373 if (command.length() > 1)
374 {
375 for (size_t i = 1; i < command.length(); ++i)
376 {
377 if (command[i] == '=' && command.length() > i + 1)
378 {
379 valToWrite = command.substr(i + 1);
380 break;
381 }
382 regIndex = (regIndex << 4) | hex::fromHex(command[i]);
383 answer = "OK";
384 }
385 }
386 auto f = plugin_core_->getStruct()->findName(arch_->getGDBCore().mapRegister(regIndex));
387 if (!f)
388 {
389 answer = "EFF";
390 etiss::log(etiss::ERROR, "Faulty implementation of the GDBCore: Register not found",
392 break;
393 }
394 switch (f->width_)
395 {
396 case 1:
397 f->write(hex::toInt<uint8_t>(valToWrite, arch_->getGDBCore().isLittleEndian(), off));
398 break;
399 case 2:
400 f->write(hex::toInt<uint16_t>(valToWrite, arch_->getGDBCore().isLittleEndian(), off));
401 break;
402 case 4:
403 f->write(hex::toInt<uint32_t>(valToWrite, arch_->getGDBCore().isLittleEndian(), off));
404 break;
405 case 8:
406 f->write(hex::toInt<uint64_t>(valToWrite, arch_->getGDBCore().isLittleEndian(), off));
407 break;
408 default:
409 answer = "EFF";
410 etiss::log(etiss::ERROR, "GDB P: Invalid write length");
411 }
412 // off += f->width_ * 2;
413 }
414 break;
415 case 'p': // read a register
416 {
417 unsigned regIndex = 0;
418 if (command.length() > 1)
419 {
420 for (size_t i = 1; i < command.length(); ++i)
421 {
422 regIndex = (regIndex << 4) | hex::fromHex(command[i]);
423 }
424 }
425 auto f = plugin_core_->getStruct()->findName(arch_->getGDBCore().mapRegister(regIndex));
426 if (!f)
427 {
428 answer = "EFF";
429 etiss::log(etiss::ERROR, "Faulty implementation of the GDBCore: Register not found",
431 break;
432 }
433 switch (f->width_)
434 {
435 case 1:
436 hex::fromInt(answer, (uint8_t)f->read(0), arch_->getGDBCore().isLittleEndian());
437 break;
438 case 2:
439 hex::fromInt(answer, (uint16_t)f->read(0), arch_->getGDBCore().isLittleEndian());
440 break;
441 case 4:
442 hex::fromInt(answer, (uint32_t)f->read(0), arch_->getGDBCore().isLittleEndian());
443 break;
444 case 8:
445 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
446 break;
447 case 16: // 128 bits
449 {
450 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
451 hex::fromInt(answer, (uint64_t)f->read(1), arch_->getGDBCore().isLittleEndian());
452 }
453 else
454 {
455 hex::fromInt(answer, (uint64_t)f->read(1), arch_->getGDBCore().isLittleEndian());
456 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
457 }
458 break;
459 case 32: // 256 bits
461 {
462 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
463 hex::fromInt(answer, (uint64_t)f->read(1), arch_->getGDBCore().isLittleEndian());
464 hex::fromInt(answer, (uint64_t)f->read(2), arch_->getGDBCore().isLittleEndian());
465 hex::fromInt(answer, (uint64_t)f->read(3), arch_->getGDBCore().isLittleEndian());
466 }
467 else
468 {
469 hex::fromInt(answer, (uint64_t)f->read(3), arch_->getGDBCore().isLittleEndian());
470 hex::fromInt(answer, (uint64_t)f->read(2), arch_->getGDBCore().isLittleEndian());
471 hex::fromInt(answer, (uint64_t)f->read(1), arch_->getGDBCore().isLittleEndian());
472 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
473 }
474 break;
475 case 64: // 512 bits
477 {
478 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
479 hex::fromInt(answer, (uint64_t)f->read(1), arch_->getGDBCore().isLittleEndian());
480 hex::fromInt(answer, (uint64_t)f->read(2), arch_->getGDBCore().isLittleEndian());
481 hex::fromInt(answer, (uint64_t)f->read(3), arch_->getGDBCore().isLittleEndian());
482 hex::fromInt(answer, (uint64_t)f->read(4), arch_->getGDBCore().isLittleEndian());
483 hex::fromInt(answer, (uint64_t)f->read(5), arch_->getGDBCore().isLittleEndian());
484 hex::fromInt(answer, (uint64_t)f->read(6), arch_->getGDBCore().isLittleEndian());
485 hex::fromInt(answer, (uint64_t)f->read(7), arch_->getGDBCore().isLittleEndian());
486 }
487 else
488 {
489 hex::fromInt(answer, (uint64_t)f->read(7), arch_->getGDBCore().isLittleEndian());
490 hex::fromInt(answer, (uint64_t)f->read(6), arch_->getGDBCore().isLittleEndian());
491 hex::fromInt(answer, (uint64_t)f->read(5), arch_->getGDBCore().isLittleEndian());
492 hex::fromInt(answer, (uint64_t)f->read(4), arch_->getGDBCore().isLittleEndian());
493 hex::fromInt(answer, (uint64_t)f->read(3), arch_->getGDBCore().isLittleEndian());
494 hex::fromInt(answer, (uint64_t)f->read(2), arch_->getGDBCore().isLittleEndian());
495 hex::fromInt(answer, (uint64_t)f->read(1), arch_->getGDBCore().isLittleEndian());
496 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
497 }
498 break;
499 case 128: // 1024 bits
501 {
502 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
503 hex::fromInt(answer, (uint64_t)f->read(1), arch_->getGDBCore().isLittleEndian());
504 hex::fromInt(answer, (uint64_t)f->read(2), arch_->getGDBCore().isLittleEndian());
505 hex::fromInt(answer, (uint64_t)f->read(3), arch_->getGDBCore().isLittleEndian());
506 hex::fromInt(answer, (uint64_t)f->read(4), arch_->getGDBCore().isLittleEndian());
507 hex::fromInt(answer, (uint64_t)f->read(5), arch_->getGDBCore().isLittleEndian());
508 hex::fromInt(answer, (uint64_t)f->read(6), arch_->getGDBCore().isLittleEndian());
509 hex::fromInt(answer, (uint64_t)f->read(7), arch_->getGDBCore().isLittleEndian());
510 hex::fromInt(answer, (uint64_t)f->read(8), arch_->getGDBCore().isLittleEndian());
511 hex::fromInt(answer, (uint64_t)f->read(9), arch_->getGDBCore().isLittleEndian());
512 hex::fromInt(answer, (uint64_t)f->read(10), arch_->getGDBCore().isLittleEndian());
513 hex::fromInt(answer, (uint64_t)f->read(11), arch_->getGDBCore().isLittleEndian());
514 hex::fromInt(answer, (uint64_t)f->read(12), arch_->getGDBCore().isLittleEndian());
515 hex::fromInt(answer, (uint64_t)f->read(13), arch_->getGDBCore().isLittleEndian());
516 hex::fromInt(answer, (uint64_t)f->read(14), arch_->getGDBCore().isLittleEndian());
517 hex::fromInt(answer, (uint64_t)f->read(15), arch_->getGDBCore().isLittleEndian());
518 }
519 else
520 {
521 hex::fromInt(answer, (uint64_t)f->read(15), arch_->getGDBCore().isLittleEndian());
522 hex::fromInt(answer, (uint64_t)f->read(14), arch_->getGDBCore().isLittleEndian());
523 hex::fromInt(answer, (uint64_t)f->read(13), arch_->getGDBCore().isLittleEndian());
524 hex::fromInt(answer, (uint64_t)f->read(12), arch_->getGDBCore().isLittleEndian());
525 hex::fromInt(answer, (uint64_t)f->read(11), arch_->getGDBCore().isLittleEndian());
526 hex::fromInt(answer, (uint64_t)f->read(10), arch_->getGDBCore().isLittleEndian());
527 hex::fromInt(answer, (uint64_t)f->read(9), arch_->getGDBCore().isLittleEndian());
528 hex::fromInt(answer, (uint64_t)f->read(8), arch_->getGDBCore().isLittleEndian());
529 hex::fromInt(answer, (uint64_t)f->read(7), arch_->getGDBCore().isLittleEndian());
530 hex::fromInt(answer, (uint64_t)f->read(6), arch_->getGDBCore().isLittleEndian());
531 hex::fromInt(answer, (uint64_t)f->read(5), arch_->getGDBCore().isLittleEndian());
532 hex::fromInt(answer, (uint64_t)f->read(4), arch_->getGDBCore().isLittleEndian());
533 hex::fromInt(answer, (uint64_t)f->read(3), arch_->getGDBCore().isLittleEndian());
534 hex::fromInt(answer, (uint64_t)f->read(2), arch_->getGDBCore().isLittleEndian());
535 hex::fromInt(answer, (uint64_t)f->read(1), arch_->getGDBCore().isLittleEndian());
536 hex::fromInt(answer, (uint64_t)f->read(0), arch_->getGDBCore().isLittleEndian());
537 }
538 break;
539 default:
540 answer = "EFF";
541 etiss::log(etiss::ERROR, "GDB p: Invalid read length");
542 }
543 }
544 break;
545 case 'm': // read memory
546 {
547 unsigned pos = 1;
548 etiss::uint64 addr = hex::tryInt<etiss::uint64>(command, pos);
549 pos++;
550 etiss::uint32 length = hex::tryInt<etiss::uint32>(command, pos);
551 etiss::uint8 *buf = new etiss::uint8[length];
552 etiss::int32 exception = (*system_->dbg_read)(system_->handle, addr, buf, length);
553 if (exception != RETURNCODE::NOERROR)
554 {
555 answer = "EFF";
556 }
557 else
558 {
559 answer = hex::fromBytes(buf, length);
560 }
561 delete[] buf;
562 }
563 break;
564 case 'M': // writes memory
565 {
566 unsigned pos = 1;
567 etiss::uint64 addr = hex::tryInt<etiss::uint64>(command, pos);
568 pos++; // comma
569 etiss::uint32 length = hex::tryInt<etiss::uint32>(command, pos);
570 pos++; // colon
571 std::vector<etiss::uint8> buf(length);
572 for (etiss::uint32 i = 0; i < length; i++)
573 {
574 buf[i] = hex::tryInt<etiss::uint8>(command, pos);
575 }
576 etiss::int32 exception = (*system_->dbg_write)(system_->handle, addr, buf.data(), length);
577 if (exception != RETURNCODE::NOERROR)
578 {
579 answer = "EFF";
580 }
581 else
582 {
583 answer = "OK";
584 }
585 }
586 break;
587 case 'c': // continue
588 {
589 if (command.length() > 1)
590 {
591 etiss::uint64 addr = 0;
592 for (size_t i = 1; i < command.length(); i += 2)
593 {
594 addr = (addr << 8) | hex::toByte(command[i], command[i + 1]);
595 }
596 status_jumpaddr_ = addr;
598 }
599 status_paused_ = false;
600 gdb_status_paused_ = false;
601 status_step_ = 0;
602 // std::cout << "GDB: command: " << command << std::endl;
603 return;
604 }
605 break;
606 case 's':
607 {
608 if (command.length() > 1)
609 {
610 etiss::uint64 addr = 0;
611 for (size_t i = 1; i < command.length(); i += 2)
612 {
613 addr = (addr << 8) | hex::toByte(command[i], command[i + 1]);
614 }
615 status_jumpaddr_ = addr;
617 }
618 status_paused_ = false;
619 gdb_status_paused_ = false;
620 status_step_ = 1;
621 // std::cout << "GDB: command: " << command << std::endl;
622 return;
623 }
624 case '?':
625 {
626 answer = "T";
627 hex::fromByte(answer, 5);
628 }
629 break;
630 case 'v':
631 break;
632 case 'W': // custom break message; might be changed in future if W is used (apply changes also to
633 // Connection::BREAKMESSAGE)
634 {
635 status_paused_ = true;
636 return;
637 }
638 break;
639 case 'Z': // insert breakpoint
640 {
641 if (command.length() > 2 && command[2] == ',')
642 {
643 BreakpointDB *bpDB = nullptr;
644 etiss::uint32 requestedFlags = 0;
645 switch (command[1])
646 {
647 case '0':
648 bpDB = &breakpoints_;
649 requestedFlags = BreakpointDB::BPTYPE_BREAK_MEM;
650 break;
651 case '1':
652 bpDB = &breakpoints_;
653 requestedFlags = BreakpointDB::BPTYPE_BREAK_HW;
654 break;
655 case '2':
656 bpDB = &watchpoints_;
657 requestedFlags = BreakpointDB::BPTYPE_WATCH_WRITE;
658 break;
659 case '3':
660 bpDB = &watchpoints_;
661 requestedFlags = BreakpointDB::BPTYPE_WATCH_READ;
662 break;
663 case '4':
664 bpDB = &watchpoints_;
666 break;
667 }
668 if (bpDB)
669 {
670 unsigned pos = 3;
671 etiss::uint64 addr = hex::tryInt<etiss::uint64>(command, pos);
672 if (pos > 3)
673 {
674 if (bpDB == &breakpoints_)
675 {
676 addr = addr >> minimal_pc_alignment;
677 }
678 etiss::uint32 existingFlags = bpDB->get(addr);
679 if ((existingFlags & requestedFlags) != requestedFlags)
680 {
681 bpDB->set(addr, existingFlags | requestedFlags);
682 }
683 answer = "OK";
684 }
685 else
686 {
687 answer = "EFF";
688 }
689 }
690 }
691 }
692 break;
693 case 'z': // remove breakpoint
694 {
695 if (command.length() > 2 && command[2] == ',')
696 {
697 BreakpointDB *bpDB = nullptr;
698 etiss::uint32 flagsToDelete = 0;
699 switch (command[1])
700 {
701 case '0':
702 bpDB = &breakpoints_;
703 flagsToDelete = BreakpointDB::BPTYPE_BREAK_MEM;
704 break;
705 case '1':
706 bpDB = &breakpoints_;
707 flagsToDelete = BreakpointDB::BPTYPE_BREAK_HW;
708 break;
709 case '2':
710 bpDB = &watchpoints_;
711 flagsToDelete = BreakpointDB::BPTYPE_WATCH_WRITE;
712 break;
713 case '3':
714 bpDB = &watchpoints_;
715 flagsToDelete = BreakpointDB::BPTYPE_WATCH_READ;
716 break;
717 case '4':
718 bpDB = &watchpoints_;
720 break;
721 }
722
723 if (bpDB)
724 {
725 unsigned pos = 3;
726 etiss::uint64 addr = hex::tryInt<etiss::uint64>(command, pos);
727 addr = addr >> minimal_pc_alignment;
728 if (pos > 3)
729 {
730 etiss::uint32 existingFlags = bpDB->get(addr);
731 if ((existingFlags & flagsToDelete) != 0)
732 {
733 bpDB->set(addr, existingFlags & ~flagsToDelete);
734 }
735 answer = "OK";
736 }
737 else
738 {
739 answer = "EFF";
740 }
741 }
742 }
743 }
744 break;
745 case 'q':
746 {
747 if (command.substr(1, 9) == "Supported")
748 {
749 answer = "PacketSize=8000;qXfer:features:read+;";
750 }
751 else if (command.substr(1, 8) == "Attached")
752 {
753 answer = "0";
754 }
755 else if (command.substr(1, 8) == "Symbol::")
756 {
757 answer = "OK";
758 }
759 else if (command.substr(1, 1) == "C")
760 {
761 answer = "0";
762 }
763 else if (command.substr(1, 7) == "TStatus")
764 {
765 answer = "T0;tnotrun:0";
766 }
767 else if (command.substr(1, 11) == "fThreadInfo")
768 {
769 answer = "m1";
770 }
771 else if (command.substr(1, 11) == "sThreadInfo")
772 {
773 answer = "l";
774 }
775 else if (command.substr(1, 4) == "Xfer")
776 {
777 char fname_buf[256];
778 std::string target_reqxml_fname;
779 uint32_t target_reqxml_addr;
780 uint32_t target_reqxml_len;
781 sscanf(command.c_str(), "qXfer:features:read:%255[^:]:%x,%x", fname_buf, &target_reqxml_addr,
782 &target_reqxml_len);
783 target_reqxml_fname = fname_buf;
784 std::string xml_contents =
785 arch_->getGDBCore().getXMLContents(cpu_, arch_->getArchName(), target_reqxml_fname);
786 uint32_t xml_len = xml_contents.length();
787 if (target_reqxml_len >= (xml_len - target_reqxml_addr))
788 {
789 answer = "l";
790 answer += xml_contents.substr(target_reqxml_addr, xml_len - target_reqxml_addr);
791 }
792 else
793 {
794 answer = "m";
795 answer += xml_contents.substr(target_reqxml_addr, target_reqxml_len);
796 }
797 }
798 }
799 break;
800 case 'k':
801 {
803 return;
804 }
805 break;
806 case 'H':
807 if (command.length() > 1)
808 {
809 switch (command[1])
810 {
811 case 'c':
812 case 'g':
813 answer = "OK"; // only one thread. ignore thread selection and continue
814 break;
815 default:
816 std::cout << "GDB: unknown command: " << command << std::endl;
817 }
818 }
819 else
820 {
821 // std::cout << "GDB: unknown command: " << command << std::endl;
822 }
823 break;
824 default:
825 std::cout << "GDB: unknown command: " << command << std::endl;
826 break;
827 }
828 if (!nodbgaction)
829 {
830 // std::cout << "GDB: command: " << command << std::endl;
831 // std::cout << "GDB: answer: "<<answer << std::endl;
832 }
833 con_.snd(answer, answerisnotification);
834 }
835 }
836}
837
838void Server::preDReadCallback(etiss::uint64 addr)
839{
840 if (!watchpoints_.isEmpty())
841 {
843 {
844 status_paused_ = true;
845 }
846 }
847}
848void Server::preDWriteCallback(etiss::uint64 addr)
849{
850 if (!watchpoints_.isEmpty())
851 {
853 {
854 status_paused_ = true;
855 }
856 }
857}
858
859etiss::int32 Server::postMemAccessCallback(etiss::int32 exception)
860{
861 if (exception)
862 {
863 status_paused_ = true;
864 }
865
866 if (status_paused_)
867 {
869 {
870 con_.snd("T" + hex::fromByte(5), false);
871 gdb_status_paused_ = true;
872 }
873
874 while (unlikely(status_paused_))
875 {
876 handlePacket(true);
878 {
879 return RETURNCODE::CPUTERMINATED;
880 }
882 {
884 status_pending_jump_ = false;
885 exception = RETURNCODE::NOERROR;
886 }
887 }
888 }
889
890 return exception;
891}
892
893std::string Server::_getPluginName() const
894{
895 return "gdbserver";
896}
897
899{
900 return (void *)this;
901}
902
904{
905 arch_ = arch;
906 cpu_ = cpu;
907 system_ = system;
908}
909
911{
912 arch_ = nullptr;
913 cpu_ = nullptr;
914 system_ = nullptr;
915}
916
917Server *Server::createTCPServer(std::map<std::string, std::string> options)
918{
919 int port = 2222;
920
921 { // parse port
922 auto f = options.find("plugin.gdbserver.port");
923 if (f != options.end())
924 {
925 int tmp = atoi(f->second.c_str());
926 if (tmp > 0)
927 port = tmp;
928 else
930 std::string("etiss::plugin::gdb::Server: failed to parse port value for tcp socket: ") +
931 f->second);
932 }
933 }
934
935 Server *s = createTCPServer(port);
936
937 { // parse skip count
938 auto f = options.find("skipcount");
939 if (f != options.end())
940 {
941 int tmp = atoi(f->second.c_str());
942 if (tmp >= 0)
943 s->execute_skip_count = tmp;
944 }
945 }
946
947 { // parse Minimal pc alignment
948
949 auto f = options.find("minPcAlign");
950 if (f != options.end())
951 {
952 int tmp = atoi(f->second.c_str());
953 if (tmp >= 0)
954 s->minimal_pc_alignment = tmp;
955 }
956 }
957 return s;
958}
960{
961
962#if ETISS_USE_POSIX_SOCKET
964 std::string("etiss::plugin::gdb::Server: starting tcp server on port ") + etiss::toString(port));
965
966 std::shared_ptr<Connection> cs(new etiss::plugin::gdb::UnixTCPGDBConnection(port));
967
968 Server *s = new Server(cs.get()->getPacketProtocol());
969
970 s->cinst_ = cs;
971
972 return s;
973#else
974
975 return 0;
976
977#endif
978}
979
980extern "C"
981{
983 {
984 return ((etiss::plugin::gdb::Server *)gdbserver)->preInstructionCallback();
985 }
987 {
989 ((etiss::plugin::gdb::Server *)gdbserver)->preInstructionCallback();
990 }
991}
ETISS_PLUGIN_EXPORT etiss::CPUArch std::map< std::string, std::string > options
create new instance of the CPUArch type at index
contains neccesary interfaces for instruction translation.
defines main cpu core interface
etiss_int32 gdb_pre_instruction(ETISS_CPU *cpu, ETISS_System *system, void *gdbserver)
static void Server_finalizeInstrSet(etiss::instr::InstructionSet *set, std::string pcode)
void gdb_pre_instruction_noreturn(ETISS_CPU *, ETISS_System *, void *gdbserver)
contains container classes to store instruction definitions + translation functions and build a trans...
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
__device__ __2f16 float bool s
static __inline__ uint32_t
Definition arm_cde.h:25
static __inline__ uint64_t
Definition arm_cde.h:31
static __inline__ uint8_t
Definition arm_mve.h:323
static __inline__ uint16_t
Definition arm_mve.h:315
#define unlikely(x)
Definition types.h:36
int32_t etiss_int32
Definition types.h:54
the interface to translate instructions of and processor architecture
Definition CPUArch.h:116
virtual etiss::plugin::gdb::GDBCore & getGDBCore()
returns arch dependent gdb functions.
Definition CPUArch.cpp:113
std::string getArchName() const
returns the name of this architecture.
Definition CPUArch.cpp:47
virtual std::shared_ptr< VirtualStruct > getStruct()
Get the virtual structure of this CPUCore instance.
Definition CPUCore.h:122
A list of CodeSets.
Definition CodePart.h:532
std::set< std::string > & fileglobalCode()
Definition CodePart.h:566
Contains a small code snipped.
Definition CodePart.h:348
@ PREINITIALDEBUGRETURNING
Definition CodePart.h:359
std::string & code()
Definition CodePart.h:378
A set of CodeParts.
Definition CodePart.h:399
CodePart & prepend(CodePart::TYPE type)
Definition CodePart.h:465
CPUCore * plugin_core_
holds a pointer to the associated CPUCore instance.
Definition Plugin.h:160
std::string getPointerCode() const
returns a C code expression that allows to get or assign a pointer to the variable assigned to this t...
Definition Plugin.cpp:63
stores a bit vector
this class contains parameters that persist in between instruction lookpus/translation within a trans...
holds etiss::instr::Instruction instances and handles automatic instruction tree creation.
void foreach(std::function< void(Instruction &)> func)
holds information and translation callbacks for an instruction.
bool addCallback(std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback, uint32_t builtinGroups, const std::set< uint32_t > &groups=std::set< uint32_t >())
holds etiss::instr::VariableInstructionSet instances for different modes.
void foreach(std::function< void(VariableInstructionSet &)> call)
holds etiss::instr::InstructionSet instances with different bit widths.
void foreach(std::function< void(InstructionSet &)> func)
structure to store breakpoints
Definition GDBServer.h:39
etiss::uint32 **** instrbrkpt_
important: index maps are reversed to instruction pointer e.g pointer(0x0102030405060708) [POINTER !...
Definition GDBServer.h:77
void set(etiss::uint64 addr, etiss::uint32 val)
Definition GDBServer.cpp:34
etiss::uint32 get(etiss::uint64 addr)
Definition GDBServer.h:52
virtual etiss::uint64 getInstructionPointer(ETISS_CPU *cpu)
allows to calculate the index of the instruction to be executed for breakpoint checks.
Definition GDBCore.cpp:46
virtual std::string mapRegister(unsigned index)
the returned string identifies the register at the given index as defined by gdb.
Definition GDBCore.cpp:30
virtual bool isLittleEndian()
returns true if the values are expected to be little endian
Definition GDBCore.cpp:42
virtual std::string getXMLContents(ETISS_CPU *cpu, std::string archName, std::string fname)
Definition GDBCore.cpp:57
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)
gdb server implementation that is used as a plugin in etiss
Definition GDBServer.h:85
void cleanup() override
this function is called after cpu execution loop (etiss::CPUCore::execute) finished.
etiss::int32 postMemAccessCallback(etiss::int32 exception)
std::string _getPluginName() const override
void * getPluginHandle() override
called to get the handle that is available in translated code via getPoinerCode()....
etiss::int32 execute() override
called before a block and may act in the same way as a block
etiss::plugin::gdb::PacketProtocol & con_
Definition GDBServer.h:117
void init(ETISS_CPU *cpu, ETISS_System *system, CPUArch *arch) override
this function is called before the plugin is used in the cpu execution loop (etiss::CPUCore::execute)...
Server(etiss::plugin::gdb::PacketProtocol &pp)
void finalizeInstrSet(etiss::instr::ModedInstructionSet &) const override
called after all instructions have been added to allow last changes
void finalizeCodeBlock(etiss::CodeBlock &) const override
called after all instructions have been translated for the code block
void preDWriteCallback(etiss::uint64 addr)
void handlePacket(bool block)
static Server * createTCPServer(std::map< std::string, std::string > options)
etiss::uint64 status_jumpaddr_
Definition GDBServer.h:127
void preDReadCallback(etiss::uint64 addr)
etiss::int32 preInstructionCallback()
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
std::string fromBytes(uint8_t *buf, size_t length)
converts a sequence of bytes to a representing hex string (without "0x" prefix)
Definition Hex.cpp:76
uint8_t fromHex(char c)
convert a character to the hex value it represents(0-15)
Definition Hex.cpp:18
void fromInt(std::string &string, INT val, bool isLittleEndian)
converts an integer type variable to a hexadecimal representation with the given endianness
Definition Hex.h:93
std::string toString(const T &val)
conversion of type T to std::string.
Definition Misc.h:133
@ VERBOSE
Definition Misc.h:88
@ ERROR
Definition Misc.h:85
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94
float __ovld __cnfn length(float p)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
basic cpu state structure needed for execution of any cpu architecture.
Definition CPU.h:51
etiss_uint64 instructionPointer
pointer to next instruction.
Definition CPU.h:54
memory access and time synchronization functions.
Definition System.h:40
void * handle
custom handle that will be passed to the functions of this structure
Definition System.h:81
etiss_int32(* dbg_write)(void *handle, etiss_uint64 addr, etiss_uint8 *buffer, etiss_uint32 length)
direct debug write
Definition System.h:70
etiss_int32(* dbg_read)(void *handle, etiss_uint64 addr, etiss_uint8 *buffer, etiss_uint32 length)
direct debug read
Definition System.h:66