gem5 v24.0.0.0
Loading...
Searching...
No Matches
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, 2021 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
42/*
43 * Copyright (c) 1990, 1993 The Regents of the University of California
44 * All rights reserved
45 *
46 * This software was developed by the Computer Systems Engineering group
47 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
48 * contributed to Berkeley.
49 *
50 * All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by the University of
53 * California, Lawrence Berkeley Laboratories.
54 *
55 * Redistribution and use in source and binary forms, with or without
56 * modification, are permitted provided that the following conditions
57 * are met:
58 * 1. Redistributions of source code must retain the above copyright
59 * notice, this list of conditions and the following disclaimer.
60 * 2. Redistributions in binary form must reproduce the above copyright
61 * notice, this list of conditions and the following disclaimer in the
62 * documentation and/or other materials provided with the distribution.
63 * 3. All advertising materials mentioning features or use of this software
64 * must display the following acknowledgement:
65 * This product includes software developed by the University of
66 * California, Berkeley and its contributors.
67 * 4. Neither the name of the University nor the names of its contributors
68 * may be used to endorse or promote products derived from this software
69 * without specific prior written permission.
70 *
71 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
72 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
75 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
76 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
77 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
78 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
79 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
80 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
81 * SUCH DAMAGE.
82 *
83 * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
84 */
85
86/*-
87 * Copyright (c) 2001 The NetBSD Foundation, Inc.
88 * All rights reserved.
89 *
90 * This code is derived from software contributed to The NetBSD Foundation
91 * by Jason R. Thorpe.
92 *
93 * Redistribution and use in source and binary forms, with or without
94 * modification, are permitted provided that the following conditions
95 * are met:
96 * 1. Redistributions of source code must retain the above copyright
97 * notice, this list of conditions and the following disclaimer.
98 * 2. Redistributions in binary form must reproduce the above copyright
99 * notice, this list of conditions and the following disclaimer in the
100 * documentation and/or other materials provided with the distribution.
101 * 3. All advertising materials mentioning features or use of this software
102 * must display the following acknowledgement:
103 * This product includes software developed by the NetBSD
104 * Foundation, Inc. and its contributors.
105 * 4. Neither the name of The NetBSD Foundation nor the names of its
106 * contributors may be used to endorse or promote products derived
107 * from this software without specific prior written permission.
108 *
109 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
110 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
111 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
112 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
113 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
114 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
115 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
116 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
117 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
118 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
119 * POSSIBILITY OF SUCH DAMAGE.
120 */
121
122/*
123 * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
124 *
125 * Taken from NetBSD
126 *
127 * "Stub" to allow remote cpu to debug over a serial line using gdb.
128 */
129
130#include "base/remote_gdb.hh"
131
132#include <sys/select.h>
133#include <sys/time.h>
134#include <unistd.h>
135
136#include <cassert>
137#include <csignal>
138#include <cstdint>
139#include <cstdio>
140#include <iterator>
141#include <sstream>
142#include <string>
143#include <utility>
144
145#include "base/cprintf.hh"
146#include "base/intmath.hh"
147#include "base/logging.hh"
148#include "base/socket.hh"
149#include "base/trace.hh"
150#include "cpu/base.hh"
151#include "cpu/static_inst.hh"
152#include "cpu/thread_context.hh"
153#include "debug/GDBAll.hh"
154#include "mem/port.hh"
155#include "mem/port_proxy.hh"
158#include "sim/full_system.hh"
159#include "sim/process.hh"
160#include "sim/sim_events.hh"
161#include "sim/system.hh"
162
163namespace gem5
164{
165
166static const char GDBStart = '$';
167static const char GDBEnd = '#';
168static const char GDBGoodP = '+';
169static const char GDBBadP = '-';
170
172{
173 private:
175
176 public:
178
179 public:
181 : PCEvent(s, "HardBreakpoint Event", pc),
182 gdb(_gdb), refcount(0)
183 {
184 DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
185 }
186
187 const std::string name() const override { return gdb->name() + ".hwbkpt"; }
188
189 void
190 process(ThreadContext *tc) override
191 {
192 DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
193
194 if (tc == gdb->tc)
195 gdb->trap(tc->contextId(), GDBSignal::TRAP,"");
196 }
197};
198
199namespace {
200
201// Exception to throw when the connection to the client is broken.
202struct BadClient
203{
204 const char *warning;
205 BadClient(const char *_warning=NULL) : warning(_warning)
206 {}
207};
208
209// Exception to throw when an error needs to be reported to the client.
210struct CmdError
211{
212 std::string error;
213 CmdError(std::string _error) : error(_error)
214 {}
215};
216
217// Exception to throw when something isn't supported.
218class Unsupported {};
219
220// Convert a hex digit into an integer.
221// This returns -1 if the argument passed is no valid hex digit.
222int
223digit2i(char c)
224{
225 if (c >= '0' && c <= '9')
226 return (c - '0');
227 else if (c >= 'a' && c <= 'f')
228 return (c - 'a' + 10);
229 else if (c >= 'A' && c <= 'F')
230 return (c - 'A' + 10);
231 else
232 return -1;
233}
234
235//convert a hex to a char
236char
237hex2c(char c0,char c1)
238{
239 char temp[3] = {c0,c1,'\0'};
240 return std::stoi(temp,0,16);
241}
242
243//this function will be used in a future patch
244//convert a encoded string to a string
245std::string
246hexS2string(std::string hex_in)
247{
248 std::string out="";
249 for (unsigned int i = 0; i + 1 < hex_in.length();i += 2){
250 out.push_back(hex2c(hex_in[i],hex_in[i+1]));
251 }
252 return out;
253}
254
255//convert a string to a hex encoded string
256std::string
257string2hexS(std::string in)
258{
259 std::string out = "";
260 for (auto ch : in){
261 char temp[3] = " ";
262 std::snprintf(temp,3,"%02hhx",ch);
263 out.append(temp);
264 }
265 return out;
266}
267
268// Convert the low 4 bits of an integer into an hex digit.
269char
270i2digit(int n)
271{
272 return "0123456789abcdef"[n & 0x0f];
273}
274
275// Convert a byte array into an hex string.
276void
277mem2hex(char *vdst, const char *vsrc, int len)
278{
279 char *dst = vdst;
280 const char *src = vsrc;
281
282 while (len--) {
283 *dst++ = i2digit(*src >> 4);
284 *dst++ = i2digit(*src++);
285 }
286 *dst = '\0';
287}
288
289// Convert an hex string into a byte array.
290// This returns a pointer to the character following the last valid
291// hex digit. If the string ends in the middle of a byte, NULL is
292// returned.
293const char *
294hex2mem(char *vdst, const char *src, int max_len)
295{
296 char *dst = vdst;
297 int msb, lsb;
298
299 while (*src && max_len--) {
300 msb = digit2i(*src++);
301 if (msb < 0)
302 return (src - 1);
303 lsb = digit2i(*src++);
304 if (lsb < 0)
305 return (NULL);
306 *dst++ = (msb << 4) | lsb;
307 }
308 return src;
309}
310
311// Convert an hex string into an integer.
312// This returns a pointer to the character following the last valid
313// hex digit.
314Addr
315hex2i(const char **srcp)
316{
317 const char *src = *srcp;
318 Addr r = 0;
319 int nibble;
320
321 while ((nibble = digit2i(*src)) >= 0) {
322 r *= 16;
323 r += nibble;
324 src++;
325 }
326 *srcp = src;
327 return r;
328}
329
330bool
331parseThreadId(const char **srcp, bool &all, bool &any, ContextID &tid)
332{
333 all = any = false;
334 tid = 0;
335 const char *src = *srcp;
336 if (*src == '-') {
337 // This could be the start of -1, which means all threads.
338 src++;
339 if (*src++ != '1')
340 return false;
341 *srcp += 2;
342 all = true;
343 return true;
344 }
345 tid = hex2i(srcp);
346 // If *srcp still points to src, no characters were consumed and no thread
347 // id was found. Without this check, we can't tell the difference between
348 // zero and a parsing error.
349 if (*srcp == src)
350 return false;
351
352 if (tid == 0)
353 any = true;
354
355 tid--;
356
357 return true;
358}
359
360int
361encodeThreadId(ContextID id)
362{
363 // Thread ID 0 is reserved and means "pick any thread".
364 return id + 1;
365}
366
367enum GdbBreakpointType
368{
369 GdbSoftBp = '0',
370 GdbHardBp = '1',
371 GdbWriteWp = '2',
372 GdbReadWp = '3',
373 GdbAccWp = '4',
374};
375
376const char *
377breakType(char c)
378{
379 switch(c) {
380 case GdbSoftBp: return "software breakpoint";
381 case GdbHardBp: return "hardware breakpoint";
382 case GdbWriteWp: return "write watchpoint";
383 case GdbReadWp: return "read watchpoint";
384 case GdbAccWp: return "access watchpoint";
385 default: return "unknown breakpoint/watchpoint";
386 }
387}
388
389std::map<Addr, HardBreakpoint *> hardBreakMap;
390
391}
392
394 ListenSocketConfig _listen_config) :
395 incomingConnectionEvent(nullptr), incomingDataEvent(nullptr),
396 fd(-1), sys(_system), connectEvent(*this), disconnectEvent(*this),
397 trapEvent(this), singleStepEvent(*this)
398{
399 listener = _listen_config.build(name());
400}
401
403{
405 delete incomingDataEvent;
406}
407
408std::string
410{
411 return sys->name() + ".remote_gdb";
412}
413
414void
416{
418 warn_once("Sockets disabled, not accepting gdb connections");
419 return;
420 }
421
422 listener->listen();
423
425 new IncomingConnectionEvent(this, listener->getfd(), POLLIN);
427}
428
429void
431{
432 panic_if(!listener->islistening(),
433 "Can't accept GDB connections without any threads!");
434
436
437 int sfd = listener->accept();
438
439 if (sfd != -1) {
440 if (isAttached())
441 close(sfd);
442 else
443 attach(sfd);
444 }
445}
446
447const ListenSocket &
449{
450 panic_if(!listener->islistening(),
451 "Remote GDB socket is unknown until listen() has been called.");
452 return *listener;
453}
454
455void
457{
458 fd = f;
459
460 attached = true;
461 DPRINTFN("remote gdb attached\n");
462
464
465 if (isAttached()) {
466 // At this point an initial communication with GDB is handled
467 // and we're ready to continue. Here we arrange IncomingDataEvent
468 // to get notified when GDB breaks in.
469 //
470 // However, GDB can decide to disconnect during that initial
471 // communication. In that case, we cannot arrange data event because
472 // the socket is already closed (not that it makes any sense, anyways).
473 //
474 // Hence the check above.
475 incomingDataEvent = new IncomingDataEvent(this, fd, POLLIN);
477 }
478}
479
480void
482{
483 attached = false;
485 close(fd);
486 fd = -1;
487
488 if (incomingDataEvent) {
489 // incomingDataEvent gets scheduled in attach() after
490 // initial communication with GDB is handled and GDB tells
491 // gem5 to continue.
492 //
493 // GDB can disconnect before that in which case `incomingDataEvent`
494 // is NULL.
495 //
496 // Hence the check above.
497
499 incomingDataEvent = nullptr;
500 }
502 DPRINTFN("remote gdb detached\n");
503}
504
505void
507{
508 [[maybe_unused]] auto it_success = threads.insert({_tc->contextId(), _tc});
509 assert(it_success.second);
510 // If no ThreadContext is current selected, select this one.
511 if (!tc)
512 assert(selectThreadContext(_tc->contextId()));
513
514 // Now that we have a thread, we can start listening.
515 if (!listener->islistening())
516 listen();
517}
518
519void
521{
522 auto it = threads.find(_tc->contextId());
523 panic_if(it == threads.end(), "No context with ID %d found.",
524 _tc->contextId());
525 it->second = _tc;
526}
527
528bool
530{
531 auto it = threads.find(id);
532 if (it == threads.end())
533 return false;
534
535 tc = it->second;
536 // Update the register cache for the new thread context, if there is one.
537 if (regCachePtr)
539 return true;
540}
541
542// This function does all command processing for interfacing to a
543// remote gdb. Note that the error codes are ignored by gdb at
544// present, but might eventually become meaningful. (XXX) It might
545// makes sense to use POSIX errno values, because that is what the
546// gdb/remote.c functions want to return.
547void
548BaseRemoteGDB::trap(ContextID id, GDBSignal sig,const std::string& stopReason)
549{
550 if (!attached)
551 return;
552
553 if (tc->contextId() != id) {
554 //prevent thread switch when single stepping
556 return;
557 }
558 DPRINTF(GDBMisc, "Finishing thread switch");
559 if (!selectThreadContext(id))
560 return;
561 }
562
563
564 DPRINTF(GDBMisc, "trap: PC=%s\n", tc->pcState());
565
567 if (stopReason=="monitor_return"){
568 //should wnot send any Tpacket here
569 send("OK");
570 }else if (threadSwitching) {
571 threadSwitching = false;
572 // Tell GDB the thread switch has completed.
573 send("OK");
574 } else {
575 // Tell remote host that an exception has occurred.
576 sendTPacket(sig,id,stopReason);
577 }
578
579 processCommands(sig);
580}
581
582bool
583BaseRemoteGDB::sendMessage(std::string message)
584{
585 if (!attached)
586 return false;
587 DPRINTF(GDBMisc, "passing message %s\n", message);
588 sendOPacket(message);
589 return true;
590}
591
592void
594{
595 if (connectEvent.scheduled()) {
596 warn("GDB connect event has already been scheduled!");
597 return;
598 }
599
600 if (revent & POLLIN) {
602 }
603}
604
605void
607{
608 if (trapEvent.scheduled()) {
609 warn("GDB trap event has already been scheduled!");
610 return;
611 }
612
613 if (revent & POLLIN) {
614 scheduleTrapEvent(tc->contextId(),GDBSignal::ILL,0,"");
615 } else if (revent & POLLNVAL) {
618 }
619}
620
621uint8_t
623{
624 uint8_t b;
625 while (!try_getbyte(&b,-1));//no timeout
626 return b;
627}
628
629bool
630BaseRemoteGDB::try_getbyte(uint8_t* c,int timeout_ms)
631{
632 if (!c)
633 panic("try_getbyte called with a null pointer as c");
634 int res,retval;
635 //Allow read to fail if it was interrupted by a signal (EINTR).
636 errno = 0;
637 //preparing fd_sets
638 fd_set rfds;
639 FD_ZERO(&rfds);
640 FD_SET(fd, &rfds);
641
642 //setting up a timeout if timeout_ms is positive
643 struct timeval tv;struct timeval* tv_ptr;
644 if (timeout_ms >= 0){
645 tv.tv_sec = timeout_ms/1000;
646 tv.tv_usec = timeout_ms%1000;
647 tv_ptr = &tv;
648 }else{
649 tv_ptr = NULL;
650 }
651 //Using select to check if the FD is ready to be read.
652 while(true){
653 do {
654 errno = 0;
655 retval = ::select(fd + 1, &rfds, NULL, NULL, tv_ptr);
656 if (retval < 0 && errno != EINTR){//error
657 DPRINTF(GDBMisc,"getbyte failed errno=%i retval=%i\n",
658 errno,retval);
659 throw BadClient("Couldn't read data from debugger.");
660 }
661 //a EINTR error means that the select call was interrupted
662 //by another signal
663 }while (errno == EINTR);
664 if (retval == 0)
665 return false;//timed out
666 //reading (retval>0)
667 res = ::read(fd, c, sizeof(*c));
668 if (res == sizeof(*c))
669 return true;//read successfully
670 //read failed (?) retrying select
671 }
672}
673void
675{
676 if (::write(fd, &b, sizeof(b)) == sizeof(b))
677 return;
678
679 throw BadClient("Couldn't write data to the debugger.");
680}
681
682// Receive a packet from gdb
683void
685{
686 uint8_t c;
687 int csum;
688 bp.resize(0);
689
690 do {
691 csum = 0;
692 // Find the beginning of a packet
693 while ((c = getbyte()) != GDBStart);
694
695 // Read until you find the end of the data in the packet, and keep
696 // track of the check sum.
697 while (true) {
698 c = getbyte();
699 if (c == GDBEnd)
700 break;
701 c &= 0x7f;
702 csum += c;
703 bp.push_back(c);
704 }
705
706 // Mask the check sum.
707 csum &= 0xff;
708
709 // Bring in the checksum. If the check sum matches, csum will be 0.
710 csum -= digit2i(getbyte()) * 16;
711 csum -= digit2i(getbyte());
712
713 // If the check sum was correct
714 if (csum == 0) {
715 // Report that the packet was received correctly
717 // Sequence present?
718 if (bp.size() > 2 && bp[2] == ':') {
719 putbyte(bp[0]);
720 putbyte(bp[1]);
721 auto begin = std::begin(bp);
722 bp.erase(begin, std::next(begin, 3));
723 }
724 break;
725 }
726 // Otherwise, report that there was a mistake.
728 } while (1);
729 // Sentinel.
730 bp.push_back('\0');
731 DPRINTF(GDBRecv, "recv: %s\n", bp.data());
732}
733
734// Send a packet to gdb
735void
736BaseRemoteGDB::send(const char *bp)
737{
738 const char *p;
739 uint8_t csum, c;
740
741 DPRINTF(GDBSend, "send: %s\n", bp);
742 //removing GDBBadP that could be waiting in the buffer
743 while (try_getbyte(&c,0));
744 do {
745 p = bp;
746 // Start sending a packet
748 // Send the contents, and also keep a check sum.
749 for (csum = 0; (c = *p); p++) {
750 putbyte(c);
751 csum += c;
752 }
753 // Send the ending character.
755 // Send the checksum.
756 putbyte(i2digit(csum >> 4));
757 putbyte(i2digit(csum));
758 // Try transmitting over and over again until the other end doesn't
759 // send an error back.
760 c = getbyte();
761 if ((c & 0x7f) == GDBBadP)
762 DPRINTF(GDBSend, "PacketError\n");
763 } while ((c & 0x7f) == GDBBadP);
764}
765
766void
768{
769 // Stick frame regs into our reg cache.
772
773 GdbCommand::Context cmd_ctx;
774 cmd_ctx.type = sig;
776
777 for (;;) {
778 try {
779 recv(data);
780 if (data.size() == 1)
781 throw BadClient();
782 cmd_ctx.cmdByte = data[0];
783 cmd_ctx.data = data.data() + 1;
784 // One for sentinel, one for cmdByte.
785 cmd_ctx.len = data.size() - 2;
786
787 auto cmd_it = commandMap.find(cmd_ctx.cmdByte);
788 if (cmd_it == commandMap.end()) {
789 DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
790 cmd_ctx.cmdByte, cmd_ctx.cmdByte);
791 throw Unsupported();
792 }
793 cmd_ctx.cmd = &(cmd_it->second);
794
795 if (!(this->*(cmd_ctx.cmd->func))(cmd_ctx))
796 break;
797
798 } catch (BadClient &e) {
799 if (e.warning)
800 warn(e.warning);
801 detach();
802 break;
803 } catch (Unsupported &e) {
804 send("");
805 } catch (CmdError &e) {
806 send(e.error);
807 } catch (std::exception &e) {
808 panic("Unrecognized GDB exception: %s", e.what());
809 } catch (...) {
810 panic("Unrecognized GDB exception.");
811 }
812 }
813}
814
815bool
817{
818 TranslatingPortProxy fs_proxy(tc);
819 SETranslatingPortProxy se_proxy(tc);
820 PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy;
821
822 virt_proxy.readBlob(vaddr, data, size);
823 return true;
824}
825
826bool
827BaseRemoteGDB::writeBlob(Addr vaddr, size_t size, const char *data)
828{
829 TranslatingPortProxy fs_proxy(tc);
830 SETranslatingPortProxy se_proxy(tc);
831 PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy;
832
833 virt_proxy.writeBlob(vaddr, data, size);
834 return true;
835}
836
837// Read bytes from kernel address space for debugger.
838bool
839BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
840{
841 DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
842
843 bool res = readBlob(vaddr, size, data);
844
845 if (!res)
846 return false;
847
848#if TRACING_ON
849 if (debug::GDBRead) {
850 if (debug::GDBExtra) {
851 char buf[1024];
852 mem2hex(buf, data, size);
853 DPRINTFNR(": %s\n", buf);
854 } else
855 DPRINTFNR("\n");
856 }
857#endif
858
859 return true;
860}
861
862// Write bytes to kernel address space for debugger.
863bool
864BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
865{
866 if (debug::GDBWrite) {
867 DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
868 if (debug::GDBExtra) {
869 char buf[1024];
870 mem2hex(buf, data, size);
871 DPRINTFNR(": %s\n", buf);
872 } else
873 DPRINTFNR("\n");
874 }
875 return writeBlob(vaddr, size, data);
876}
877
878void
885
886void
891
892void
898
899void
901{
902 if (!checkBpKind(kind))
903 throw BadClient("Invalid breakpoint kind.\n");
904
905 return insertHardBreak(addr, kind);
906}
907
908void
910{
911 if (!checkBpKind(kind))
912 throw BadClient("Invalid breakpoint kind.\n");
913
914 return removeHardBreak(addr, kind);
915}
916
917void
919{
920 if (!checkBpKind(kind))
921 throw BadClient("Invalid breakpoint kind.\n");
922
923 DPRINTF(GDBMisc, "Inserting hardware breakpoint at %#x\n", addr);
924
925 HardBreakpoint *&bkpt = hardBreakMap[addr];
926 if (bkpt == 0)
927 bkpt = new HardBreakpoint(this, sys, addr);
928
929 bkpt->refcount++;
930}
931
932void
934{
935 if (!checkBpKind(kind))
936 throw BadClient("Invalid breakpoint kind.\n");
937
938 DPRINTF(GDBMisc, "Removing hardware breakpoint at %#x\n", addr);
939
940 auto i = hardBreakMap.find(addr);
941 if (i == hardBreakMap.end())
942 throw CmdError("E0C");
943
944 HardBreakpoint *hbp = (*i).second;
945 if (--hbp->refcount == 0) {
946 delete hbp;
947 hardBreakMap.erase(i);
948 }
949}
950
951void
953 const std::string& stopReason)
954{
955 if (!stopReason.empty()){
956 send("T%02xcore:%x;thread:%x;%s;",
957 (uint8_t)sig,id + 1,id + 1,stopReason);
958 }else{
959 send("T%02xcore:%x;thread:%x;",
960 (uint8_t)sig,id + 1,id + 1);
961 }
962}
963void
965 send("S%02x",(uint8_t)sig);
966}
967void
968BaseRemoteGDB::sendOPacket(const std::string message){
969 send("O" + string2hexS(message));
970}
971
972void
974 std::string stopReason){
975 ThreadContext* _tc = threads[id];
976 panic_if(_tc == nullptr, "Unknown context id :%i",id);
977 trapEvent.id(id);
978 trapEvent.type(sig);
979 trapEvent.stopReason(stopReason);
980 if (!trapEvent.scheduled())
982}
983
984void
986{
987 if (delta == 0 && _tc->status() != ThreadContext::Active) {
988 // If delta is zero, we're just trying to wait for an instruction
989 // boundary. If the CPU is not active, assume we're already at a
990 // boundary without waiting for the CPU to eventually wake up.
991 ev->process();
992 } else {
993 // Here "ticks" aren't simulator ticks which measure time, they're
994 // instructions committed by the CPU.
995 _tc->scheduleInstCountEvent(ev, _tc->getCurrentInstCount() + delta);
996 }
997}
998
999void
1005
1006std::map<char, BaseRemoteGDB::GdbCommand> BaseRemoteGDB::commandMap = {
1007 // last signal
1008 { '?', { "KGDB_SIGNAL", &BaseRemoteGDB::cmdSignal } },
1009 // set baud (deprecated)
1010 { 'b', { "KGDB_SET_BAUD", &BaseRemoteGDB::cmdUnsupported } },
1011 // set breakpoint (deprecated)
1012 { 'B', { "KGDB_SET_BREAK", &BaseRemoteGDB::cmdUnsupported } },
1013 // resume
1014 { 'c', { "KGDB_CONT", &BaseRemoteGDB::cmdCont } },
1015 // continue with signal
1016 { 'C', { "KGDB_ASYNC_CONT", &BaseRemoteGDB::cmdAsyncCont } },
1017 // toggle debug flags (deprecated)
1018 { 'd', { "KGDB_DEBUG", &BaseRemoteGDB::cmdUnsupported } },
1019 // detach remote gdb
1020 { 'D', { "KGDB_DETACH", &BaseRemoteGDB::cmdDetach } },
1021 // read general registers
1022 { 'g', { "KGDB_REG_R", &BaseRemoteGDB::cmdRegR } },
1023 // write general registers
1024 { 'G', { "KGDB_REG_W", &BaseRemoteGDB::cmdRegW } },
1025 // set thread
1026 { 'H', { "KGDB_SET_THREAD", &BaseRemoteGDB::cmdSetThread } },
1027 // step a single cycle
1028 { 'i', { "KGDB_CYCLE_STEP", &BaseRemoteGDB::cmdUnsupported } },
1029 // signal then cycle step
1030 { 'I', { "KGDB_SIG_CYCLE_STEP", &BaseRemoteGDB::cmdUnsupported } },
1031 // kill program
1032 { 'k', { "KGDB_KILL", &BaseRemoteGDB::cmdDetach } },
1033 // read memory
1034 { 'm', { "KGDB_MEM_R", &BaseRemoteGDB::cmdMemR } },
1035 // write memory
1036 { 'M', { "KGDB_MEM_W", &BaseRemoteGDB::cmdMemW } },
1037 // read register
1038 { 'p', { "KGDB_READ_REG", &BaseRemoteGDB::cmdUnsupported } },
1039 // write register
1040 { 'P', { "KGDB_SET_REG", &BaseRemoteGDB::cmdUnsupported } },
1041 // query variable
1042 { 'q', { "KGDB_QUERY_VAR", &BaseRemoteGDB::cmdQueryVar } },
1043 // set variable
1044 { 'Q', { "KGDB_SET_VAR", &BaseRemoteGDB::cmdUnsupported } },
1045 // reset system (deprecated)
1046 { 'r', { "KGDB_RESET", &BaseRemoteGDB::cmdUnsupported } },
1047 // step
1048 { 's', { "KGDB_STEP", &BaseRemoteGDB::cmdStep } },
1049 // signal and step
1050 { 'S', { "KGDB_ASYNC_STEP", &BaseRemoteGDB::cmdAsyncStep } },
1051 // find out if the thread is alive
1052 { 'T', { "KGDB_THREAD_ALIVE", &BaseRemoteGDB::cmdIsThreadAlive } },
1053 //multi letter command
1054 { 'v', { "KGDB_MULTI_LETTER", &BaseRemoteGDB::cmdMultiLetter } },
1055 // target exited
1056 { 'W', { "KGDB_TARGET_EXIT", &BaseRemoteGDB::cmdUnsupported } },
1057 // write memory
1058 { 'X', { "KGDB_BINARY_DLOAD", &BaseRemoteGDB::cmdUnsupported } },
1059 // remove breakpoint or watchpoint
1060 { 'z', { "KGDB_CLR_HW_BKPT", &BaseRemoteGDB::cmdClrHwBkpt } },
1061 // insert breakpoint or watchpoint
1062 { 'Z', { "KGDB_SET_HW_BKPT", &BaseRemoteGDB::cmdSetHwBkpt } },
1063 // non-standard RSP extension: dump page table
1064 { '.', { "GET_PAGE_TABLE", &BaseRemoteGDB::cmdDumpPageTable } },
1065};
1066
1067bool
1069{
1070 return true;
1071}
1072
1073bool
1075{
1076 DPRINTF(GDBMisc, "Unsupported command: %s\n", ctx.cmd->name);
1077 DDUMP(GDBMisc, ctx.data, ctx.len);
1078 throw Unsupported();
1079}
1080
1081
1082bool
1084{
1085 sendTPacket(ctx.type,tc->contextId(),"");
1086 return true;
1087}
1088
1089bool
1091{
1092 const char *p = ctx.data;
1093 if (ctx.len) {
1094 Addr new_pc = hex2i(&p);
1095 tc->pcState(new_pc);
1096 }
1098 return false;
1099}
1100
1101bool
1103{
1104 const char *p = ctx.data;
1105 hex2i(&p);
1106 if (*p++ == ';') {
1107 Addr new_pc = hex2i(&p);
1108 tc->pcState(new_pc);
1109 }
1111 return false;
1112}
1113
1114bool
1116{
1117 detach();
1118 return false;
1119}
1120
1121bool
1123{
1124 char buf[2 * regCachePtr->size() + 1];
1125 buf[2 * regCachePtr->size()] = '\0';
1126 mem2hex(buf, regCachePtr->data(), regCachePtr->size());
1127 send(buf);
1128 return true;
1129}
1130
1131bool
1133{
1134 const char *p = ctx.data;
1135 p = hex2mem(regCachePtr->data(), p, regCachePtr->size());
1136 if (p == NULL || *p != '\0')
1137 throw CmdError("E01");
1138
1140 send("OK");
1141
1142 return true;
1143}
1144
1145bool
1147{
1148 const char *p = ctx.data;
1149 char subcommand = *p++;
1150 int tid = 0;
1151 bool all, any;
1152 if (!parseThreadId(&p, all, any, tid))
1153 throw CmdError("E01");
1154
1155 if (subcommand == 'c') {
1156 // We can only single step or continue all threads at once, since we
1157 // stop time itself and not individual threads.
1158 if (!all)
1159 throw CmdError("E02");
1160 } else if (subcommand == 'g') {
1161 // We don't currently support reading registers, memory, etc, from all
1162 // threads at once. GDB may never ask for this, but if it does we
1163 // should complain.
1164 if (all)
1165 throw CmdError("E03");
1166
1167 // If GDB doesn't care which thread we're using, keep using the
1168 // current one, otherwise switch.
1169 if (!any && tid != tc->contextId()) {
1170 if (!selectThreadContext(tid))
1171 throw CmdError("E04");
1172 // Line up on an instruction boundary in the new thread.
1173 threadSwitching = true;
1174 scheduleTrapEvent(tid,GDBSignal::ZERO,0,"");
1175 return false;
1176 }
1177 } else {
1178 throw CmdError("E05");
1179 }
1180
1181 send("OK");
1182 return true;
1183}
1184
1185bool
1187{
1188 const char *p = ctx.data;
1189 int tid = 0;
1190 bool all, any;
1191 if (!parseThreadId(&p, all, any, tid))
1192 throw CmdError("E01");
1193 if (all)
1194 throw CmdError("E03");
1195 if (threads.find(tid) == threads.end())
1196 throw CmdError("E04");
1197 send("OK");
1198 return true;
1199}
1200
1201bool
1203{
1204 const char *p = ctx.data;
1205 Addr addr = hex2i(&p);
1206 if (*p++ != ',')
1207 throw CmdError("E02");
1208 size_t len = hex2i(&p);
1209 if (*p != '\0')
1210 throw CmdError("E03");
1211 if (!acc(addr, len))
1212 throw CmdError("E05");
1213
1214 char buf[len];
1215 if (!read(addr, len, buf))
1216 throw CmdError("E05");
1217
1218 char temp[2 * len + 1];
1219 temp[2 * len] = '\0';
1220 mem2hex(temp, buf, len);
1221 send(temp);
1222 return true;
1223}
1224
1225bool
1227{
1228 const char *p = ctx.data;
1229 Addr addr = hex2i(&p);
1230 if (*p++ != ',')
1231 throw CmdError("E06");
1232 size_t len = hex2i(&p);
1233 if (*p++ != ':')
1234 throw CmdError("E07");
1235 if (len * 2 > ctx.len - (p - ctx.data))
1236 throw CmdError("E08");
1237 char buf[len];
1238 p = (char *)hex2mem(buf, p, len);
1239 if (p == NULL)
1240 throw CmdError("E09");
1241 if (!acc(addr, len))
1242 throw CmdError("E0A");
1243 if (!write(addr, len, buf))
1244 throw CmdError("E0B");
1245 send("OK");
1246 return true;
1247}
1248
1249bool
1251{
1253 new_ctx.type = ctx.type;
1254 strtok(ctx.data,";?");
1255 char* sep = strtok(NULL,";:?");
1256
1257 int txt_len = (sep != NULL) ? (sep - ctx.data) : strlen(ctx.data);
1258 DPRINTF(GDBMisc, "Multi-letter: %s , len=%i\n", ctx.data,txt_len);
1259 new_ctx.cmdTxt = std::string(ctx.data,txt_len);
1260 new_ctx.data = sep;
1261 new_ctx.len = ctx.len - txt_len;
1262 try {
1263 auto cmd_it = multiLetterMap.find(new_ctx.cmdTxt);
1264 if (cmd_it == multiLetterMap.end()) {
1265 DPRINTF(GDBMisc, "Unknown command: %s\n", new_ctx.cmdTxt);
1266 throw Unsupported();
1267 }
1268 new_ctx.cmd = &(cmd_it->second);
1269
1270 return (this->*(new_ctx.cmd->func))(new_ctx);
1271 //catching errors: we don't need to catch anything else
1272 //as it will be handled by processCommands
1273 } catch (CmdError &e) {
1274 send(e.error);
1275 }
1276 return false;
1277}
1278
1279std::map<std::string, BaseRemoteGDB::GdbMultiLetterCommand>
1281 { "MustReplyEmpty", { "KGDB_REPLY_EMPTY", &BaseRemoteGDB::cmdReplyEmpty}},
1282 { "Kill", { "KGDB_VKILL", &BaseRemoteGDB::cmdVKill}},
1283};
1284
1285
1286bool
1288{
1289 send("");
1290 return true;
1291}
1292
1293bool
1295{
1296 warn("GDB command for kill received detaching instead");
1297 detach();
1298 return false;
1299}
1300
1301bool
1303{
1304 DPRINTF(GDBMisc, "Unsupported Multi name command : %s\n",
1305 ctx.cmd->name);
1306 DDUMP(GDBMisc, ctx.data, ctx.len);
1307 throw Unsupported();
1308}
1309
1310namespace {
1311
1313splitAt(std::string str, const char * const delim)
1314{
1315 size_t pos = str.find_first_of(delim);
1316 if (pos == std::string::npos)
1318 else
1320 str.substr(0, pos), str.substr(pos + 1));
1321}
1322
1323} // anonymous namespace
1324
1325std::map<std::string, BaseRemoteGDB::QuerySetCommand>
1327 { "C", { &BaseRemoteGDB::queryC } },
1328 { "Rcmd", { &BaseRemoteGDB::queryRcmd} },
1329 { "Attached", { &BaseRemoteGDB::queryAttached} },
1330 { "Supported", { &BaseRemoteGDB::querySupported, ";" } },
1331 { "Xfer", { &BaseRemoteGDB::queryXfer } },
1332 { "Symbol", { &BaseRemoteGDB::querySymbol ,":" } },
1333 { "fThreadInfo", { &BaseRemoteGDB::queryFThreadInfo } },
1334 { "sThreadInfo", { &BaseRemoteGDB::querySThreadInfo } },
1335};
1336
1337bool
1339{
1340 send("QC%x", encodeThreadId(tc->contextId()));
1341 return true;
1342}
1343
1344bool
1346{
1347 std::ostringstream oss;
1348 // This reply field mandatory. We can receive arbitrarily
1349 // long packets, so we could choose it to be arbitrarily large.
1350 // This is just an arbitrary filler value that seems to work.
1351 oss << "PacketSize=1024";
1352 for (const auto& feature : availableFeatures())
1353 oss << ';' << feature;
1354 send(oss.str());
1355 return true;
1356}
1357
1358bool
1360{
1361 auto split = splitAt(ctx.args.at(0), ":");
1362 auto object = split.first;
1363
1364 split = splitAt(split.second, ":");
1365 auto operation = split.first;
1366
1367 // Only the "features" object and "read"ing are supported currently.
1368 if (object != "features" || operation != "read")
1369 throw Unsupported();
1370
1371 // Extract the annex name.
1372 split = splitAt(split.second, ":");
1373 auto annex = split.first;
1374
1375 // Read the contents of the annex.
1376 std::string content;
1377 if (!getXferFeaturesRead(annex, content))
1378 throw CmdError("E00");
1379
1380 // Extract the offset and length.
1381 split = splitAt(split.second, ",");
1382 auto offset_str = split.first;
1383 auto length_str = split.second;
1384
1385 const char *offset_ptr = offset_str.c_str();
1386 const char *length_ptr = length_str.c_str();
1387 auto offset = hex2i(&offset_ptr);
1388 auto length = hex2i(&length_ptr);
1389 if (offset_ptr != offset_str.c_str() + offset_str.length() ||
1390 length_ptr != length_str.c_str() + length_str.length()) {
1391 throw CmdError("E00");
1392 }
1393
1394 std::string encoded;
1395 encodeXferResponse(content, encoded, offset, length);
1396 send(encoded);
1397 return true;
1398}
1399bool
1401{
1402 //The target does not need to look up any (more) symbols.
1403 send("OK");
1404 return true;
1405}
1406bool
1408{
1409 std::string pid="";
1410 if (!ctx.args.empty() && !ctx.args[0].empty()){
1411 pid=ctx.args[0];
1412 }
1413 DPRINTF(GDBMisc, "QAttached : pid=%s\n",pid);
1414 //The remote server is attached to an existing process.
1415 send("1");
1416 return true;
1417}
1418
1420{
1423 public:
1424 MonitorCallEvent(BaseRemoteGDB& gdb,ContextID id,const std::string &_cause,
1425 int code):
1427 {};
1428 void process() override{
1430 }
1431 void clean() override{
1432 //trapping now
1433 //this is the only point in time when we can call trap
1434 //before any breakpoint triggers
1435 gdb.trap(id,GDBSignal::ZERO,"monitor_return");
1436 delete this;
1437 }
1439 DPRINTF(Event,"MonitorCallEvent destructed\n");;
1440 }
1441};
1442
1443bool
1445 std::string message=hexS2string(ctx.args[0]);
1446 DPRINTF(GDBMisc, "Rcmd Query: %s => %s\n", ctx.args[0],message);
1447 //Tick when = curTick();
1448 new MonitorCallEvent(*this,tc->contextId(),"GDB_MONITOR:"+ message, 0);
1449 return false;
1450}
1451
1452bool
1454{
1455 threadInfoIdx = 0;
1456 querySThreadInfo(ctx);
1457 return true;
1458}
1459
1460bool
1462{
1463 if (threadInfoIdx >= threads.size()) {
1464 threadInfoIdx = 0;
1465 send("l");
1466 } else {
1467 auto it = threads.begin();
1468 std::advance(it, threadInfoIdx++);
1469 send("m%x", encodeThreadId(it->second->contextId()));
1470 }
1471 return true;
1472}
1473
1474bool
1476{
1477 // The query command goes until the first ':', or the end of the string.
1478 std::string s(ctx.data, ctx.len);
1479 auto query_split = splitAt({ ctx.data, (size_t)ctx.len }, ":,");
1480 const auto &query_str = query_split.first;
1481
1482 // Look up the query command, and report if it isn't found.
1483 auto query_it = queryMap.find(query_str);
1484 if (query_it == queryMap.end()) {
1485 DPRINTF(GDBMisc, "Unknown query %s\n", s);
1486 throw Unsupported();
1487 }
1488
1489 // If it was found, construct a context.
1490 QuerySetCommand::Context qctx(query_str);
1491
1492 const auto &query = query_it->second;
1493 auto remaining = std::move(query_split.second);
1494 if (!query.argSep) {
1495 qctx.args.emplace_back(std::move(remaining));
1496 } else {
1497 while (remaining != "") {
1498 auto arg_split = splitAt(remaining, query.argSep);
1499 qctx.args.emplace_back(std::move(arg_split.first));
1500 remaining = std::move(arg_split.second);
1501 }
1502 }
1503 //returning true if the query want to pursue GDB command processing
1504 //false means that the command processing stop until it's trigger again.
1505 return (this->*(query.func))(qctx);
1506}
1507
1510{
1511 return {};
1512};
1513
1514bool
1516 const std::string &annex, std::string &output)
1517{
1518 return false;
1519}
1520
1521void
1523 const std::string &unencoded, std::string &encoded) const
1524{
1525 for (const char& c : unencoded) {
1526 if (c == '$' || c == '#' || c == '}' || c == '*') {
1527 encoded += '}';
1528 encoded += c ^ 0x20;
1529 } else {
1530 encoded += c;
1531 }
1532 }
1533}
1534
1535void
1536BaseRemoteGDB::encodeXferResponse(const std::string &unencoded,
1537 std::string &encoded, size_t offset, size_t unencoded_length) const
1538{
1539 if (offset + unencoded_length < unencoded.length())
1540 encoded += 'm';
1541 else
1542 encoded += 'l';
1543 encodeBinaryData(unencoded.substr(offset, unencoded_length), encoded);
1544}
1545
1546bool
1548{
1549 send(tc->getProcessPtr()->pTable->externalize().c_str());
1550 return true;
1551}
1552
1553bool
1555{
1556 const char *p = ctx.data;
1557 hex2i(&p); // Ignore the subcommand byte.
1558 if (*p++ == ';') {
1559 Addr new_pc = hex2i(&p);
1560 tc->pcState(new_pc);
1561 }
1562 setSingleStep();
1563 return false;
1564}
1565
1566bool
1568{
1569 if (ctx.len) {
1570 const char *p = ctx.data;
1571 Addr new_pc = hex2i(&p);
1572 tc->pcState(new_pc);
1573 }
1574 setSingleStep();
1575 return false;
1576}
1577
1578bool
1580{
1581 const char *p = ctx.data;
1582 char sub_cmd = *p++;
1583 if (*p++ != ',')
1584 throw CmdError("E0D");
1585 Addr addr = hex2i(&p);
1586 if (*p++ != ',')
1587 throw CmdError("E0D");
1588 size_t kind = hex2i(&p);
1589
1590 DPRINTF(GDBMisc, "clear %s, addr=%#x, kind=%d\n",
1591 breakType(sub_cmd), addr, kind);
1592
1593 switch (sub_cmd) {
1594 case GdbSoftBp:
1595 removeSoftBreak(addr, kind);
1596 break;
1597 case GdbHardBp:
1598 removeHardBreak(addr, kind);
1599 break;
1600 case GdbWriteWp:
1601 case GdbReadWp:
1602 case GdbAccWp:
1603 default: // unknown
1604 throw Unsupported();
1605 }
1606 send("OK");
1607
1608 return true;
1609}
1610
1611bool
1613{
1614 const char *p = ctx.data;
1615 char sub_cmd = *p++;
1616 if (*p++ != ',')
1617 throw CmdError("E0D");
1618 Addr addr = hex2i(&p);
1619 if (*p++ != ',')
1620 throw CmdError("E0D");
1621 size_t kind = hex2i(&p);
1622
1623 DPRINTF(GDBMisc, "set %s, addr=%#x, kind=%d\n",
1624 breakType(sub_cmd), addr, kind);
1625
1626 switch (sub_cmd) {
1627 case GdbSoftBp:
1628 insertSoftBreak(addr, kind);
1629 break;
1630 case GdbHardBp:
1631 insertHardBreak(addr, kind);
1632 break;
1633 case GdbWriteWp:
1634 case GdbReadWp:
1635 case GdbAccWp:
1636 default: // unknown
1637 throw Unsupported();
1638 }
1639 send("OK");
1640
1641 return true;
1642}
1643
1644} // namespace gem5
const char * warning
std::string error
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
Definition trace.hh:204
#define DPRINTFN(...)
Definition trace.hh:238
#define DPRINTFNR(...)
Definition trace.hh:245
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
void stopReason(std::string s)
void removeHardBreak(Addr addr, size_t kind)
bool queryAttached(QuerySetCommand::Context &ctx)
std::map< ContextID, ThreadContext * > threads
ListenSocketPtr listener
bool cmdQueryVar(GdbCommand::Context &ctx)
ThreadContext * tc
bool cmdCont(GdbCommand::Context &ctx)
virtual bool checkBpKind(size_t kind)
MemberEventWrapper<&BaseRemoteGDB::singleStep > singleStepEvent
bool cmdDetach(GdbCommand::Context &ctx)
bool cmdReplyEmpty(GdbMultiLetterCommand::Context &ctx)
static std::map< std::string, GdbMultiLetterCommand > multiLetterMap
void send(const char *data)
void incomingConnection(int revent)
IncomingConnectionEvent * incomingConnectionEvent
void encodeBinaryData(const std::string &unencoded, std::string &encoded) const
void insertSoftBreak(Addr addr, size_t kind)
static std::map< std::string, QuerySetCommand > queryMap
virtual bool writeBlob(Addr vaddr, size_t size, const char *data)
bool cmdMemW(GdbCommand::Context &ctx)
bool querySupported(QuerySetCommand::Context &ctx)
bool queryRcmd(QuerySetCommand::Context &ctx)
IncomingDataEvent * incomingDataEvent
void putbyte(uint8_t b)
bool cmdSetThread(GdbCommand::Context &ctx)
bool cmdClrHwBkpt(GdbCommand::Context &ctx)
bool cmdDumpPageTable(GdbCommand::Context &ctx)
static std::map< char, GdbCommand > commandMap
bool trap(ContextID id, int type)
Definition remote_gdb.hh:55
void incomingData(int revent)
bool try_getbyte(uint8_t *c, int timeout=-1)
bool cmdAsyncStep(GdbCommand::Context &ctx)
virtual std::vector< std::string > availableFeatures() const
MemberEventWrapper<&BaseRemoteGDB::connect > connectEvent
void sendTPacket(GDBSignal sig, ContextID id, const std::string &stopReason)
MemberEventWrapper<&BaseRemoteGDB::detach > disconnectEvent
SocketEvent<&BaseRemoteGDB::incomingData > IncomingDataEvent
bool cmdSetHwBkpt(GdbCommand::Context &ctx)
virtual ~BaseRemoteGDB()
Definition remote_gdb.hh:57
bool querySThreadInfo(QuerySetCommand::Context &ctx)
bool cmdStep(GdbCommand::Context &ctx)
void recv(std::vector< char > &bp)
virtual bool getXferFeaturesRead(const std::string &annex, std::string &output)
Get an XML target description.
bool cmdRegW(GdbCommand::Context &ctx)
void encodeXferResponse(const std::string &unencoded, std::string &encoded, size_t offset, size_t unencoded_length) const
bool cmdSignal(GdbCommand::Context &ctx)
void sendSPacket(GDBSignal sig)
bool cmdMemR(GdbCommand::Context &ctx)
void descheduleInstCommitEvent(Event *ev)
Deschedule an instruction count based event.
bool read(Addr vaddr, size_t size, char *data)
SocketEvent<&BaseRemoteGDB::incomingConnection > IncomingConnectionEvent
bool cmdRegR(GdbCommand::Context &ctx)
bool cmdIsThreadAlive(GdbCommand::Context &ctx)
void scheduleInstCommitEvent(Event *ev, int delta, ThreadContext *_tc)
Schedule an event which will be triggered "delta" instructions later.
virtual bool readBlob(Addr vaddr, size_t size, char *data)
virtual bool acc(Addr addr, size_t len)=0
virtual BaseGdbRegCache * gdbRegs()=0
gem5::BaseRemoteGDB::TrapEvent trapEvent
bool write(Addr vaddr, size_t size, const char *data)
bool cmdMultiUnsupported(GdbMultiLetterCommand::Context &ctx)
bool cmdUnsupported(GdbCommand::Context &ctx)
friend class HardBreakpoint
bool cmdMultiLetter(GdbCommand::Context &ctx)
bool queryXfer(QuerySetCommand::Context &ctx)
bool cmdVKill(GdbMultiLetterCommand::Context &ctx)
BaseGdbRegCache * regCachePtr
bool cmdAsyncCont(GdbCommand::Context &ctx)
void sendOPacket(const std::string message)
bool querySymbol(QuerySetCommand::Context &ctx)
bool queryFThreadInfo(QuerySetCommand::Context &ctx)
void removeSoftBreak(Addr addr, size_t kind)
void processCommands(GDBSignal sig=GDBSignal::ZERO)
void replaceThreadContext(ThreadContext *tc)
Definition remote_gdb.hh:54
bool queryC(QuerySetCommand::Context &ctx)
void insertHardBreak(Addr addr, size_t kind)
const std::string externalize() const
Dump all items in the pTable, to a concatenation of strings of the form Addr:Entry;.
virtual void process()=0
const std::string name() const override
HardBreakpoint(BaseRemoteGDB *_gdb, PCEventScope *s, Addr pc)
void process(ThreadContext *tc) override
BaseRemoteGDB * gdb
ListenSocketPtr build(const std::string &name) const
Definition socket.hh:123
static bool allDisabled()
Definition socket.cc:90
void process() override
MonitorCallEvent(BaseRemoteGDB &gdb, ContextID id, const std::string &_cause, int code)
BaseRemoteGDB & gdb
void clean() override
virtual std::string name() const
Definition named.hh:47
Addr pc() const
Definition pc_event.hh:61
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition port_proxy.hh:87
void readBlob(Addr addr, void *p, uint64_t size) const
Higher level interfaces based on the above.
void writeBlob(Addr addr, const void *p, uint64_t size) const
Same as tryWriteBlob, but insists on success.
EmulationPageTable * pTable
Definition process.hh:184
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual void descheduleInstCountEvent(Event *event)=0
virtual Tick getCurrentInstCount()=0
virtual void scheduleInstCountEvent(Event *event, Tick count)=0
virtual const PCStateBase & pcState() const =0
virtual Status status() const =0
virtual Process * getProcessPtr()=0
virtual ContextID contextId() const =0
This proxy attempts to translate virtual addresses using the TLBs.
STL pair class.
Definition stl.hh:58
STL vector class.
Definition stl.hh:37
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh: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:214
void remove(PollEvent *event)
Definition pollevent.cc:139
PollQueue pollQueue
Definition pollevent.cc:55
void schedule(PollEvent *event)
Definition pollevent.cc:159
void attach(int fd)
bool sendMessage(std::string message)
virtual void getRegs(ThreadContext *)=0
Fill the raw buffer from the registers in the ThreadContext.
std::string name()
virtual void setRegs(ThreadContext *) const =0
Set the ThreadContext's registers from the values in the raw buffer.
const ListenSocket & hostSocket() const
void scheduleTrapEvent(ContextID id, GDBSignal type, int delta, std::string stopReason)
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).
virtual char * data() const =0
Return the pointer to the raw bytes buffer containing the register values.
void addThreadContext(ThreadContext *_tc)
BaseRemoteGDB(System *system, ListenSocketConfig _listen_config)
Interface to other parts of the simulator.
bool selectThreadContext(ContextID id)
#define warn(...)
Definition logging.hh:256
#define warn_once(...)
Definition logging.hh:260
Port Object Declaration.
Bitfield< 14, 12 > fd
Definition types.hh:150
Bitfield< 31 > n
Bitfield< 18, 16 > len
Bitfield< 4 > s
Bitfield< 7 > b
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 9 > e
Definition misc_types.hh:65
Bitfield< 33 > id
Bitfield< 29 > c
Definition misc_types.hh:53
Bitfield< 6 > f
Definition misc_types.hh:68
Bitfield< 0 > p
Bitfield< 31, 0 > all
Definition types.hh:76
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
static const char GDBEnd
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition root.cc:220
static void output(const char *filename)
Definition debug.cc:60
static const char GDBBadP
int ContextID
Globally unique thread context ID.
Definition types.hh:239
static const char GDBGoodP
static const char GDBStart
PortProxy Object Declaration.

Generated on Tue Jun 18 2024 16:23:59 for gem5 by doxygen 1.11.0