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