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