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

Generated on Fri Feb 28 2020 16:26:56 for gem5 by doxygen 1.8.13