gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
remote_gdb.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2015 LabWare
3  * Copyright 2014 Google, Inc.
4  * Copyright (c) 2002-2005 The Regents of The University of Michigan
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met: redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer;
11  * redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution;
14  * neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Authors: Nathan Binkert
31  * Boris Shingarov
32  */
33 
34 /*
35  * Copyright (c) 1990, 1993 The Regents of the University of California
36  * All rights reserved
37  *
38  * This software was developed by the Computer Systems Engineering group
39  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
40  * contributed to Berkeley.
41  *
42  * All advertising materials mentioning features or use of this software
43  * must display the following acknowledgement:
44  * This product includes software developed by the University of
45  * California, Lawrence Berkeley Laboratories.
46  *
47  * Redistribution and use in source and binary forms, with or without
48  * modification, are permitted provided that the following conditions
49  * are met:
50  * 1. Redistributions of source code must retain the above copyright
51  * notice, this list of conditions and the following disclaimer.
52  * 2. Redistributions in binary form must reproduce the above copyright
53  * notice, this list of conditions and the following disclaimer in the
54  * documentation and/or other materials provided with the distribution.
55  * 3. All advertising materials mentioning features or use of this software
56  * must display the following acknowledgement:
57  * This product includes software developed by the University of
58  * California, Berkeley and its contributors.
59  * 4. Neither the name of the University nor the names of its contributors
60  * may be used to endorse or promote products derived from this software
61  * without specific prior written permission.
62  *
63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73  * SUCH DAMAGE.
74  *
75  * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
76  */
77 
78 /*-
79  * Copyright (c) 2001 The NetBSD Foundation, Inc.
80  * All rights reserved.
81  *
82  * This code is derived from software contributed to The NetBSD Foundation
83  * by Jason R. Thorpe.
84  *
85  * Redistribution and use in source and binary forms, with or without
86  * modification, are permitted provided that the following conditions
87  * are met:
88  * 1. Redistributions of source code must retain the above copyright
89  * notice, this list of conditions and the following disclaimer.
90  * 2. Redistributions in binary form must reproduce the above copyright
91  * notice, this list of conditions and the following disclaimer in the
92  * documentation and/or other materials provided with the distribution.
93  * 3. All advertising materials mentioning features or use of this software
94  * must display the following acknowledgement:
95  * This product includes software developed by the NetBSD
96  * Foundation, Inc. and its contributors.
97  * 4. Neither the name of The NetBSD Foundation nor the names of its
98  * contributors may be used to endorse or promote products derived
99  * from this software without specific prior written permission.
100  *
101  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
102  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
103  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
104  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
105  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
106  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
107  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
108  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
109  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
110  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
111  * POSSIBILITY OF SUCH DAMAGE.
112  */
113 
114 /*
115  * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
116  *
117  * Taken from NetBSD
118  *
119  * "Stub" to allow remote cpu to debug over a serial line using gdb.
120  */
121 
122 #include "base/remote_gdb.hh"
123 
124 #include <sys/signal.h>
125 #include <unistd.h>
126 
127 #include <csignal>
128 #include <cstdint>
129 #include <cstdio>
130 #include <string>
131 
132 #include "arch/vtophys.hh"
133 #include "base/intmath.hh"
134 #include "base/socket.hh"
135 #include "base/trace.hh"
136 #include "config/the_isa.hh"
137 #include "cpu/base.hh"
138 #include "cpu/static_inst.hh"
139 #include "cpu/thread_context.hh"
140 #include "debug/GDBAll.hh"
142 #include "mem/port.hh"
144 #include "sim/full_system.hh"
145 #include "sim/system.hh"
146 
147 using namespace std;
148 using namespace TheISA;
149 
150 static const char GDBStart = '$';
151 static const char GDBEnd = '#';
152 static const char GDBGoodP = '+';
153 static const char GDBBadP = '-';
154 
155 static const int GDBPacketBufLen = 1024;
156 
157 #ifndef NDEBUG
159 
160 void
162 {
163  static int current_debugger = -1;
164  if (current_debugger >= 0 && current_debugger < (int)debuggers.size()) {
165  BaseRemoteGDB *gdb = debuggers[current_debugger];
166  if (!gdb->isattached())
167  gdb->listener->accept();
168  if (gdb->isattached())
169  gdb->trap(SIGILL);
170  }
171 }
172 #endif
173 
175 //
176 //
177 //
178 
180  : PollEvent(fd, e), listener(l)
181 {}
182 
183 void
185 {
186  listener->accept();
187 }
188 
190  : inputEvent(NULL), gdb(g), port(p)
191 {
192  assert(!gdb->listener);
193  gdb->listener = this;
194 }
195 
197 {
198  delete inputEvent;
199 }
200 
201 string
203 {
204  return gdb->name() + ".listener";
205 }
206 
207 void
209 {
211  warn_once("Sockets disabled, not accepting gdb connections");
212  return;
213  }
214 
215  while (!listener.listen(port, true)) {
216  DPRINTF(GDBMisc, "Can't bind port %d\n", port);
217  port++;
218  }
219 
220  inputEvent = new InputEvent(this, listener.getfd(), POLLIN);
222 
223 #ifndef NDEBUG
224  gdb->number = debuggers.size();
225  debuggers.push_back(gdb);
226 #endif
227 
228 #ifndef NDEBUG
229  ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n",
230  curTick(), name(), gdb->number, port);
231 #else
232  ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
233  curTick(), name(), port);
234 #endif
235 }
236 
237 void
239 {
240  if (!listener.islistening())
241  panic("GDBListener::accept(): cannot accept if we're not listening!");
242 
243  int sfd = listener.accept(true);
244 
245  if (sfd != -1) {
246  if (gdb->isattached())
247  close(sfd);
248  else
249  gdb->attach(sfd);
250  }
251 }
252 
254  : PollEvent(fd, e), gdb(g)
255 {}
256 
257 void
259 {
260  if (gdb->trapEvent.scheduled()) {
261  warn("GDB trap event has already been scheduled! "
262  "Ignoring this input event.");
263  return;
264  }
265 
266  if (revent & POLLIN) {
267  gdb->trapEvent.type(SIGILL);
268  gdb->scheduleInstCommitEvent(&gdb->trapEvent, 0);
269  } else if (revent & POLLNVAL) {
270  gdb->descheduleInstCommitEvent(&gdb->trapEvent);
271  gdb->detach();
272  }
273 }
274 
275 void
277 {
278  gdb->trap(_type);
279 }
280 
281 void
283 {
284  if (!gdb->singleStepEvent.scheduled())
285  gdb->scheduleInstCommitEvent(&gdb->singleStepEvent, 1);
286  gdb->trap(SIGTRAP);
287 }
288 
290  inputEvent(NULL), trapEvent(this), listener(NULL),
291  number(-1), fd(-1), active(false), attached(false), system(_system),
292  context(c), singleStepEvent(this)
293 {
294 }
295 
297 {
298  if (inputEvent)
299  delete inputEvent;
300 }
301 
302 string
304 {
305  return system->name() + ".remote_gdb";
306 }
307 
308 bool
310 { return attached; }
311 
312 void
314 {
315  fd = f;
316 
317  inputEvent = new InputEvent(this, fd, POLLIN);
319 
320  attached = true;
321  DPRINTFN("remote gdb attached\n");
322 }
323 
324 void
326 {
327  attached = false;
328  active = false;
329  clearSingleStep();
330  close(fd);
331  fd = -1;
332 
334  DPRINTFN("remote gdb detached\n");
335 }
336 
338 //
339 //
340 
341 uint8_t
343 {
344  uint8_t b;
345  if (::read(fd, &b, sizeof(b)) == sizeof(b))
346  return b;
347 
348  throw BadClient("Couldn't read data from debugger.");
349 }
350 
351 void
353 {
354  if (::write(fd, &b, sizeof(b)) == sizeof(b))
355  return;
356 
357  throw BadClient("Couldn't write data to the debugger.");
358 }
359 
360 // Send a packet to gdb
361 void
362 BaseRemoteGDB::send(const char *bp)
363 {
364  const char *p;
365  uint8_t csum, c;
366 
367  DPRINTF(GDBSend, "send: %s\n", bp);
368 
369  do {
370  p = bp;
371  // Start sending a packet
372  putbyte(GDBStart);
373  // Send the contents, and also keep a check sum.
374  for (csum = 0; (c = *p); p++) {
375  putbyte(c);
376  csum += c;
377  }
378  // Send the ending character.
379  putbyte(GDBEnd);
380  // Send the checksum.
381  putbyte(i2digit(csum >> 4));
382  putbyte(i2digit(csum));
383  // Try transmitting over and over again until the other end doesn't
384  // send an error back.
385  c = getbyte();
386  } while ((c & 0x7f) == GDBBadP);
387 }
388 
389 // Receive a packet from gdb
390 int
391 BaseRemoteGDB::recv(char *bp, int maxlen)
392 {
393  char *p;
394  uint8_t c;
395  int csum;
396  int len;
397 
398  do {
399  p = bp;
400  csum = len = 0;
401  // Find the beginning of a packet
402  while ((c = getbyte()) != GDBStart);
403 
404  // Read until you find the end of the data in the packet, and keep
405  // track of the check sum.
406  while (len < maxlen) {
407  c = getbyte();
408  if (c == GDBEnd)
409  break;
410  c &= 0x7f;
411  csum += c;
412  *p++ = c;
413  len++;
414  }
415 
416  // Mask the check sum, and terminate the command string.
417  csum &= 0xff;
418  *p = '\0';
419 
420  // If the command was too long, report an error.
421  if (len >= maxlen) {
422  putbyte(GDBBadP);
423  continue;
424  }
425 
426  // Bring in the checksum. If the check sum matches, csum will be 0.
427  csum -= digit2i(getbyte()) * 16;
428  csum -= digit2i(getbyte());
429 
430  // If the check sum was correct
431  if (csum == 0) {
432  // Report that the packet was received correctly
433  putbyte(GDBGoodP);
434  // Sequence present?
435  if (bp[2] == ':') {
436  putbyte(bp[0]);
437  putbyte(bp[1]);
438  len -= 3;
439  memcpy(bp, bp+3, len);
440  }
441  break;
442  }
443  // Otherwise, report that there was a mistake.
444  putbyte(GDBBadP);
445  } while (1);
446 
447  DPRINTF(GDBRecv, "recv: %s\n", bp);
448 
449  return len;
450 }
451 
452 // Read bytes from kernel address space for debugger.
453 bool
455 {
456  static Addr lastaddr = 0;
457  static size_t lastsize = 0;
458 
459  if (vaddr < 10) {
460  DPRINTF(GDBRead, "read: reading memory location zero!\n");
461  vaddr = lastaddr + lastsize;
462  }
463 
464  DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
465 
466  if (FullSystem) {
468  proxy.readBlob(vaddr, (uint8_t*)data, size);
469  } else {
471  proxy.readBlob(vaddr, (uint8_t*)data, size);
472  }
473 
474 #if TRACING_ON
475  if (DTRACE(GDBRead)) {
476  if (DTRACE(GDBExtra)) {
477  char buf[1024];
478  mem2hex(buf, data, size);
479  DPRINTFNR(": %s\n", buf);
480  } else
481  DPRINTFNR("\n");
482  }
483 #endif
484 
485  return true;
486 }
487 
488 // Write bytes to kernel address space for debugger.
489 bool
490 BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
491 {
492  static Addr lastaddr = 0;
493  static size_t lastsize = 0;
494 
495  if (vaddr < 10) {
496  DPRINTF(GDBWrite, "write: writing memory location zero!\n");
497  vaddr = lastaddr + lastsize;
498  }
499 
500  if (DTRACE(GDBWrite)) {
501  DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
502  if (DTRACE(GDBExtra)) {
503  char buf[1024];
504  mem2hex(buf, data, size);
505  DPRINTFNR(": %s\n", buf);
506  } else
507  DPRINTFNR("\n");
508  }
509  if (FullSystem) {
511  proxy.writeBlob(vaddr, (uint8_t*)data, size);
512  } else {
514  proxy.writeBlob(vaddr, (uint8_t*)data, size);
515  }
516 
517  return true;
518 }
519 
520 void
522 {
524 }
525 
526 void
528 {
529  if (!singleStepEvent.scheduled())
531 }
532 
534 {
535  return &system->pcEventQueue;
536 }
537 
538 EventQueue *
540 {
541  BaseCPU *cpu = context->getCpuPtr();
542  return cpu->comInstEventQueue[context->threadId()];
543 }
544 
545 void
547 {
549  // Here "ticks" aren't simulator ticks which measure time, they're
550  // instructions committed by the CPU.
551  eq->schedule(ev, eq->getCurTick() + delta);
552 }
553 
554 void
556 {
557  if (ev->scheduled())
559 }
560 
561 bool
563 {
564  return len == sizeof(MachInst);
565 }
566 
568  : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
569  gdb(_gdb), refcount(0)
570 {
571  DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
572 }
573 
574 void
576 {
577  DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
578 
579  if (tc == gdb->context)
580  gdb->trap(SIGTRAP);
581 }
582 
583 void
585 {
586  if (!checkBpLen(len))
587  throw BadClient("Invalid breakpoint length\n");
588 
589  return insertHardBreak(addr, len);
590 }
591 
592 void
594 {
595  if (!checkBpLen(len))
596  throw BadClient("Invalid breakpoint length.\n");
597 
598  return removeHardBreak(addr, len);
599 }
600 
601 void
603 {
604  if (!checkBpLen(len))
605  throw BadClient("Invalid breakpoint length\n");
606 
607  DPRINTF(GDBMisc, "Inserting hardware breakpoint at %#x\n", addr);
608 
609  HardBreakpoint *&bkpt = hardBreakMap[addr];
610  if (bkpt == 0)
611  bkpt = new HardBreakpoint(this, addr);
612 
613  bkpt->refcount++;
614 }
615 
616 void
618 {
619  if (!checkBpLen(len))
620  throw BadClient("Invalid breakpoint length\n");
621 
622  DPRINTF(GDBMisc, "Removing hardware breakpoint at %#x\n", addr);
623 
624  break_iter_t i = hardBreakMap.find(addr);
625  if (i == hardBreakMap.end())
626  throw CmdError("E0C");
627 
628  HardBreakpoint *hbp = (*i).second;
629  if (--hbp->refcount == 0) {
630  delete hbp;
631  hardBreakMap.erase(i);
632  }
633 }
634 
635 void
637 {
638  DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
639  insertHardBreak(bkpt, sizeof(TheISA::MachInst));
640 }
641 
642 void
644 {
645  DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
646  removeHardBreak(bkpt, sizeof(TheISA::MachInst));
647  bkpt = 0;
648 }
649 
651  GdbSoftBp = '0',
652  GdbHardBp = '1',
653  GdbWriteWp = '2',
654  GdbReadWp = '3',
655  GdbAccWp = '4',
656 };
657 
658 const char *
660 {
661  switch(c) {
662  case GdbSoftBp: return "software breakpoint";
663  case GdbHardBp: return "hardware breakpoint";
664  case GdbWriteWp: return "write watchpoint";
665  case GdbReadWp: return "read watchpoint";
666  case GdbAccWp: return "access watchpoint";
667  default: return "unknown breakpoint/watchpoint";
668  }
669 }
670 
671 std::map<char, GdbCommand> BaseRemoteGDB::command_map = {
672  // last signal
673  { '?', { "KGDB_SIGNAL", &BaseRemoteGDB::cmd_signal } },
674  // set baud (deprecated)
675  { 'b', { "KGDB_SET_BAUD", &BaseRemoteGDB::cmd_unsupported } },
676  // set breakpoint (deprecated)
677  { 'B', { "KGDB_SET_BREAK", &BaseRemoteGDB::cmd_unsupported } },
678  // resume
679  { 'c', { "KGDB_CONT", &BaseRemoteGDB::cmd_cont } },
680  // continue with signal
681  { 'C', { "KGDB_ASYNC_CONT", &BaseRemoteGDB::cmd_async_cont } },
682  // toggle debug flags (deprecated)
683  { 'd', { "KGDB_DEBUG", &BaseRemoteGDB::cmd_unsupported } },
684  // detach remote gdb
685  { 'D', { "KGDB_DETACH", &BaseRemoteGDB::cmd_detach } },
686  // read general registers
687  { 'g', { "KGDB_REG_R", &BaseRemoteGDB::cmd_reg_r } },
688  // write general registers
689  { 'G', { "KGDB_REG_W", &BaseRemoteGDB::cmd_reg_w } },
690  // set thread
691  { 'H', { "KGDB_SET_THREAD", &BaseRemoteGDB::cmd_set_thread } },
692  // step a single cycle
693  { 'i', { "KGDB_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
694  // signal then cycle step
695  { 'I', { "KGDB_SIG_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
696  // kill program
697  { 'k', { "KGDB_KILL", &BaseRemoteGDB::cmd_detach } },
698  // read memory
699  { 'm', { "KGDB_MEM_R", &BaseRemoteGDB::cmd_mem_r } },
700  // write memory
701  { 'M', { "KGDB_MEM_W", &BaseRemoteGDB::cmd_mem_w } },
702  // read register
703  { 'p', { "KGDB_READ_REG", &BaseRemoteGDB::cmd_unsupported } },
704  // write register
705  { 'P', { "KGDB_SET_REG", &BaseRemoteGDB::cmd_unsupported } },
706  // query variable
707  { 'q', { "KGDB_QUERY_VAR", &BaseRemoteGDB::cmd_query_var } },
708  // set variable
709  { 'Q', { "KGDB_SET_VAR", &BaseRemoteGDB::cmd_unsupported } },
710  // reset system (deprecated)
711  { 'r', { "KGDB_RESET", &BaseRemoteGDB::cmd_unsupported } },
712  // step
713  { 's', { "KGDB_STEP", &BaseRemoteGDB::cmd_step } },
714  // signal and step
715  { 'S', { "KGDB_ASYNC_STEP", &BaseRemoteGDB::cmd_async_step } },
716  // find out if the thread is alive
717  { 'T', { "KGDB_THREAD_ALIVE", &BaseRemoteGDB::cmd_unsupported } },
718  // target exited
719  { 'W', { "KGDB_TARGET_EXIT", &BaseRemoteGDB::cmd_unsupported } },
720  // write memory
721  { 'X', { "KGDB_BINARY_DLOAD", &BaseRemoteGDB::cmd_unsupported } },
722  // remove breakpoint or watchpoint
723  { 'z', { "KGDB_CLR_HW_BKPT", &BaseRemoteGDB::cmd_clr_hw_bkpt } },
724  // insert breakpoint or watchpoint
725  { 'Z', { "KGDB_SET_HW_BKPT", &BaseRemoteGDB::cmd_set_hw_bkpt } },
726 };
727 
728 
729 bool
731 {
732  DPRINTF(GDBMisc, "Unsupported command: %s\n", ctx.cmd->name);
733  DDUMP(GDBMisc, ctx.data, ctx.len);
734  throw Unsupported();
735 }
736 
737 
738 bool
740 {
741  send(csprintf("S%02x", ctx.type).c_str());
742  return true;
743 }
744 
745 bool
747 {
748  const char *p = ctx.data;
749  if (ctx.len) {
750  Addr newPc = hex2i(&p);
751  context->pcState(newPc);
752  }
753  clearSingleStep();
754  return false;
755 }
756 
757 bool
759 {
760  const char *p = ctx.data;
761  hex2i(&p);
762  if (*p++ == ';') {
763  Addr newPc = hex2i(&p);
764  context->pcState(newPc);
765  }
766  clearSingleStep();
767  return false;
768 }
769 
770 bool
772 {
773  detach();
774  return false;
775 }
776 
777 bool
779 {
780  char buf[2 * regCachePtr->size() + 1];
781  buf[2 * regCachePtr->size()] = '\0';
782  mem2hex(buf, regCachePtr->data(), regCachePtr->size());
783  send(buf);
784  return true;
785 }
786 
787 bool
789 {
790  const char *p = ctx.data;
791  p = hex2mem(regCachePtr->data(), p, regCachePtr->size());
792  if (p == NULL || *p != '\0')
793  throw CmdError("E01");
794 
796  send("OK");
797 
798  return true;
799 }
800 
801 bool
803 {
804  const char *p = ctx.data + 1; // Ignore the subcommand byte.
805  if (hex2i(&p) != 0)
806  throw CmdError("E01");
807  send("OK");
808  return true;
809 }
810 
811 bool
813 {
814  const char *p = ctx.data;
815  Addr addr = hex2i(&p);
816  if (*p++ != ',')
817  throw CmdError("E02");
818  size_t len = hex2i(&p);
819  if (*p != '\0')
820  throw CmdError("E03");
821  if (!acc(addr, len))
822  throw CmdError("E05");
823 
824  char buf[len];
825  if (!read(addr, len, buf))
826  throw CmdError("E05");
827 
828  char temp[2 * len + 1];
829  temp[2 * len] = '\0';
830  mem2hex(temp, buf, len);
831  send(temp);
832  return true;
833 }
834 
835 bool
837 {
838  const char *p = ctx.data;
839  Addr addr = hex2i(&p);
840  if (*p++ != ',')
841  throw CmdError("E06");
842  size_t len = hex2i(&p);
843  if (*p++ != ':')
844  throw CmdError("E07");
845  if (len * 2 > ctx.len - (p - ctx.data))
846  throw CmdError("E08");
847  char buf[len];
848  p = (char *)hex2mem(buf, p, len);
849  if (p == NULL)
850  throw CmdError("E09");
851  if (!acc(addr, len))
852  throw CmdError("E0A");
853  if (!write(addr, len, buf))
854  throw CmdError("E0B");
855  send("OK");
856  return true;
857 }
858 
859 bool
861 {
862  if (string(ctx.data, ctx.len - 1) != "C")
863  throw Unsupported();
864  send("QC0");
865  return true;
866 }
867 
868 bool
870 {
871  const char *p = ctx.data;
872  hex2i(&p); // Ignore the subcommand byte.
873  if (*p++ == ';') {
874  Addr newPc = hex2i(&p);
875  context->pcState(newPc);
876  }
877  setSingleStep();
878  return false;
879 }
880 
881 bool
883 {
884  if (ctx.len) {
885  const char *p = ctx.data;
886  Addr newPc = hex2i(&p);
887  context->pcState(newPc);
888  }
889  setSingleStep();
890  return false;
891 }
892 
893 bool
895 {
896  const char *p = ctx.data;
897  char subcmd = *p++;
898  if (*p++ != ',')
899  throw CmdError("E0D");
900  Addr addr = hex2i(&p);
901  if (*p++ != ',')
902  throw CmdError("E0D");
903  size_t len = hex2i(&p);
904 
905  DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
906  break_type(subcmd), addr, len);
907 
908  switch (subcmd) {
909  case GdbSoftBp:
910  removeSoftBreak(addr, len);
911  break;
912  case GdbHardBp:
913  removeHardBreak(addr, len);
914  break;
915  case GdbWriteWp:
916  case GdbReadWp:
917  case GdbAccWp:
918  default: // unknown
919  throw Unsupported();
920  }
921  send("OK");
922 
923  return true;
924 }
925 
926 bool
928 {
929  const char *p = ctx.data;
930  char subcmd = *p++;
931  if (*p++ != ',')
932  throw CmdError("E0D");
933  Addr addr = hex2i(&p);
934  if (*p++ != ',')
935  throw CmdError("E0D");
936  size_t len = hex2i(&p);
937 
938  DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
939  break_type(subcmd), addr, len);
940 
941  switch (subcmd) {
942  case GdbSoftBp:
943  insertSoftBreak(addr, len);
944  break;
945  case GdbHardBp:
946  insertHardBreak(addr, len);
947  break;
948  case GdbWriteWp:
949  case GdbReadWp:
950  case GdbAccWp:
951  default: // unknown
952  throw Unsupported();
953  }
954  send("OK");
955 
956  return true;
957 }
958 
959 
960 // This function does all command processing for interfacing to a
961 // remote gdb. Note that the error codes are ignored by gdb at
962 // present, but might eventually become meaningful. (XXX) It might
963 // makes sense to use POSIX errno values, because that is what the
964 // gdb/remote.c functions want to return.
965 bool
967 {
968 
969  if (!attached)
970  return false;
971 
972  DPRINTF(GDBMisc, "trap: PC=%s\n", context->pcState());
973 
974  clearSingleStep();
975 
976  /*
977  * The first entry to this function is normally through
978  * a breakpoint trap in kgdb_connect(), in which case we
979  * must advance past the breakpoint because gdb will not.
980  *
981  * On the first entry here, we expect that gdb is not yet
982  * listening to us, so just enter the interaction loop.
983  * After the debugger is "active" (connected) it will be
984  * waiting for a "signaled" message from us.
985  */
986  if (!active) {
987  active = true;
988  } else {
989  // Tell remote host that an exception has occurred.
990  send(csprintf("S%02x", type).c_str());
991  }
992 
993  // Stick frame regs into our reg cache.
994  regCachePtr = gdbRegs();
996 
997  char data[GDBPacketBufLen + 1];
998  GdbCommand::Context cmdCtx;
999  cmdCtx.type = type;
1000  cmdCtx.data = &data[1];
1001 
1002  for (;;) {
1003  try {
1004  size_t datalen = recv(data, sizeof(data));
1005  if (datalen < 1)
1006  throw BadClient();
1007 
1008  data[datalen] = 0; // Sentinel
1009  cmdCtx.cmd_byte = data[0];
1010  cmdCtx.len = datalen - 1;
1011 
1012  auto cmdIt = command_map.find(cmdCtx.cmd_byte);
1013  if (cmdIt == command_map.end()) {
1014  DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
1015  cmdCtx.cmd_byte, cmdCtx.cmd_byte);
1016  throw Unsupported();
1017  }
1018  cmdCtx.cmd = &(cmdIt->second);
1019 
1020  if (!(this->*(cmdCtx.cmd->func))(cmdCtx))
1021  break;
1022 
1023  } catch (BadClient &e) {
1024  if (e.warning)
1025  warn(e.warning);
1026  detach();
1027  break;
1028  } catch (Unsupported &e) {
1029  send("");
1030  } catch (CmdError &e) {
1031  send(e.error.c_str());
1032  } catch (...) {
1033  panic("Unrecognzied GDB exception.");
1034  }
1035  }
1036 
1037  return true;
1038 }
1039 
1040 // Convert a hex digit into an integer.
1041 // This returns -1 if the argument passed is no valid hex digit.
1042 int
1044 {
1045  if (c >= '0' && c <= '9')
1046  return (c - '0');
1047  else if (c >= 'a' && c <= 'f')
1048  return (c - 'a' + 10);
1049  else if (c >= 'A' && c <= 'F')
1050  return (c - 'A' + 10);
1051  else
1052  return (-1);
1053 }
1054 
1055 // Convert the low 4 bits of an integer into an hex digit.
1056 char
1058 {
1059  return ("0123456789abcdef"[n & 0x0f]);
1060 }
1061 
1062 // Convert a byte array into an hex string.
1063 void
1064 BaseRemoteGDB::mem2hex(char *vdst, const char *vsrc, int len)
1065 {
1066  char *dst = vdst;
1067  const char *src = vsrc;
1068 
1069  while (len--) {
1070  *dst++ = i2digit(*src >> 4);
1071  *dst++ = i2digit(*src++);
1072  }
1073  *dst = '\0';
1074 }
1075 
1076 // Convert an hex string into a byte array.
1077 // This returns a pointer to the character following the last valid
1078 // hex digit. If the string ends in the middle of a byte, NULL is
1079 // returned.
1080 const char *
1081 BaseRemoteGDB::hex2mem(char *vdst, const char *src, int maxlen)
1082 {
1083  char *dst = vdst;
1084  int msb, lsb;
1085 
1086  while (*src && maxlen--) {
1087  msb = digit2i(*src++);
1088  if (msb < 0)
1089  return (src - 1);
1090  lsb = digit2i(*src++);
1091  if (lsb < 0)
1092  return (NULL);
1093  *dst++ = (msb << 4) | lsb;
1094  }
1095  return src;
1096 }
1097 
1098 // Convert an hex string into an integer.
1099 // This returns a pointer to the character following the last valid
1100 // hex digit.
1101 Addr
1102 BaseRemoteGDB::hex2i(const char **srcp)
1103 {
1104  const char *src = *srcp;
1105  Addr r = 0;
1106  int nibble;
1107 
1108  while ((nibble = digit2i(*src)) >= 0) {
1109  r *= 16;
1110  r += nibble;
1111  src++;
1112  }
1113  *srcp = src;
1114  return r;
1115 }
1116 
virtual void setRegs(ThreadContext *) const =0
Set the ThreadContext's registers from the values in the raw buffer.
friend class HardBreakpoint
Definition: remote_gdb.hh:306
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
#define DPRINTF(x,...)
Definition: trace.hh:212
A TranslatingPortProxy in FS mode translates a virtual address to a physical address and then calls t...
const Func func
Definition: remote_gdb.hh:71
void removeSoftBreak(Addr addr, size_t len)
Definition: remote_gdb.cc:593
Bitfield< 29 > eq
Definition: miscregs.hh:50
void descheduleInstCommitEvent(Event *ev)
Deschedule an instruction count based event.
Definition: remote_gdb.cc:555
TrapEvent trapEvent
Definition: remote_gdb.hh:160
void listen()
Definition: remote_gdb.cc:208
std::string name()
Definition: remote_gdb.cc:202
virtual bool read(Addr addr, size_t size, char *data)
Definition: remote_gdb.cc:454
int recv(char *data, int len)
Definition: remote_gdb.cc:391
bool trap(int type)
Definition: remote_gdb.cc:966
HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr)
Definition: remote_gdb.cc:567
virtual bool listen(int port, bool reuse=true)
Definition: socket.cc:90
void insertSoftBreak(Addr addr, size_t len)
Definition: remote_gdb.cc:584
PollQueue pollQueue
Definition: pollevent.cc:55
Bitfield< 7 > i
Definition: miscregs.hh:1378
void deschedule(Event *event)
Deschedule the specified event.
Definition: eventq_impl.hh:69
void send(const char *data)
Definition: remote_gdb.cc:362
#define panic(...)
Definition: misc.hh:153
void clearTempBreakpoint(Addr &bkpt)
Definition: remote_gdb.cc:643
GdbBreakpointType
Definition: remote_gdb.cc:650
break_map_t::iterator break_iter_t
Definition: remote_gdb.hh:309
SingleStepEvent singleStepEvent
Definition: remote_gdb.hh:276
BaseRemoteGDB * gdb
Definition: remote_gdb.hh:357
bool cmd_async_cont(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:758
ip6_addr_t addr
Definition: inet.hh:335
bool cmd_reg_r(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:778
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:381
#define DDUMP(x, data, count)
Definition: trace.hh:211
void process(int revent)
Definition: remote_gdb.cc:258
InputEvent(BaseRemoteGDB *g, int fd, int e)
Definition: remote_gdb.cc:253
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:146
void putbyte(uint8_t b)
Definition: remote_gdb.cc:352
Port Object Declaration.
ListenSocket listener
Definition: remote_gdb.hh:356
void setTempBreakpoint(Addr bkpt)
Definition: remote_gdb.cc:636
void process(int revent)
Definition: remote_gdb.cc:184
#define warn_once(...)
Definition: misc.hh:226
virtual void readBlob(Addr addr, uint8_t *p, int size) const
Read size bytes memory at address and store in p.
Definition: system.hh:83
virtual BaseCPU * getCpuPtr()=0
GDBListener(BaseRemoteGDB *g, int p)
Definition: remote_gdb.cc:189
Addr evpc
Definition: pc_event.hh:49
virtual TheISA::PCState pcState()=0
GDBListener * listener
Definition: remote_gdb.hh:161
System * system
Definition: remote_gdb.hh:172
bool cmd_reg_w(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:788
void debugger()
Definition: remote_gdb.cc:161
void setSingleStep()
Definition: remote_gdb.cc:527
ThreadContext is the external interface to all thread state for anything outside of the CPU...
#define DPRINTFN(...)
Definition: trace.hh:216
virtual char * data() const =0
Return the pointer to the raw bytes buffer containing the register values.
virtual void readBlob(Addr addr, uint8_t *p, int size) const
Version of readblob that translates virt->phys and deals with page boundries.
uint32_t MachInst
Definition: types.hh:40
Bitfield< 31 > n
Definition: miscregs.hh:1636
const char data[]
Definition: circlebuf.cc:43
Bitfield< 6 > f
Definition: miscregs.hh:1379
void schedule(PollEvent *event)
Definition: pollevent.cc:159
void scheduleInstCommitEvent(Event *ev, int delta)
Schedule an event which will be triggered "delta" instructions later.
Definition: remote_gdb.cc:546
#define warn(...)
Definition: misc.hh:219
bool cmd_detach(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:771
Bitfield< 7 > b
Definition: miscregs.hh:1564
ThreadContext * context
Definition: remote_gdb.hh:173
virtual void writeBlob(Addr addr, const uint8_t *p, int size) const
Version of writeBlob that translates virt->phys and deals with page boundries.
BaseGdbRegCache * regCachePtr
Definition: remote_gdb.hh:228
Tick curTick()
The current simulated tick.
Definition: core.hh:47
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
friend class InputEvent
Definition: remote_gdb.hh:352
static const char GDBGoodP
Definition: remote_gdb.cc:152
#define DTRACE(x)
Definition: trace.hh:210
static bool allDisabled()
Definition: socket.cc:61
Bitfield< 4 > g
Definition: dt_constants.hh:85
Queue of events sorted in time order.
Definition: eventq.hh:488
bool cmd_query_var(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:860
static const char GDBEnd
Definition: remote_gdb.cc:151
void clearSingleStep()
Definition: remote_gdb.cc:521
Exception to throw when an error needs to be reported to the client.
Definition: remote_gdb.hh:92
static const char GDBStart
Definition: remote_gdb.cc:150
bool cmd_cont(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:746
virtual bool acc(Addr addr, size_t len)=0
bool cmd_set_thread(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:802
Exception to throw when something isn't supported.
Definition: remote_gdb.hh:99
virtual const char * hex2mem(char *, const char *, int)
Definition: remote_gdb.cc:1081
bool cmd_set_hw_bkpt(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:927
virtual bool checkBpLen(size_t len)
Definition: remote_gdb.cc:562
virtual int accept(bool nodelay=false)
Definition: socket.cc:136
virtual SETranslatingPortProxy & getMemProxy()=0
virtual const char * break_type(char c)
Definition: remote_gdb.cc:659
virtual void getRegs(ThreadContext *)=0
Fill the raw buffer from the registers in the ThreadContext.
const char *const name
Definition: remote_gdb.hh:70
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
virtual bool write(Addr addr, size_t size, const char *data)
Definition: remote_gdb.cc:490
virtual BaseGdbRegCache * gdbRegs()=0
std::string name()
Definition: remote_gdb.cc:303
Addr hex2i(const char **)
Definition: remote_gdb.cc:1102
static const char GDBBadP
Definition: remote_gdb.cc:153
bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:894
bool isattached()
Definition: remote_gdb.cc:309
EventQueue * getComInstEventQueue()
Definition: remote_gdb.cc:539
Bitfield< 9 > e
Definition: miscregs.hh:1376
void accept()
Definition: remote_gdb.cc:238
virtual FSTranslatingPortProxy & getVirtProxy()=0
vector< BaseRemoteGDB * > debuggers
Definition: remote_gdb.cc:158
type
Definition: misc.hh:728
int size()
Definition: pagetable.hh:146
virtual const std::string name() const
Definition: sim_object.hh:117
Bitfield< 29 > c
Definition: miscregs.hh:1365
void attach(int fd)
Definition: remote_gdb.cc:313
friend class InputEvent
Definition: remote_gdb.hh:158
bool cmd_unsupported(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:730
virtual ~BaseRemoteGDB()
Definition: remote_gdb.hh:53
bool cmd_mem_w(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:836
Definition: eventq.hh:185
void remove(PollEvent *event)
Definition: pollevent.cc:139
bool cmd_mem_r(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:812
virtual int threadId() const =0
break_map_t hardBreakMap
Definition: remote_gdb.hh:310
void schedule(Event *event, Tick when, bool global=false)
Schedule the given event on this queue.
Definition: eventq_impl.hh:42
TranslatingPortProxy Object Declaration for FS.
Bitfield< 18, 16 > len
Definition: miscregs.hh:1626
uint8_t getbyte()
Definition: remote_gdb.cc:342
char i2digit(int)
Definition: remote_gdb.cc:1057
TranslatingPortProxy Object Declaration for SE.
int digit2i(char)
Definition: remote_gdb.cc:1043
bool islistening() const
Definition: socket.hh:60
bool cmd_async_step(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:869
virtual void mem2hex(char *, const char *, int)
Definition: remote_gdb.cc:1064
Tick getCurTick() const
Definition: eventq.hh:615
Exception to throw when the connection to the client is broken.
Definition: remote_gdb.hh:85
IntReg pc
Definition: remote_gdb.hh:91
bool cmd_signal(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:739
PCEventQueue * getPcEventQueue()
Definition: remote_gdb.cc:533
InputEvent(GDBListener *l, int fd, int e)
Definition: remote_gdb.cc:179
static std::map< char, GdbCommand > command_map
Definition: remote_gdb.hh:114
#define DPRINTFNR(...)
Definition: trace.hh:217
static const int GDBPacketBufLen
Definition: remote_gdb.cc:155
bool cmd_step(GdbCommand::Context &ctx)
Definition: remote_gdb.cc:882
BaseRemoteGDB(System *system, ThreadContext *context)
Definition: remote_gdb.cc:289
const GdbCommand * cmd
Definition: remote_gdb.hh:61
Bitfield< 14, 12 > fd
Definition: types.hh:155
void removeHardBreak(Addr addr, size_t len)
Definition: remote_gdb.cc:617
Bitfield< 0 > p
virtual void insertHardBreak(Addr addr, size_t len)
Definition: remote_gdb.cc:602
Bitfield< 5 > l
int getfd() const
Definition: socket.hh:59
virtual size_t size() const =0
Return the size of the raw buffer, in bytes (i.e., half of the number of digits in the g/G packet)...
InputEvent * inputEvent
Definition: remote_gdb.hh:159
virtual void process(ThreadContext *tc)
Definition: remote_gdb.cc:575
InputEvent * inputEvent
Definition: remote_gdb.hh:353
virtual void writeBlob(Addr addr, const uint8_t *p, int size) const
Write size bytes from p to address.

Generated on Fri Jun 9 2017 13:03:36 for gem5 by doxygen 1.8.6