remote_gdb.cc (14010:0e1e887507c0) remote_gdb.cc (14020:c9bf7a011602)
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"
153#include "mem/fs_translating_port_proxy.hh"
154#include "mem/port.hh"
155#include "mem/se_translating_port_proxy.hh"
156#include "sim/full_system.hh"
157#include "sim/system.hh"
158
159using namespace std;
160using namespace TheISA;
161
162static const char GDBStart = '$';
163static const char GDBEnd = '#';
164static const char GDBGoodP = '+';
165static const char GDBBadP = '-';
166
167vector<BaseRemoteGDB *> debuggers;
168
169class HardBreakpoint : public PCEvent
170{
171 private:
172 BaseRemoteGDB *gdb;
173
174 public:
175 int refcount;
176
177 public:
178 HardBreakpoint(BaseRemoteGDB *_gdb, PCEventQueue *q, Addr pc)
179 : PCEvent(q, "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
197namespace {
198
199// Exception to throw when the connection to the client is broken.
200struct 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.
208struct CmdError
209{
210 string error;
211 CmdError(std::string _error) : error(_error)
212 {}
213};
214
215// Exception to throw when something isn't supported.
216class Unsupported {};
217
218// Convert a hex digit into an integer.
219// This returns -1 if the argument passed is no valid hex digit.
220int
221digit2i(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.
234char
235i2digit(int n)
236{
237 return ("0123456789abcdef"[n & 0x0f]);
238}
239
240// Convert a byte array into an hex string.
241void
242mem2hex(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.
258const char *
259hex2mem(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.
279Addr
280hex2i(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
295enum GdbBreakpointType {
296 GdbSoftBp = '0',
297 GdbHardBp = '1',
298 GdbWriteWp = '2',
299 GdbReadWp = '3',
300 GdbAccWp = '4',
301};
302
303#ifndef NDEBUG
304const char *
305break_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
318std::map<Addr, HardBreakpoint *> hardBreakMap;
319
320EventQueue *
321getComInstEventQueue(ThreadContext *tc)
322{
323 return tc->getCpuPtr()->comInstEventQueue[tc->threadId()];
324}
325
326}
327
328BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, int _port) :
329 connectEvent(nullptr), dataEvent(nullptr), _port(_port), fd(-1),
330 active(false), attached(false), sys(_system), tc(c),
331 trapEvent(this), singleStepEvent(*this)
332{
333 debuggers.push_back(this);
334}
335
336BaseRemoteGDB::~BaseRemoteGDB()
337{
338 delete connectEvent;
339 delete dataEvent;
340}
341
342string
343BaseRemoteGDB::name()
344{
345 return sys->name() + ".remote_gdb";
346}
347
348void
349BaseRemoteGDB::listen()
350{
351 if (ListenSocket::allDisabled()) {
352 warn_once("Sockets disabled, not accepting gdb connections");
353 return;
354 }
355
356 while (!listener.listen(_port, true)) {
357 DPRINTF(GDBMisc, "Can't bind port %d\n", _port);
358 _port++;
359 }
360
361 connectEvent = new ConnectEvent(this, listener.getfd(), POLLIN);
362 pollQueue.schedule(connectEvent);
363
364 ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
365 curTick(), name(), _port);
366}
367
368void
369BaseRemoteGDB::connect()
370{
371 panic_if(!listener.islistening(),
372 "Cannot accept GDB connections if we're not listening!");
373
374 int sfd = listener.accept(true);
375
376 if (sfd != -1) {
377 if (isAttached())
378 close(sfd);
379 else
380 attach(sfd);
381 }
382}
383
384int
385BaseRemoteGDB::port() const
386{
387 panic_if(!listener.islistening(),
388 "Remote GDB port is unknown until listen() has been called.\n");
389 return _port;
390}
391
392void
393BaseRemoteGDB::attach(int f)
394{
395 fd = f;
396
397 dataEvent = new DataEvent(this, fd, POLLIN);
398 pollQueue.schedule(dataEvent);
399
400 attached = true;
401 DPRINTFN("remote gdb attached\n");
402}
403
404void
405BaseRemoteGDB::detach()
406{
407 attached = false;
408 active = false;
409 clearSingleStep();
410 close(fd);
411 fd = -1;
412
413 pollQueue.remove(dataEvent);
414 DPRINTFN("remote gdb detached\n");
415}
416
417// This function does all command processing for interfacing to a
418// remote gdb. Note that the error codes are ignored by gdb at
419// present, but might eventually become meaningful. (XXX) It might
420// makes sense to use POSIX errno values, because that is what the
421// gdb/remote.c functions want to return.
422bool
423BaseRemoteGDB::trap(int type)
424{
425
426 if (!attached)
427 return false;
428
429 DPRINTF(GDBMisc, "trap: PC=%s\n", tc->pcState());
430
431 clearSingleStep();
432
433 /*
434 * The first entry to this function is normally through
435 * a breakpoint trap in kgdb_connect(), in which case we
436 * must advance past the breakpoint because gdb will not.
437 *
438 * On the first entry here, we expect that gdb is not yet
439 * listening to us, so just enter the interaction loop.
440 * After the debugger is "active" (connected) it will be
441 * waiting for a "signaled" message from us.
442 */
443 if (!active) {
444 active = true;
445 } else {
446 // Tell remote host that an exception has occurred.
447 send(csprintf("S%02x", type).c_str());
448 }
449
450 // Stick frame regs into our reg cache.
451 regCachePtr = gdbRegs();
452 regCachePtr->getRegs(tc);
453
454 GdbCommand::Context cmdCtx;
455 cmdCtx.type = type;
456 std::vector<char> data;
457
458 for (;;) {
459 try {
460 recv(data);
461 if (data.size() == 1)
462 throw BadClient();
463 cmdCtx.cmd_byte = data[0];
464 cmdCtx.data = data.data() + 1;
465 // One for sentinel, one for cmd_byte.
466 cmdCtx.len = data.size() - 2;
467
468 auto cmdIt = command_map.find(cmdCtx.cmd_byte);
469 if (cmdIt == command_map.end()) {
470 DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
471 cmdCtx.cmd_byte, cmdCtx.cmd_byte);
472 throw Unsupported();
473 }
474 cmdCtx.cmd = &(cmdIt->second);
475
476 if (!(this->*(cmdCtx.cmd->func))(cmdCtx))
477 break;
478
479 } catch (BadClient &e) {
480 if (e.warning)
481 warn(e.warning);
482 detach();
483 break;
484 } catch (Unsupported &e) {
485 send("");
486 } catch (CmdError &e) {
487 send(e.error.c_str());
488 } catch (...) {
489 panic("Unrecognzied GDB exception.");
490 }
491 }
492
493 return true;
494}
495
496void
497BaseRemoteGDB::incomingData(int revent)
498{
499 if (trapEvent.scheduled()) {
500 warn("GDB trap event has already been scheduled!");
501 return;
502 }
503
504 if (revent & POLLIN) {
505 trapEvent.type(SIGILL);
506 scheduleInstCommitEvent(&trapEvent, 0);
507 } else if (revent & POLLNVAL) {
508 descheduleInstCommitEvent(&trapEvent);
509 detach();
510 }
511}
512
513uint8_t
514BaseRemoteGDB::getbyte()
515{
516 uint8_t b;
517 if (::read(fd, &b, sizeof(b)) == sizeof(b))
518 return b;
519
520 throw BadClient("Couldn't read data from debugger.");
521}
522
523void
524BaseRemoteGDB::putbyte(uint8_t b)
525{
526 if (::write(fd, &b, sizeof(b)) == sizeof(b))
527 return;
528
529 throw BadClient("Couldn't write data to the debugger.");
530}
531
532// Receive a packet from gdb
533void
534BaseRemoteGDB::recv(std::vector<char>& bp)
535{
536 uint8_t c;
537 int csum;
538 bp.resize(0);
539
540 do {
541 csum = 0;
542 // Find the beginning of a packet
543 while ((c = getbyte()) != GDBStart);
544
545 // Read until you find the end of the data in the packet, and keep
546 // track of the check sum.
547 while (true) {
548 c = getbyte();
549 if (c == GDBEnd)
550 break;
551 c &= 0x7f;
552 csum += c;
553 bp.push_back(c);
554 }
555
556 // Mask the check sum.
557 csum &= 0xff;
558
559 // Bring in the checksum. If the check sum matches, csum will be 0.
560 csum -= digit2i(getbyte()) * 16;
561 csum -= digit2i(getbyte());
562
563 // If the check sum was correct
564 if (csum == 0) {
565 // Report that the packet was received correctly
566 putbyte(GDBGoodP);
567 // Sequence present?
568 if (bp.size() > 2 && bp[2] == ':') {
569 putbyte(bp[0]);
570 putbyte(bp[1]);
571 auto begin = std::begin(bp);
572 bp.erase(begin, std::next(begin, 3));
573 }
574 break;
575 }
576 // Otherwise, report that there was a mistake.
577 putbyte(GDBBadP);
578 } while (1);
579 // Sentinel.
580 bp.push_back('\0');
581 DPRINTF(GDBRecv, "recv: %s\n", bp.data());
582}
583
584// Send a packet to gdb
585void
586BaseRemoteGDB::send(const char *bp)
587{
588 const char *p;
589 uint8_t csum, c;
590
591 DPRINTF(GDBSend, "send: %s\n", bp);
592
593 do {
594 p = bp;
595 // Start sending a packet
596 putbyte(GDBStart);
597 // Send the contents, and also keep a check sum.
598 for (csum = 0; (c = *p); p++) {
599 putbyte(c);
600 csum += c;
601 }
602 // Send the ending character.
603 putbyte(GDBEnd);
604 // Send the checksum.
605 putbyte(i2digit(csum >> 4));
606 putbyte(i2digit(csum));
607 // Try transmitting over and over again until the other end doesn't
608 // send an error back.
609 c = getbyte();
610 } while ((c & 0x7f) == GDBBadP);
611}
612
613// Read bytes from kernel address space for debugger.
614bool
615BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
616{
617 static Addr lastaddr = 0;
618 static size_t lastsize = 0;
619
620 if (vaddr < 10) {
621 DPRINTF(GDBRead, "read: reading memory location zero!\n");
622 vaddr = lastaddr + lastsize;
623 }
624
625 DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
626
627 if (FullSystem) {
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"
153#include "mem/fs_translating_port_proxy.hh"
154#include "mem/port.hh"
155#include "mem/se_translating_port_proxy.hh"
156#include "sim/full_system.hh"
157#include "sim/system.hh"
158
159using namespace std;
160using namespace TheISA;
161
162static const char GDBStart = '$';
163static const char GDBEnd = '#';
164static const char GDBGoodP = '+';
165static const char GDBBadP = '-';
166
167vector<BaseRemoteGDB *> debuggers;
168
169class HardBreakpoint : public PCEvent
170{
171 private:
172 BaseRemoteGDB *gdb;
173
174 public:
175 int refcount;
176
177 public:
178 HardBreakpoint(BaseRemoteGDB *_gdb, PCEventQueue *q, Addr pc)
179 : PCEvent(q, "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
197namespace {
198
199// Exception to throw when the connection to the client is broken.
200struct 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.
208struct CmdError
209{
210 string error;
211 CmdError(std::string _error) : error(_error)
212 {}
213};
214
215// Exception to throw when something isn't supported.
216class Unsupported {};
217
218// Convert a hex digit into an integer.
219// This returns -1 if the argument passed is no valid hex digit.
220int
221digit2i(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.
234char
235i2digit(int n)
236{
237 return ("0123456789abcdef"[n & 0x0f]);
238}
239
240// Convert a byte array into an hex string.
241void
242mem2hex(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.
258const char *
259hex2mem(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.
279Addr
280hex2i(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
295enum GdbBreakpointType {
296 GdbSoftBp = '0',
297 GdbHardBp = '1',
298 GdbWriteWp = '2',
299 GdbReadWp = '3',
300 GdbAccWp = '4',
301};
302
303#ifndef NDEBUG
304const char *
305break_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
318std::map<Addr, HardBreakpoint *> hardBreakMap;
319
320EventQueue *
321getComInstEventQueue(ThreadContext *tc)
322{
323 return tc->getCpuPtr()->comInstEventQueue[tc->threadId()];
324}
325
326}
327
328BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, int _port) :
329 connectEvent(nullptr), dataEvent(nullptr), _port(_port), fd(-1),
330 active(false), attached(false), sys(_system), tc(c),
331 trapEvent(this), singleStepEvent(*this)
332{
333 debuggers.push_back(this);
334}
335
336BaseRemoteGDB::~BaseRemoteGDB()
337{
338 delete connectEvent;
339 delete dataEvent;
340}
341
342string
343BaseRemoteGDB::name()
344{
345 return sys->name() + ".remote_gdb";
346}
347
348void
349BaseRemoteGDB::listen()
350{
351 if (ListenSocket::allDisabled()) {
352 warn_once("Sockets disabled, not accepting gdb connections");
353 return;
354 }
355
356 while (!listener.listen(_port, true)) {
357 DPRINTF(GDBMisc, "Can't bind port %d\n", _port);
358 _port++;
359 }
360
361 connectEvent = new ConnectEvent(this, listener.getfd(), POLLIN);
362 pollQueue.schedule(connectEvent);
363
364 ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
365 curTick(), name(), _port);
366}
367
368void
369BaseRemoteGDB::connect()
370{
371 panic_if(!listener.islistening(),
372 "Cannot accept GDB connections if we're not listening!");
373
374 int sfd = listener.accept(true);
375
376 if (sfd != -1) {
377 if (isAttached())
378 close(sfd);
379 else
380 attach(sfd);
381 }
382}
383
384int
385BaseRemoteGDB::port() const
386{
387 panic_if(!listener.islistening(),
388 "Remote GDB port is unknown until listen() has been called.\n");
389 return _port;
390}
391
392void
393BaseRemoteGDB::attach(int f)
394{
395 fd = f;
396
397 dataEvent = new DataEvent(this, fd, POLLIN);
398 pollQueue.schedule(dataEvent);
399
400 attached = true;
401 DPRINTFN("remote gdb attached\n");
402}
403
404void
405BaseRemoteGDB::detach()
406{
407 attached = false;
408 active = false;
409 clearSingleStep();
410 close(fd);
411 fd = -1;
412
413 pollQueue.remove(dataEvent);
414 DPRINTFN("remote gdb detached\n");
415}
416
417// This function does all command processing for interfacing to a
418// remote gdb. Note that the error codes are ignored by gdb at
419// present, but might eventually become meaningful. (XXX) It might
420// makes sense to use POSIX errno values, because that is what the
421// gdb/remote.c functions want to return.
422bool
423BaseRemoteGDB::trap(int type)
424{
425
426 if (!attached)
427 return false;
428
429 DPRINTF(GDBMisc, "trap: PC=%s\n", tc->pcState());
430
431 clearSingleStep();
432
433 /*
434 * The first entry to this function is normally through
435 * a breakpoint trap in kgdb_connect(), in which case we
436 * must advance past the breakpoint because gdb will not.
437 *
438 * On the first entry here, we expect that gdb is not yet
439 * listening to us, so just enter the interaction loop.
440 * After the debugger is "active" (connected) it will be
441 * waiting for a "signaled" message from us.
442 */
443 if (!active) {
444 active = true;
445 } else {
446 // Tell remote host that an exception has occurred.
447 send(csprintf("S%02x", type).c_str());
448 }
449
450 // Stick frame regs into our reg cache.
451 regCachePtr = gdbRegs();
452 regCachePtr->getRegs(tc);
453
454 GdbCommand::Context cmdCtx;
455 cmdCtx.type = type;
456 std::vector<char> data;
457
458 for (;;) {
459 try {
460 recv(data);
461 if (data.size() == 1)
462 throw BadClient();
463 cmdCtx.cmd_byte = data[0];
464 cmdCtx.data = data.data() + 1;
465 // One for sentinel, one for cmd_byte.
466 cmdCtx.len = data.size() - 2;
467
468 auto cmdIt = command_map.find(cmdCtx.cmd_byte);
469 if (cmdIt == command_map.end()) {
470 DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
471 cmdCtx.cmd_byte, cmdCtx.cmd_byte);
472 throw Unsupported();
473 }
474 cmdCtx.cmd = &(cmdIt->second);
475
476 if (!(this->*(cmdCtx.cmd->func))(cmdCtx))
477 break;
478
479 } catch (BadClient &e) {
480 if (e.warning)
481 warn(e.warning);
482 detach();
483 break;
484 } catch (Unsupported &e) {
485 send("");
486 } catch (CmdError &e) {
487 send(e.error.c_str());
488 } catch (...) {
489 panic("Unrecognzied GDB exception.");
490 }
491 }
492
493 return true;
494}
495
496void
497BaseRemoteGDB::incomingData(int revent)
498{
499 if (trapEvent.scheduled()) {
500 warn("GDB trap event has already been scheduled!");
501 return;
502 }
503
504 if (revent & POLLIN) {
505 trapEvent.type(SIGILL);
506 scheduleInstCommitEvent(&trapEvent, 0);
507 } else if (revent & POLLNVAL) {
508 descheduleInstCommitEvent(&trapEvent);
509 detach();
510 }
511}
512
513uint8_t
514BaseRemoteGDB::getbyte()
515{
516 uint8_t b;
517 if (::read(fd, &b, sizeof(b)) == sizeof(b))
518 return b;
519
520 throw BadClient("Couldn't read data from debugger.");
521}
522
523void
524BaseRemoteGDB::putbyte(uint8_t b)
525{
526 if (::write(fd, &b, sizeof(b)) == sizeof(b))
527 return;
528
529 throw BadClient("Couldn't write data to the debugger.");
530}
531
532// Receive a packet from gdb
533void
534BaseRemoteGDB::recv(std::vector<char>& bp)
535{
536 uint8_t c;
537 int csum;
538 bp.resize(0);
539
540 do {
541 csum = 0;
542 // Find the beginning of a packet
543 while ((c = getbyte()) != GDBStart);
544
545 // Read until you find the end of the data in the packet, and keep
546 // track of the check sum.
547 while (true) {
548 c = getbyte();
549 if (c == GDBEnd)
550 break;
551 c &= 0x7f;
552 csum += c;
553 bp.push_back(c);
554 }
555
556 // Mask the check sum.
557 csum &= 0xff;
558
559 // Bring in the checksum. If the check sum matches, csum will be 0.
560 csum -= digit2i(getbyte()) * 16;
561 csum -= digit2i(getbyte());
562
563 // If the check sum was correct
564 if (csum == 0) {
565 // Report that the packet was received correctly
566 putbyte(GDBGoodP);
567 // Sequence present?
568 if (bp.size() > 2 && bp[2] == ':') {
569 putbyte(bp[0]);
570 putbyte(bp[1]);
571 auto begin = std::begin(bp);
572 bp.erase(begin, std::next(begin, 3));
573 }
574 break;
575 }
576 // Otherwise, report that there was a mistake.
577 putbyte(GDBBadP);
578 } while (1);
579 // Sentinel.
580 bp.push_back('\0');
581 DPRINTF(GDBRecv, "recv: %s\n", bp.data());
582}
583
584// Send a packet to gdb
585void
586BaseRemoteGDB::send(const char *bp)
587{
588 const char *p;
589 uint8_t csum, c;
590
591 DPRINTF(GDBSend, "send: %s\n", bp);
592
593 do {
594 p = bp;
595 // Start sending a packet
596 putbyte(GDBStart);
597 // Send the contents, and also keep a check sum.
598 for (csum = 0; (c = *p); p++) {
599 putbyte(c);
600 csum += c;
601 }
602 // Send the ending character.
603 putbyte(GDBEnd);
604 // Send the checksum.
605 putbyte(i2digit(csum >> 4));
606 putbyte(i2digit(csum));
607 // Try transmitting over and over again until the other end doesn't
608 // send an error back.
609 c = getbyte();
610 } while ((c & 0x7f) == GDBBadP);
611}
612
613// Read bytes from kernel address space for debugger.
614bool
615BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
616{
617 static Addr lastaddr = 0;
618 static size_t lastsize = 0;
619
620 if (vaddr < 10) {
621 DPRINTF(GDBRead, "read: reading memory location zero!\n");
622 vaddr = lastaddr + lastsize;
623 }
624
625 DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
626
627 if (FullSystem) {
628 FSTranslatingPortProxy &proxy = tc->getVirtProxy();
628 PortProxy &proxy = tc->getVirtProxy();
629 proxy.readBlob(vaddr, data, size);
630 } else {
629 proxy.readBlob(vaddr, data, size);
630 } else {
631 SETranslatingPortProxy &proxy = tc->getMemProxy();
631 PortProxy &proxy = tc->getMemProxy();
632 proxy.readBlob(vaddr, data, size);
633 }
634
635#if TRACING_ON
636 if (DTRACE(GDBRead)) {
637 if (DTRACE(GDBExtra)) {
638 char buf[1024];
639 mem2hex(buf, data, size);
640 DPRINTFNR(": %s\n", buf);
641 } else
642 DPRINTFNR("\n");
643 }
644#endif
645
646 return true;
647}
648
649// Write bytes to kernel address space for debugger.
650bool
651BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
652{
653 static Addr lastaddr = 0;
654 static size_t lastsize = 0;
655
656 if (vaddr < 10) {
657 DPRINTF(GDBWrite, "write: writing memory location zero!\n");
658 vaddr = lastaddr + lastsize;
659 }
660
661 if (DTRACE(GDBWrite)) {
662 DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
663 if (DTRACE(GDBExtra)) {
664 char buf[1024];
665 mem2hex(buf, data, size);
666 DPRINTFNR(": %s\n", buf);
667 } else
668 DPRINTFNR("\n");
669 }
670 if (FullSystem) {
632 proxy.readBlob(vaddr, data, size);
633 }
634
635#if TRACING_ON
636 if (DTRACE(GDBRead)) {
637 if (DTRACE(GDBExtra)) {
638 char buf[1024];
639 mem2hex(buf, data, size);
640 DPRINTFNR(": %s\n", buf);
641 } else
642 DPRINTFNR("\n");
643 }
644#endif
645
646 return true;
647}
648
649// Write bytes to kernel address space for debugger.
650bool
651BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
652{
653 static Addr lastaddr = 0;
654 static size_t lastsize = 0;
655
656 if (vaddr < 10) {
657 DPRINTF(GDBWrite, "write: writing memory location zero!\n");
658 vaddr = lastaddr + lastsize;
659 }
660
661 if (DTRACE(GDBWrite)) {
662 DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
663 if (DTRACE(GDBExtra)) {
664 char buf[1024];
665 mem2hex(buf, data, size);
666 DPRINTFNR(": %s\n", buf);
667 } else
668 DPRINTFNR("\n");
669 }
670 if (FullSystem) {
671 FSTranslatingPortProxy &proxy = tc->getVirtProxy();
671 PortProxy &proxy = tc->getVirtProxy();
672 proxy.writeBlob(vaddr, data, size);
673 } else {
672 proxy.writeBlob(vaddr, data, size);
673 } else {
674 SETranslatingPortProxy &proxy = tc->getMemProxy();
674 PortProxy &proxy = tc->getMemProxy();
675 proxy.writeBlob(vaddr, data, size);
676 }
677
678 return true;
679}
680
681void
682BaseRemoteGDB::singleStep()
683{
684 if (!singleStepEvent.scheduled())
685 scheduleInstCommitEvent(&singleStepEvent, 1);
686 trap(SIGTRAP);
687}
688
689void
690BaseRemoteGDB::clearSingleStep()
691{
692 descheduleInstCommitEvent(&singleStepEvent);
693}
694
695void
696BaseRemoteGDB::setSingleStep()
697{
698 if (!singleStepEvent.scheduled())
699 scheduleInstCommitEvent(&singleStepEvent, 1);
700}
701
702void
703BaseRemoteGDB::insertSoftBreak(Addr addr, size_t len)
704{
705 if (!checkBpLen(len))
706 throw BadClient("Invalid breakpoint length\n");
707
708 return insertHardBreak(addr, len);
709}
710
711void
712BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len)
713{
714 if (!checkBpLen(len))
715 throw BadClient("Invalid breakpoint length.\n");
716
717 return removeHardBreak(addr, len);
718}
719
720void
721BaseRemoteGDB::insertHardBreak(Addr addr, size_t len)
722{
723 if (!checkBpLen(len))
724 throw BadClient("Invalid breakpoint length\n");
725
726 DPRINTF(GDBMisc, "Inserting hardware breakpoint at %#x\n", addr);
727
728 HardBreakpoint *&bkpt = hardBreakMap[addr];
729 if (bkpt == 0)
730 bkpt = new HardBreakpoint(this, &sys->pcEventQueue, addr);
731
732 bkpt->refcount++;
733}
734
735void
736BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
737{
738 if (!checkBpLen(len))
739 throw BadClient("Invalid breakpoint length\n");
740
741 DPRINTF(GDBMisc, "Removing hardware breakpoint at %#x\n", addr);
742
743 auto i = hardBreakMap.find(addr);
744 if (i == hardBreakMap.end())
745 throw CmdError("E0C");
746
747 HardBreakpoint *hbp = (*i).second;
748 if (--hbp->refcount == 0) {
749 delete hbp;
750 hardBreakMap.erase(i);
751 }
752}
753
754void
755BaseRemoteGDB::clearTempBreakpoint(Addr &bkpt)
756{
757 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
758 removeHardBreak(bkpt, sizeof(TheISA::MachInst));
759 bkpt = 0;
760}
761
762void
763BaseRemoteGDB::setTempBreakpoint(Addr bkpt)
764{
765 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
766 insertHardBreak(bkpt, sizeof(TheISA::MachInst));
767}
768
769void
770BaseRemoteGDB::scheduleInstCommitEvent(Event *ev, int delta)
771{
772 EventQueue *eq = getComInstEventQueue(tc);
773 // Here "ticks" aren't simulator ticks which measure time, they're
774 // instructions committed by the CPU.
775 eq->schedule(ev, eq->getCurTick() + delta);
776}
777
778void
779BaseRemoteGDB::descheduleInstCommitEvent(Event *ev)
780{
781 if (ev->scheduled())
782 getComInstEventQueue(tc)->deschedule(ev);
783}
784
785std::map<char, BaseRemoteGDB::GdbCommand> BaseRemoteGDB::command_map = {
786 // last signal
787 { '?', { "KGDB_SIGNAL", &BaseRemoteGDB::cmd_signal } },
788 // set baud (deprecated)
789 { 'b', { "KGDB_SET_BAUD", &BaseRemoteGDB::cmd_unsupported } },
790 // set breakpoint (deprecated)
791 { 'B', { "KGDB_SET_BREAK", &BaseRemoteGDB::cmd_unsupported } },
792 // resume
793 { 'c', { "KGDB_CONT", &BaseRemoteGDB::cmd_cont } },
794 // continue with signal
795 { 'C', { "KGDB_ASYNC_CONT", &BaseRemoteGDB::cmd_async_cont } },
796 // toggle debug flags (deprecated)
797 { 'd', { "KGDB_DEBUG", &BaseRemoteGDB::cmd_unsupported } },
798 // detach remote gdb
799 { 'D', { "KGDB_DETACH", &BaseRemoteGDB::cmd_detach } },
800 // read general registers
801 { 'g', { "KGDB_REG_R", &BaseRemoteGDB::cmd_reg_r } },
802 // write general registers
803 { 'G', { "KGDB_REG_W", &BaseRemoteGDB::cmd_reg_w } },
804 // set thread
805 { 'H', { "KGDB_SET_THREAD", &BaseRemoteGDB::cmd_set_thread } },
806 // step a single cycle
807 { 'i', { "KGDB_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
808 // signal then cycle step
809 { 'I', { "KGDB_SIG_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
810 // kill program
811 { 'k', { "KGDB_KILL", &BaseRemoteGDB::cmd_detach } },
812 // read memory
813 { 'm', { "KGDB_MEM_R", &BaseRemoteGDB::cmd_mem_r } },
814 // write memory
815 { 'M', { "KGDB_MEM_W", &BaseRemoteGDB::cmd_mem_w } },
816 // read register
817 { 'p', { "KGDB_READ_REG", &BaseRemoteGDB::cmd_unsupported } },
818 // write register
819 { 'P', { "KGDB_SET_REG", &BaseRemoteGDB::cmd_unsupported } },
820 // query variable
821 { 'q', { "KGDB_QUERY_VAR", &BaseRemoteGDB::cmd_query_var } },
822 // set variable
823 { 'Q', { "KGDB_SET_VAR", &BaseRemoteGDB::cmd_unsupported } },
824 // reset system (deprecated)
825 { 'r', { "KGDB_RESET", &BaseRemoteGDB::cmd_unsupported } },
826 // step
827 { 's', { "KGDB_STEP", &BaseRemoteGDB::cmd_step } },
828 // signal and step
829 { 'S', { "KGDB_ASYNC_STEP", &BaseRemoteGDB::cmd_async_step } },
830 // find out if the thread is alive
831 { 'T', { "KGDB_THREAD_ALIVE", &BaseRemoteGDB::cmd_unsupported } },
832 // target exited
833 { 'W', { "KGDB_TARGET_EXIT", &BaseRemoteGDB::cmd_unsupported } },
834 // write memory
835 { 'X', { "KGDB_BINARY_DLOAD", &BaseRemoteGDB::cmd_unsupported } },
836 // remove breakpoint or watchpoint
837 { 'z', { "KGDB_CLR_HW_BKPT", &BaseRemoteGDB::cmd_clr_hw_bkpt } },
838 // insert breakpoint or watchpoint
839 { 'Z', { "KGDB_SET_HW_BKPT", &BaseRemoteGDB::cmd_set_hw_bkpt } },
840};
841
842bool
843BaseRemoteGDB::checkBpLen(size_t len)
844{
845 return len == sizeof(MachInst);
846}
847
848bool
849BaseRemoteGDB::cmd_unsupported(GdbCommand::Context &ctx)
850{
851 DPRINTF(GDBMisc, "Unsupported command: %s\n", ctx.cmd->name);
852 DDUMP(GDBMisc, ctx.data, ctx.len);
853 throw Unsupported();
854}
855
856
857bool
858BaseRemoteGDB::cmd_signal(GdbCommand::Context &ctx)
859{
860 send(csprintf("S%02x", ctx.type).c_str());
861 return true;
862}
863
864bool
865BaseRemoteGDB::cmd_cont(GdbCommand::Context &ctx)
866{
867 const char *p = ctx.data;
868 if (ctx.len) {
869 Addr newPc = hex2i(&p);
870 tc->pcState(newPc);
871 }
872 clearSingleStep();
873 return false;
874}
875
876bool
877BaseRemoteGDB::cmd_async_cont(GdbCommand::Context &ctx)
878{
879 const char *p = ctx.data;
880 hex2i(&p);
881 if (*p++ == ';') {
882 Addr newPc = hex2i(&p);
883 tc->pcState(newPc);
884 }
885 clearSingleStep();
886 return false;
887}
888
889bool
890BaseRemoteGDB::cmd_detach(GdbCommand::Context &ctx)
891{
892 detach();
893 return false;
894}
895
896bool
897BaseRemoteGDB::cmd_reg_r(GdbCommand::Context &ctx)
898{
899 char buf[2 * regCachePtr->size() + 1];
900 buf[2 * regCachePtr->size()] = '\0';
901 mem2hex(buf, regCachePtr->data(), regCachePtr->size());
902 send(buf);
903 return true;
904}
905
906bool
907BaseRemoteGDB::cmd_reg_w(GdbCommand::Context &ctx)
908{
909 const char *p = ctx.data;
910 p = hex2mem(regCachePtr->data(), p, regCachePtr->size());
911 if (p == NULL || *p != '\0')
912 throw CmdError("E01");
913
914 regCachePtr->setRegs(tc);
915 send("OK");
916
917 return true;
918}
919
920bool
921BaseRemoteGDB::cmd_set_thread(GdbCommand::Context &ctx)
922{
923 const char *p = ctx.data + 1; // Ignore the subcommand byte.
924 if (hex2i(&p) != 0)
925 throw CmdError("E01");
926 send("OK");
927 return true;
928}
929
930bool
931BaseRemoteGDB::cmd_mem_r(GdbCommand::Context &ctx)
932{
933 const char *p = ctx.data;
934 Addr addr = hex2i(&p);
935 if (*p++ != ',')
936 throw CmdError("E02");
937 size_t len = hex2i(&p);
938 if (*p != '\0')
939 throw CmdError("E03");
940 if (!acc(addr, len))
941 throw CmdError("E05");
942
943 char buf[len];
944 if (!read(addr, len, buf))
945 throw CmdError("E05");
946
947 char temp[2 * len + 1];
948 temp[2 * len] = '\0';
949 mem2hex(temp, buf, len);
950 send(temp);
951 return true;
952}
953
954bool
955BaseRemoteGDB::cmd_mem_w(GdbCommand::Context &ctx)
956{
957 const char *p = ctx.data;
958 Addr addr = hex2i(&p);
959 if (*p++ != ',')
960 throw CmdError("E06");
961 size_t len = hex2i(&p);
962 if (*p++ != ':')
963 throw CmdError("E07");
964 if (len * 2 > ctx.len - (p - ctx.data))
965 throw CmdError("E08");
966 char buf[len];
967 p = (char *)hex2mem(buf, p, len);
968 if (p == NULL)
969 throw CmdError("E09");
970 if (!acc(addr, len))
971 throw CmdError("E0A");
972 if (!write(addr, len, buf))
973 throw CmdError("E0B");
974 send("OK");
975 return true;
976}
977
978bool
979BaseRemoteGDB::cmd_query_var(GdbCommand::Context &ctx)
980{
981 string s(ctx.data, ctx.len - 1);
982 string xfer_read_prefix = "Xfer:features:read:";
983 if (s.rfind("Supported:", 0) == 0) {
984 std::ostringstream oss;
985 // This reply field mandatory. We can receive arbitrarily
986 // long packets, so we could choose it to be arbitrarily large.
987 // This is just an arbitrary filler value that seems to work.
988 oss << "PacketSize=1024";
989 for (const auto& feature : availableFeatures())
990 oss << ';' << feature;
991 send(oss.str().c_str());
992 } else if (s.rfind(xfer_read_prefix, 0) == 0) {
993 size_t offset, length;
994 auto value_string = s.substr(xfer_read_prefix.length());
995 auto colon_pos = value_string.find(':');
996 auto comma_pos = value_string.find(',');
997 if (colon_pos == std::string::npos || comma_pos == std::string::npos)
998 throw CmdError("E00");
999 std::string annex;
1000 if (!getXferFeaturesRead(value_string.substr(0, colon_pos), annex))
1001 throw CmdError("E00");
1002 try {
1003 offset = std::stoull(
1004 value_string.substr(colon_pos + 1, comma_pos), NULL, 16);
1005 length = std::stoull(
1006 value_string.substr(comma_pos + 1), NULL, 16);
1007 } catch (std::invalid_argument& e) {
1008 throw CmdError("E00");
1009 } catch (std::out_of_range& e) {
1010 throw CmdError("E00");
1011 }
1012 std::string encoded;
1013 encodeXferResponse(annex, encoded, offset, length);
1014 send(encoded.c_str());
1015 } else if (s == "C") {
1016 send("QC0");
1017 } else {
1018 throw Unsupported();
1019 }
1020 return true;
1021}
1022
1023std::vector<std::string>
1024BaseRemoteGDB::availableFeatures() const
1025{
1026 return {};
1027};
1028
1029bool
1030BaseRemoteGDB::getXferFeaturesRead(
1031 const std::string &annex, std::string &output)
1032{
1033 return false;
1034}
1035
1036void
1037BaseRemoteGDB::encodeBinaryData(
1038 const std::string &unencoded, std::string &encoded) const
1039{
1040 for (const char& c : unencoded) {
1041 if (c == '$' || c == '#' || c == '}' || c == '*') {
1042 encoded += '}';
1043 encoded += c ^ 0x20;
1044 } else {
1045 encoded += c;
1046 }
1047 }
1048}
1049
1050void
1051BaseRemoteGDB::encodeXferResponse(const std::string &unencoded,
1052 std::string &encoded, size_t offset, size_t unencoded_length) const
1053{
1054 if (offset + unencoded_length < unencoded.length())
1055 encoded += 'm';
1056 else
1057 encoded += 'l';
1058 encodeBinaryData(unencoded.substr(offset, unencoded_length), encoded);
1059}
1060
1061bool
1062BaseRemoteGDB::cmd_async_step(GdbCommand::Context &ctx)
1063{
1064 const char *p = ctx.data;
1065 hex2i(&p); // Ignore the subcommand byte.
1066 if (*p++ == ';') {
1067 Addr newPc = hex2i(&p);
1068 tc->pcState(newPc);
1069 }
1070 setSingleStep();
1071 return false;
1072}
1073
1074bool
1075BaseRemoteGDB::cmd_step(GdbCommand::Context &ctx)
1076{
1077 if (ctx.len) {
1078 const char *p = ctx.data;
1079 Addr newPc = hex2i(&p);
1080 tc->pcState(newPc);
1081 }
1082 setSingleStep();
1083 return false;
1084}
1085
1086bool
1087BaseRemoteGDB::cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
1088{
1089 const char *p = ctx.data;
1090 char subcmd = *p++;
1091 if (*p++ != ',')
1092 throw CmdError("E0D");
1093 Addr addr = hex2i(&p);
1094 if (*p++ != ',')
1095 throw CmdError("E0D");
1096 size_t len = hex2i(&p);
1097
1098 DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
1099 break_type(subcmd), addr, len);
1100
1101 switch (subcmd) {
1102 case GdbSoftBp:
1103 removeSoftBreak(addr, len);
1104 break;
1105 case GdbHardBp:
1106 removeHardBreak(addr, len);
1107 break;
1108 case GdbWriteWp:
1109 case GdbReadWp:
1110 case GdbAccWp:
1111 default: // unknown
1112 throw Unsupported();
1113 }
1114 send("OK");
1115
1116 return true;
1117}
1118
1119bool
1120BaseRemoteGDB::cmd_set_hw_bkpt(GdbCommand::Context &ctx)
1121{
1122 const char *p = ctx.data;
1123 char subcmd = *p++;
1124 if (*p++ != ',')
1125 throw CmdError("E0D");
1126 Addr addr = hex2i(&p);
1127 if (*p++ != ',')
1128 throw CmdError("E0D");
1129 size_t len = hex2i(&p);
1130
1131 DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
1132 break_type(subcmd), addr, len);
1133
1134 switch (subcmd) {
1135 case GdbSoftBp:
1136 insertSoftBreak(addr, len);
1137 break;
1138 case GdbHardBp:
1139 insertHardBreak(addr, len);
1140 break;
1141 case GdbWriteWp:
1142 case GdbReadWp:
1143 case GdbAccWp:
1144 default: // unknown
1145 throw Unsupported();
1146 }
1147 send("OK");
1148
1149 return true;
1150}
675 proxy.writeBlob(vaddr, data, size);
676 }
677
678 return true;
679}
680
681void
682BaseRemoteGDB::singleStep()
683{
684 if (!singleStepEvent.scheduled())
685 scheduleInstCommitEvent(&singleStepEvent, 1);
686 trap(SIGTRAP);
687}
688
689void
690BaseRemoteGDB::clearSingleStep()
691{
692 descheduleInstCommitEvent(&singleStepEvent);
693}
694
695void
696BaseRemoteGDB::setSingleStep()
697{
698 if (!singleStepEvent.scheduled())
699 scheduleInstCommitEvent(&singleStepEvent, 1);
700}
701
702void
703BaseRemoteGDB::insertSoftBreak(Addr addr, size_t len)
704{
705 if (!checkBpLen(len))
706 throw BadClient("Invalid breakpoint length\n");
707
708 return insertHardBreak(addr, len);
709}
710
711void
712BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len)
713{
714 if (!checkBpLen(len))
715 throw BadClient("Invalid breakpoint length.\n");
716
717 return removeHardBreak(addr, len);
718}
719
720void
721BaseRemoteGDB::insertHardBreak(Addr addr, size_t len)
722{
723 if (!checkBpLen(len))
724 throw BadClient("Invalid breakpoint length\n");
725
726 DPRINTF(GDBMisc, "Inserting hardware breakpoint at %#x\n", addr);
727
728 HardBreakpoint *&bkpt = hardBreakMap[addr];
729 if (bkpt == 0)
730 bkpt = new HardBreakpoint(this, &sys->pcEventQueue, addr);
731
732 bkpt->refcount++;
733}
734
735void
736BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
737{
738 if (!checkBpLen(len))
739 throw BadClient("Invalid breakpoint length\n");
740
741 DPRINTF(GDBMisc, "Removing hardware breakpoint at %#x\n", addr);
742
743 auto i = hardBreakMap.find(addr);
744 if (i == hardBreakMap.end())
745 throw CmdError("E0C");
746
747 HardBreakpoint *hbp = (*i).second;
748 if (--hbp->refcount == 0) {
749 delete hbp;
750 hardBreakMap.erase(i);
751 }
752}
753
754void
755BaseRemoteGDB::clearTempBreakpoint(Addr &bkpt)
756{
757 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
758 removeHardBreak(bkpt, sizeof(TheISA::MachInst));
759 bkpt = 0;
760}
761
762void
763BaseRemoteGDB::setTempBreakpoint(Addr bkpt)
764{
765 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
766 insertHardBreak(bkpt, sizeof(TheISA::MachInst));
767}
768
769void
770BaseRemoteGDB::scheduleInstCommitEvent(Event *ev, int delta)
771{
772 EventQueue *eq = getComInstEventQueue(tc);
773 // Here "ticks" aren't simulator ticks which measure time, they're
774 // instructions committed by the CPU.
775 eq->schedule(ev, eq->getCurTick() + delta);
776}
777
778void
779BaseRemoteGDB::descheduleInstCommitEvent(Event *ev)
780{
781 if (ev->scheduled())
782 getComInstEventQueue(tc)->deschedule(ev);
783}
784
785std::map<char, BaseRemoteGDB::GdbCommand> BaseRemoteGDB::command_map = {
786 // last signal
787 { '?', { "KGDB_SIGNAL", &BaseRemoteGDB::cmd_signal } },
788 // set baud (deprecated)
789 { 'b', { "KGDB_SET_BAUD", &BaseRemoteGDB::cmd_unsupported } },
790 // set breakpoint (deprecated)
791 { 'B', { "KGDB_SET_BREAK", &BaseRemoteGDB::cmd_unsupported } },
792 // resume
793 { 'c', { "KGDB_CONT", &BaseRemoteGDB::cmd_cont } },
794 // continue with signal
795 { 'C', { "KGDB_ASYNC_CONT", &BaseRemoteGDB::cmd_async_cont } },
796 // toggle debug flags (deprecated)
797 { 'd', { "KGDB_DEBUG", &BaseRemoteGDB::cmd_unsupported } },
798 // detach remote gdb
799 { 'D', { "KGDB_DETACH", &BaseRemoteGDB::cmd_detach } },
800 // read general registers
801 { 'g', { "KGDB_REG_R", &BaseRemoteGDB::cmd_reg_r } },
802 // write general registers
803 { 'G', { "KGDB_REG_W", &BaseRemoteGDB::cmd_reg_w } },
804 // set thread
805 { 'H', { "KGDB_SET_THREAD", &BaseRemoteGDB::cmd_set_thread } },
806 // step a single cycle
807 { 'i', { "KGDB_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
808 // signal then cycle step
809 { 'I', { "KGDB_SIG_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
810 // kill program
811 { 'k', { "KGDB_KILL", &BaseRemoteGDB::cmd_detach } },
812 // read memory
813 { 'm', { "KGDB_MEM_R", &BaseRemoteGDB::cmd_mem_r } },
814 // write memory
815 { 'M', { "KGDB_MEM_W", &BaseRemoteGDB::cmd_mem_w } },
816 // read register
817 { 'p', { "KGDB_READ_REG", &BaseRemoteGDB::cmd_unsupported } },
818 // write register
819 { 'P', { "KGDB_SET_REG", &BaseRemoteGDB::cmd_unsupported } },
820 // query variable
821 { 'q', { "KGDB_QUERY_VAR", &BaseRemoteGDB::cmd_query_var } },
822 // set variable
823 { 'Q', { "KGDB_SET_VAR", &BaseRemoteGDB::cmd_unsupported } },
824 // reset system (deprecated)
825 { 'r', { "KGDB_RESET", &BaseRemoteGDB::cmd_unsupported } },
826 // step
827 { 's', { "KGDB_STEP", &BaseRemoteGDB::cmd_step } },
828 // signal and step
829 { 'S', { "KGDB_ASYNC_STEP", &BaseRemoteGDB::cmd_async_step } },
830 // find out if the thread is alive
831 { 'T', { "KGDB_THREAD_ALIVE", &BaseRemoteGDB::cmd_unsupported } },
832 // target exited
833 { 'W', { "KGDB_TARGET_EXIT", &BaseRemoteGDB::cmd_unsupported } },
834 // write memory
835 { 'X', { "KGDB_BINARY_DLOAD", &BaseRemoteGDB::cmd_unsupported } },
836 // remove breakpoint or watchpoint
837 { 'z', { "KGDB_CLR_HW_BKPT", &BaseRemoteGDB::cmd_clr_hw_bkpt } },
838 // insert breakpoint or watchpoint
839 { 'Z', { "KGDB_SET_HW_BKPT", &BaseRemoteGDB::cmd_set_hw_bkpt } },
840};
841
842bool
843BaseRemoteGDB::checkBpLen(size_t len)
844{
845 return len == sizeof(MachInst);
846}
847
848bool
849BaseRemoteGDB::cmd_unsupported(GdbCommand::Context &ctx)
850{
851 DPRINTF(GDBMisc, "Unsupported command: %s\n", ctx.cmd->name);
852 DDUMP(GDBMisc, ctx.data, ctx.len);
853 throw Unsupported();
854}
855
856
857bool
858BaseRemoteGDB::cmd_signal(GdbCommand::Context &ctx)
859{
860 send(csprintf("S%02x", ctx.type).c_str());
861 return true;
862}
863
864bool
865BaseRemoteGDB::cmd_cont(GdbCommand::Context &ctx)
866{
867 const char *p = ctx.data;
868 if (ctx.len) {
869 Addr newPc = hex2i(&p);
870 tc->pcState(newPc);
871 }
872 clearSingleStep();
873 return false;
874}
875
876bool
877BaseRemoteGDB::cmd_async_cont(GdbCommand::Context &ctx)
878{
879 const char *p = ctx.data;
880 hex2i(&p);
881 if (*p++ == ';') {
882 Addr newPc = hex2i(&p);
883 tc->pcState(newPc);
884 }
885 clearSingleStep();
886 return false;
887}
888
889bool
890BaseRemoteGDB::cmd_detach(GdbCommand::Context &ctx)
891{
892 detach();
893 return false;
894}
895
896bool
897BaseRemoteGDB::cmd_reg_r(GdbCommand::Context &ctx)
898{
899 char buf[2 * regCachePtr->size() + 1];
900 buf[2 * regCachePtr->size()] = '\0';
901 mem2hex(buf, regCachePtr->data(), regCachePtr->size());
902 send(buf);
903 return true;
904}
905
906bool
907BaseRemoteGDB::cmd_reg_w(GdbCommand::Context &ctx)
908{
909 const char *p = ctx.data;
910 p = hex2mem(regCachePtr->data(), p, regCachePtr->size());
911 if (p == NULL || *p != '\0')
912 throw CmdError("E01");
913
914 regCachePtr->setRegs(tc);
915 send("OK");
916
917 return true;
918}
919
920bool
921BaseRemoteGDB::cmd_set_thread(GdbCommand::Context &ctx)
922{
923 const char *p = ctx.data + 1; // Ignore the subcommand byte.
924 if (hex2i(&p) != 0)
925 throw CmdError("E01");
926 send("OK");
927 return true;
928}
929
930bool
931BaseRemoteGDB::cmd_mem_r(GdbCommand::Context &ctx)
932{
933 const char *p = ctx.data;
934 Addr addr = hex2i(&p);
935 if (*p++ != ',')
936 throw CmdError("E02");
937 size_t len = hex2i(&p);
938 if (*p != '\0')
939 throw CmdError("E03");
940 if (!acc(addr, len))
941 throw CmdError("E05");
942
943 char buf[len];
944 if (!read(addr, len, buf))
945 throw CmdError("E05");
946
947 char temp[2 * len + 1];
948 temp[2 * len] = '\0';
949 mem2hex(temp, buf, len);
950 send(temp);
951 return true;
952}
953
954bool
955BaseRemoteGDB::cmd_mem_w(GdbCommand::Context &ctx)
956{
957 const char *p = ctx.data;
958 Addr addr = hex2i(&p);
959 if (*p++ != ',')
960 throw CmdError("E06");
961 size_t len = hex2i(&p);
962 if (*p++ != ':')
963 throw CmdError("E07");
964 if (len * 2 > ctx.len - (p - ctx.data))
965 throw CmdError("E08");
966 char buf[len];
967 p = (char *)hex2mem(buf, p, len);
968 if (p == NULL)
969 throw CmdError("E09");
970 if (!acc(addr, len))
971 throw CmdError("E0A");
972 if (!write(addr, len, buf))
973 throw CmdError("E0B");
974 send("OK");
975 return true;
976}
977
978bool
979BaseRemoteGDB::cmd_query_var(GdbCommand::Context &ctx)
980{
981 string s(ctx.data, ctx.len - 1);
982 string xfer_read_prefix = "Xfer:features:read:";
983 if (s.rfind("Supported:", 0) == 0) {
984 std::ostringstream oss;
985 // This reply field mandatory. We can receive arbitrarily
986 // long packets, so we could choose it to be arbitrarily large.
987 // This is just an arbitrary filler value that seems to work.
988 oss << "PacketSize=1024";
989 for (const auto& feature : availableFeatures())
990 oss << ';' << feature;
991 send(oss.str().c_str());
992 } else if (s.rfind(xfer_read_prefix, 0) == 0) {
993 size_t offset, length;
994 auto value_string = s.substr(xfer_read_prefix.length());
995 auto colon_pos = value_string.find(':');
996 auto comma_pos = value_string.find(',');
997 if (colon_pos == std::string::npos || comma_pos == std::string::npos)
998 throw CmdError("E00");
999 std::string annex;
1000 if (!getXferFeaturesRead(value_string.substr(0, colon_pos), annex))
1001 throw CmdError("E00");
1002 try {
1003 offset = std::stoull(
1004 value_string.substr(colon_pos + 1, comma_pos), NULL, 16);
1005 length = std::stoull(
1006 value_string.substr(comma_pos + 1), NULL, 16);
1007 } catch (std::invalid_argument& e) {
1008 throw CmdError("E00");
1009 } catch (std::out_of_range& e) {
1010 throw CmdError("E00");
1011 }
1012 std::string encoded;
1013 encodeXferResponse(annex, encoded, offset, length);
1014 send(encoded.c_str());
1015 } else if (s == "C") {
1016 send("QC0");
1017 } else {
1018 throw Unsupported();
1019 }
1020 return true;
1021}
1022
1023std::vector<std::string>
1024BaseRemoteGDB::availableFeatures() const
1025{
1026 return {};
1027};
1028
1029bool
1030BaseRemoteGDB::getXferFeaturesRead(
1031 const std::string &annex, std::string &output)
1032{
1033 return false;
1034}
1035
1036void
1037BaseRemoteGDB::encodeBinaryData(
1038 const std::string &unencoded, std::string &encoded) const
1039{
1040 for (const char& c : unencoded) {
1041 if (c == '$' || c == '#' || c == '}' || c == '*') {
1042 encoded += '}';
1043 encoded += c ^ 0x20;
1044 } else {
1045 encoded += c;
1046 }
1047 }
1048}
1049
1050void
1051BaseRemoteGDB::encodeXferResponse(const std::string &unencoded,
1052 std::string &encoded, size_t offset, size_t unencoded_length) const
1053{
1054 if (offset + unencoded_length < unencoded.length())
1055 encoded += 'm';
1056 else
1057 encoded += 'l';
1058 encodeBinaryData(unencoded.substr(offset, unencoded_length), encoded);
1059}
1060
1061bool
1062BaseRemoteGDB::cmd_async_step(GdbCommand::Context &ctx)
1063{
1064 const char *p = ctx.data;
1065 hex2i(&p); // Ignore the subcommand byte.
1066 if (*p++ == ';') {
1067 Addr newPc = hex2i(&p);
1068 tc->pcState(newPc);
1069 }
1070 setSingleStep();
1071 return false;
1072}
1073
1074bool
1075BaseRemoteGDB::cmd_step(GdbCommand::Context &ctx)
1076{
1077 if (ctx.len) {
1078 const char *p = ctx.data;
1079 Addr newPc = hex2i(&p);
1080 tc->pcState(newPc);
1081 }
1082 setSingleStep();
1083 return false;
1084}
1085
1086bool
1087BaseRemoteGDB::cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
1088{
1089 const char *p = ctx.data;
1090 char subcmd = *p++;
1091 if (*p++ != ',')
1092 throw CmdError("E0D");
1093 Addr addr = hex2i(&p);
1094 if (*p++ != ',')
1095 throw CmdError("E0D");
1096 size_t len = hex2i(&p);
1097
1098 DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
1099 break_type(subcmd), addr, len);
1100
1101 switch (subcmd) {
1102 case GdbSoftBp:
1103 removeSoftBreak(addr, len);
1104 break;
1105 case GdbHardBp:
1106 removeHardBreak(addr, len);
1107 break;
1108 case GdbWriteWp:
1109 case GdbReadWp:
1110 case GdbAccWp:
1111 default: // unknown
1112 throw Unsupported();
1113 }
1114 send("OK");
1115
1116 return true;
1117}
1118
1119bool
1120BaseRemoteGDB::cmd_set_hw_bkpt(GdbCommand::Context &ctx)
1121{
1122 const char *p = ctx.data;
1123 char subcmd = *p++;
1124 if (*p++ != ',')
1125 throw CmdError("E0D");
1126 Addr addr = hex2i(&p);
1127 if (*p++ != ',')
1128 throw CmdError("E0D");
1129 size_t len = hex2i(&p);
1130
1131 DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
1132 break_type(subcmd), addr, len);
1133
1134 switch (subcmd) {
1135 case GdbSoftBp:
1136 insertSoftBreak(addr, len);
1137 break;
1138 case GdbHardBp:
1139 insertHardBreak(addr, len);
1140 break;
1141 case GdbWriteWp:
1142 case GdbReadWp:
1143 case GdbAccWp:
1144 default: // unknown
1145 throw Unsupported();
1146 }
1147 send("OK");
1148
1149 return true;
1150}