remote_gdb.cc revision 1717
112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * Copyright (c) 2002-2004 The Regents of The University of Michigan
312027Sjungma@eit.uni-kl.de * All rights reserved.
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
612027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are
712027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright
812027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer;
912027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright
1012027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the
1112027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution;
1212027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its
1312027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from
1412027Sjungma@eit.uni-kl.de * this software without specific prior written permission.
1512027Sjungma@eit.uni-kl.de *
1612027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712027Sjungma@eit.uni-kl.de */
2812027Sjungma@eit.uni-kl.de
2912027Sjungma@eit.uni-kl.de/*
3012027Sjungma@eit.uni-kl.de * Copyright (c) 1990, 1993
3112027Sjungma@eit.uni-kl.de *	The Regents of the University of California.  All rights reserved.
3212027Sjungma@eit.uni-kl.de *
3312027Sjungma@eit.uni-kl.de * This software was developed by the Computer Systems Engineering group
3412027Sjungma@eit.uni-kl.de * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
3512027Sjungma@eit.uni-kl.de * contributed to Berkeley.
3612027Sjungma@eit.uni-kl.de *
3712027Sjungma@eit.uni-kl.de * All advertising materials mentioning features or use of this software
3812027Sjungma@eit.uni-kl.de * must display the following acknowledgement:
3912027Sjungma@eit.uni-kl.de *	This product includes software developed by the University of
4012027Sjungma@eit.uni-kl.de *	California, Lawrence Berkeley Laboratories.
4112027Sjungma@eit.uni-kl.de *
4212027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
4312027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions
4412027Sjungma@eit.uni-kl.de * are met:
4512027Sjungma@eit.uni-kl.de * 1. Redistributions of source code must retain the above copyright
4612027Sjungma@eit.uni-kl.de *    notice, this list of conditions and the following disclaimer.
4712027Sjungma@eit.uni-kl.de * 2. Redistributions in binary form must reproduce the above copyright
4812027Sjungma@eit.uni-kl.de *    notice, this list of conditions and the following disclaimer in the
4912027Sjungma@eit.uni-kl.de *    documentation and/or other materials provided with the distribution.
5012027Sjungma@eit.uni-kl.de * 3. All advertising materials mentioning features or use of this software
5112027Sjungma@eit.uni-kl.de *    must display the following acknowledgement:
5212027Sjungma@eit.uni-kl.de *	This product includes software developed by the University of
5312027Sjungma@eit.uni-kl.de *	California, Berkeley and its contributors.
5412027Sjungma@eit.uni-kl.de * 4. Neither the name of the University nor the names of its contributors
5512027Sjungma@eit.uni-kl.de *    may be used to endorse or promote products derived from this software
5612027Sjungma@eit.uni-kl.de *    without specific prior written permission.
5712027Sjungma@eit.uni-kl.de *
5812027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5912027Sjungma@eit.uni-kl.de * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6012027Sjungma@eit.uni-kl.de * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6112027Sjungma@eit.uni-kl.de * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6212027Sjungma@eit.uni-kl.de * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6312027Sjungma@eit.uni-kl.de * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6412027Sjungma@eit.uni-kl.de * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6512027Sjungma@eit.uni-kl.de * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6612027Sjungma@eit.uni-kl.de * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6712027Sjungma@eit.uni-kl.de * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6812027Sjungma@eit.uni-kl.de * SUCH DAMAGE.
6912027Sjungma@eit.uni-kl.de *
7012027Sjungma@eit.uni-kl.de *	@(#)kgdb_stub.c	8.4 (Berkeley) 1/12/94
7112027Sjungma@eit.uni-kl.de */
7212027Sjungma@eit.uni-kl.de
7312027Sjungma@eit.uni-kl.de/*-
7412027Sjungma@eit.uni-kl.de * Copyright (c) 2001 The NetBSD Foundation, Inc.
7512027Sjungma@eit.uni-kl.de * All rights reserved.
7612027Sjungma@eit.uni-kl.de *
7712027Sjungma@eit.uni-kl.de * This code is derived from software contributed to The NetBSD Foundation
7812027Sjungma@eit.uni-kl.de * by Jason R. Thorpe.
7912027Sjungma@eit.uni-kl.de *
8012027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
8112027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions
8212027Sjungma@eit.uni-kl.de * are met:
8312027Sjungma@eit.uni-kl.de * 1. Redistributions of source code must retain the above copyright
8412027Sjungma@eit.uni-kl.de *    notice, this list of conditions and the following disclaimer.
8512027Sjungma@eit.uni-kl.de * 2. Redistributions in binary form must reproduce the above copyright
8612027Sjungma@eit.uni-kl.de *    notice, this list of conditions and the following disclaimer in the
8712027Sjungma@eit.uni-kl.de *    documentation and/or other materials provided with the distribution.
8812027Sjungma@eit.uni-kl.de * 3. All advertising materials mentioning features or use of this software
8912027Sjungma@eit.uni-kl.de *    must display the following acknowledgement:
9012027Sjungma@eit.uni-kl.de *	This product includes software developed by the NetBSD
9112027Sjungma@eit.uni-kl.de *	Foundation, Inc. and its contributors.
9212027Sjungma@eit.uni-kl.de * 4. Neither the name of The NetBSD Foundation nor the names of its
9312027Sjungma@eit.uni-kl.de *    contributors may be used to endorse or promote products derived
9412027Sjungma@eit.uni-kl.de *    from this software without specific prior written permission.
9512027Sjungma@eit.uni-kl.de *
9612027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
9712027Sjungma@eit.uni-kl.de * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
9812027Sjungma@eit.uni-kl.de * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9912027Sjungma@eit.uni-kl.de * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
10012027Sjungma@eit.uni-kl.de * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
101 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
102 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
103 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
104 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
105 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
106 * POSSIBILITY OF SUCH DAMAGE.
107 */
108
109/*
110 * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
111 *
112 * Taken from NetBSD
113 *
114 * "Stub" to allow remote cpu to debug over a serial line using gdb.
115 */
116
117#include <sys/signal.h>
118
119#include <cstdio>
120#include <string>
121#include <unistd.h>
122
123#include "base/intmath.hh"
124#include "base/kgdb.h"
125#include "base/remote_gdb.hh"
126#include "base/socket.hh"
127#include "base/trace.hh"
128#include "cpu/exec_context.hh"
129#include "cpu/static_inst.hh"
130#include "mem/functional/physical.hh"
131#include "sim/system.hh"
132#include "targetarch/vtophys.hh"
133
134using namespace std;
135
136#ifdef DEBUG
137RemoteGDB *theDebugger = NULL;
138
139void
140debugger()
141{
142    if (theDebugger)
143        theDebugger->trap(ALPHA_KENTRY_IF);
144}
145#endif
146
147///////////////////////////////////////////////////////////
148//
149//
150//
151
152GDBListener::Event::Event(GDBListener *l, int fd, int e)
153    : PollEvent(fd, e), listener(l)
154{}
155
156void
157GDBListener::Event::process(int revent)
158{
159    listener->accept();
160}
161
162GDBListener::GDBListener(RemoteGDB *g, int p)
163    : event(NULL), gdb(g), port(p)
164{}
165
166GDBListener::~GDBListener()
167{
168    if (event)
169        delete event;
170}
171
172string
173GDBListener::name()
174{
175    return gdb->name() + ".listener";
176}
177
178void
179GDBListener::listen()
180{
181    while (!listener.listen(port, true)) {
182        DPRINTF(GDBMisc, "Can't bind port %d\n", port);
183        port++;
184    }
185
186    cerr << "Listening for remote gdb connection on port " << port << endl;
187    event = new Event(this, listener.getfd(), POLLIN);
188    pollQueue.schedule(event);
189}
190
191void
192GDBListener::accept()
193{
194    if (!listener.islistening())
195        panic("GDBListener::accept(): cannot accept if we're not listening!");
196
197    int sfd = listener.accept(true);
198
199    if (sfd != -1) {
200        if (gdb->isattached())
201            close(sfd);
202        else
203            gdb->attach(sfd);
204    }
205}
206
207///////////////////////////////////////////////////////////
208//
209//
210//
211int digit2i(char);
212char i2digit(int);
213void mem2hex(void *, const void *, int);
214const char *hex2mem(void *, const char *, int);
215Addr hex2i(const char **);
216
217RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e)
218    : PollEvent(fd, e), gdb(g)
219{}
220
221void
222RemoteGDB::Event::process(int revent)
223{
224    if (revent & POLLIN)
225        gdb->trap(ALPHA_KENTRY_IF);
226    else if (revent & POLLNVAL)
227        gdb->detach();
228}
229
230RemoteGDB::RemoteGDB(System *_system, ExecContext *c)
231    : event(NULL), fd(-1), active(false), attached(false),
232      system(_system), pmem(_system->physmem), context(c)
233{
234    memset(gdbregs, 0, sizeof(gdbregs));
235}
236
237RemoteGDB::~RemoteGDB()
238{
239    if (event)
240        delete event;
241}
242
243string
244RemoteGDB::name()
245{
246    return system->name() + ".remote_gdb";
247}
248
249bool
250RemoteGDB::isattached()
251{ return attached; }
252
253void
254RemoteGDB::attach(int f)
255{
256    fd = f;
257
258    event = new Event(this, fd, POLLIN);
259    pollQueue.schedule(event);
260
261    attached = true;
262    DPRINTFN("remote gdb attached\n");
263#ifdef DEBUG
264    theDebugger = this;
265#endif
266}
267
268void
269RemoteGDB::detach()
270{
271    attached = false;
272    close(fd);
273    fd = -1;
274
275    pollQueue.remove(event);
276    DPRINTFN("remote gdb detached\n");
277}
278
279const char *
280gdb_command(char cmd)
281{
282    switch (cmd) {
283      case KGDB_SIGNAL: return "KGDB_SIGNAL";
284      case KGDB_SET_BAUD: return "KGDB_SET_BAUD";
285      case KGDB_SET_BREAK: return "KGDB_SET_BREAK";
286      case KGDB_CONT: return "KGDB_CONT";
287      case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT";
288      case KGDB_DEBUG: return "KGDB_DEBUG";
289      case KGDB_DETACH: return "KGDB_DETACH";
290      case KGDB_REG_R: return "KGDB_REG_R";
291      case KGDB_REG_W: return "KGDB_REG_W";
292      case KGDB_SET_THREAD: return "KGDB_SET_THREAD";
293      case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP";
294      case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP";
295      case KGDB_KILL: return "KGDB_KILL";
296      case KGDB_MEM_W: return "KGDB_MEM_W";
297      case KGDB_MEM_R: return "KGDB_MEM_R";
298      case KGDB_SET_REG: return "KGDB_SET_REG";
299      case KGDB_READ_REG: return "KGDB_READ_REG";
300      case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR";
301      case KGDB_SET_VAR: return "KGDB_SET_VAR";
302      case KGDB_RESET: return "KGDB_RESET";
303      case KGDB_STEP: return "KGDB_STEP";
304      case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP";
305      case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE";
306      case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT";
307      case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD";
308      case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT";
309      case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT";
310      case KGDB_START: return "KGDB_START";
311      case KGDB_END: return "KGDB_END";
312      case KGDB_GOODP: return "KGDB_GOODP";
313      case KGDB_BADP: return "KGDB_BADP";
314      default: return "KGDB_UNKNOWN";
315    }
316}
317
318///////////////////////////////////////////////////////////
319// RemoteGDB::acc
320//
321//	Determine if the mapping at va..(va+len) is valid.
322//
323bool
324RemoteGDB::acc(Addr va, size_t len)
325{
326    Addr last_va;
327
328    va = TheISA::TruncPage(va);
329    last_va = TheISA::RoundPage(va + len);
330
331    do  {
332        if (TheISA::IsK0Seg(va)) {
333            if (va < (TheISA::K0SegBase + pmem->size())) {
334                DPRINTF(GDBAcc, "acc:   Mapping is valid  K0SEG <= "
335                        "%#x < K0SEG + size\n", va);
336                return true;
337            } else {
338                DPRINTF(GDBAcc, "acc:   Mapping invalid %#x > K0SEG + size\n",
339                        va);
340                return false;
341            }
342        }
343
344    /**
345     * This code says that all accesses to palcode (instruction and data)
346     * are valid since there isn't a va->pa mapping because palcode is
347     * accessed physically. At some point this should probably be cleaned up
348     * but there is no easy way to do it.
349     */
350
351        if (AlphaISA::PcPAL(va) || va < 0x10000)
352            return true;
353
354        Addr ptbr = context->regs.ipr[AlphaISA::IPR_PALtemp20];
355        TheISA::PageTableEntry pte = kernel_pte_lookup(pmem, ptbr, va);
356        if (!pte.valid()) {
357            DPRINTF(GDBAcc, "acc:   %#x pte is invalid\n", va);
358            return false;
359        }
360        va += TheISA::PageBytes;
361    } while (va < last_va);
362
363    DPRINTF(GDBAcc, "acc:   %#x mapping is valid\n", va);
364    return true;
365}
366
367///////////////////////////////////////////////////////////
368// RemoteGDB::signal
369//
370//	Translate a trap number into a Unix-compatible signal number.
371//	(GDB only understands Unix signal numbers.)
372//
373int
374RemoteGDB::signal(int type)
375{
376    switch (type) {
377      case ALPHA_KENTRY_INT:
378        return (SIGTRAP);
379
380      case ALPHA_KENTRY_UNA:
381        return (SIGBUS);
382
383      case ALPHA_KENTRY_ARITH:
384        return (SIGFPE);
385
386      case ALPHA_KENTRY_IF:
387        return (SIGILL);
388
389      case ALPHA_KENTRY_MM:
390        return (SIGSEGV);
391
392      default:
393        panic("unknown signal type");
394        return 0;
395    }
396}
397
398///////////////////////////////////////////////////////////
399// RemoteGDB::getregs
400//
401//	Translate the kernel debugger register format into
402//	the GDB register format.
403void
404RemoteGDB::getregs()
405{
406    memset(gdbregs, 0, sizeof(gdbregs));
407    memcpy(&gdbregs[KGDB_REG_V0], context->regs.intRegFile, 32 * sizeof(uint64_t));
408#ifdef KGDB_FP_REGS
409    memcpy(&gdbregs[KGDB_REG_F0], context->regs.floatRegFile.q,
410           32 * sizeof(uint64_t));
411#endif
412    gdbregs[KGDB_REG_PC] = context->regs.pc;
413}
414
415///////////////////////////////////////////////////////////
416// RemoteGDB::setregs
417//
418//	Translate the GDB register format into the kernel
419//	debugger register format.
420//
421void
422RemoteGDB::setregs()
423{
424    memcpy(context->regs.intRegFile, &gdbregs[KGDB_REG_V0],
425           32 * sizeof(uint64_t));
426#ifdef KGDB_FP_REGS
427    memcpy(context->regs.floatRegFile.q, &gdbregs[KGDB_REG_F0],
428           32 * sizeof(uint64_t));
429#endif
430    context->regs.pc = gdbregs[KGDB_REG_PC];
431}
432
433void
434RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr)
435{
436    DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr);
437
438    bkpt.address = addr;
439    insertHardBreak(addr, 4);
440}
441
442void
443RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt)
444{
445    DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n",
446            bkpt.address);
447
448
449    removeHardBreak(bkpt.address, 4);
450    bkpt.address = 0;
451}
452
453void
454RemoteGDB::clearSingleStep()
455{
456    DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
457            takenBkpt.address, notTakenBkpt.address);
458
459    if (takenBkpt.address != 0)
460        clearTempBreakpoint(takenBkpt);
461
462    if (notTakenBkpt.address != 0)
463        clearTempBreakpoint(notTakenBkpt);
464}
465
466void
467RemoteGDB::setSingleStep()
468{
469    Addr pc = context->regs.pc;
470    Addr npc, bpc;
471    bool set_bt = false;
472
473    npc = pc + sizeof(MachInst);
474
475    // User was stopped at pc, e.g. the instruction at pc was not
476    // executed.
477    MachInst inst = read<MachInst>(pc);
478    StaticInstPtr<TheISA> si(inst);
479    if (si->hasBranchTarget(pc, context, bpc)) {
480        // Don't bother setting a breakpoint on the taken branch if it
481        // is the same as the next pc
482        if (bpc != npc)
483            set_bt = true;
484    }
485
486    DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
487            takenBkpt.address, notTakenBkpt.address);
488
489    setTempBreakpoint(notTakenBkpt, npc);
490
491    if (set_bt)
492        setTempBreakpoint(takenBkpt, bpc);
493}
494
495/////////////////////////
496//
497//
498
499uint8_t
500RemoteGDB::getbyte()
501{
502    uint8_t b;
503    ::read(fd, &b, 1);
504    return b;
505}
506
507void
508RemoteGDB::putbyte(uint8_t b)
509{
510    ::write(fd, &b, 1);
511}
512
513// Send a packet to gdb
514void
515RemoteGDB::send(const char *bp)
516{
517    const char *p;
518    uint8_t csum, c;
519
520    DPRINTF(GDBSend, "send:  %s\n", bp);
521
522    do {
523        p = bp;
524        putbyte(KGDB_START);
525        for (csum = 0; (c = *p); p++) {
526            putbyte(c);
527            csum += c;
528        }
529        putbyte(KGDB_END);
530        putbyte(i2digit(csum >> 4));
531        putbyte(i2digit(csum));
532    } while ((c = getbyte() & 0x7f) == KGDB_BADP);
533}
534
535// Receive a packet from gdb
536int
537RemoteGDB::recv(char *bp, int maxlen)
538{
539    char *p;
540    int c, csum;
541    int len;
542
543    do {
544        p = bp;
545        csum = len = 0;
546        while ((c = getbyte()) != KGDB_START)
547            ;
548
549        while ((c = getbyte()) != KGDB_END && len < maxlen) {
550            c &= 0x7f;
551            csum += c;
552            *p++ = c;
553            len++;
554        }
555        csum &= 0xff;
556        *p = '\0';
557
558        if (len >= maxlen) {
559            putbyte(KGDB_BADP);
560            continue;
561        }
562
563        csum -= digit2i(getbyte()) * 16;
564        csum -= digit2i(getbyte());
565
566        if (csum == 0) {
567            putbyte(KGDB_GOODP);
568            // Sequence present?
569            if (bp[2] == ':') {
570                putbyte(bp[0]);
571                putbyte(bp[1]);
572                len -= 3;
573                bcopy(bp + 3, bp, len);
574            }
575            break;
576        }
577        putbyte(KGDB_BADP);
578    } while (1);
579
580    DPRINTF(GDBRecv, "recv:  %s: %s\n", gdb_command(*bp), bp);
581
582    return (len);
583}
584
585// Read bytes from kernel address space for debugger.
586bool
587RemoteGDB::read(Addr vaddr, size_t size, char *data)
588{
589    static Addr lastaddr = 0;
590    static size_t lastsize = 0;
591
592    uint8_t *maddr;
593
594    if (vaddr < 10) {
595      DPRINTF(GDBRead, "read:  reading memory location zero!\n");
596      vaddr = lastaddr + lastsize;
597    }
598
599    DPRINTF(GDBRead, "read:  addr=%#x, size=%d", vaddr, size);
600#if TRACING_ON
601    char *d = data;
602    size_t s = size;
603#endif
604
605    lastaddr = vaddr;
606    lastsize = size;
607
608    size_t count = min((Addr)size,
609                       VMPageSize - (vaddr & (VMPageSize - 1)));
610
611    maddr = vtomem(context, vaddr, count);
612    memcpy(data, maddr, count);
613
614    vaddr += count;
615    data += count;
616    size -= count;
617
618    while (size >= VMPageSize) {
619        maddr = vtomem(context, vaddr, count);
620        memcpy(data, maddr, VMPageSize);
621
622        vaddr += VMPageSize;
623        data += VMPageSize;
624        size -= VMPageSize;
625    }
626
627    if (size > 0) {
628        maddr = vtomem(context, vaddr, count);
629        memcpy(data, maddr, size);
630    }
631
632#if TRACING_ON
633    if (DTRACE(GDBRead)) {
634        if (DTRACE(GDBExtra)) {
635            char buf[1024];
636            mem2hex(buf, d, s);
637            DPRINTFNR(": %s\n", buf);
638        } else
639            DPRINTFNR("\n");
640    }
641#endif
642
643    return true;
644}
645
646// Write bytes to kernel address space for debugger.
647bool
648RemoteGDB::write(Addr vaddr, size_t size, const char *data)
649{
650    static Addr lastaddr = 0;
651    static size_t lastsize = 0;
652
653    uint8_t *maddr;
654
655    if (vaddr < 10) {
656      DPRINTF(GDBWrite, "write: writing memory location zero!\n");
657      vaddr = lastaddr + lastsize;
658    }
659
660    if (DTRACE(GDBWrite)) {
661        DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
662        if (DTRACE(GDBExtra)) {
663            char buf[1024];
664            mem2hex(buf, data, size);
665            DPRINTFNR(": %s\n", buf);
666        } else
667            DPRINTFNR("\n");
668    }
669
670    lastaddr = vaddr;
671    lastsize = size;
672
673    size_t count = min((Addr)size,
674                       VMPageSize - (vaddr & (VMPageSize - 1)));
675
676    maddr = vtomem(context, vaddr, count);
677    memcpy(maddr, data, count);
678
679    vaddr += count;
680    data += count;
681    size -= count;
682
683    while (size >= VMPageSize) {
684        maddr = vtomem(context, vaddr, count);
685        memcpy(maddr, data, VMPageSize);
686
687        vaddr += VMPageSize;
688        data += VMPageSize;
689        size -= VMPageSize;
690    }
691
692    if (size > 0) {
693        maddr = vtomem(context, vaddr, count);
694        memcpy(maddr, data, size);
695    }
696
697#ifdef IMB
698    alpha_pal_imb();
699#endif
700
701    return true;
702}
703
704
705PCEventQueue *RemoteGDB::getPcEventQueue()
706{
707    return &system->pcEventQueue;
708}
709
710
711RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
712    : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
713      gdb(_gdb), refcount(0)
714{
715    DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
716    schedule();
717}
718
719void
720RemoteGDB::HardBreakpoint::process(ExecContext *xc)
721{
722    DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
723
724    if (xc == gdb->context)
725        gdb->trap(ALPHA_KENTRY_INT);
726}
727
728bool
729RemoteGDB::insertSoftBreak(Addr addr, size_t len)
730{
731    if (len != sizeof(MachInst))
732        panic("invalid length\n");
733
734    return insertHardBreak(addr, len);
735}
736
737bool
738RemoteGDB::removeSoftBreak(Addr addr, size_t len)
739{
740    if (len != sizeof(MachInst))
741        panic("invalid length\n");
742
743    return removeHardBreak(addr, len);
744}
745
746bool
747RemoteGDB::insertHardBreak(Addr addr, size_t len)
748{
749    if (len != sizeof(MachInst))
750        panic("invalid length\n");
751
752    DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr);
753
754    HardBreakpoint *&bkpt = hardBreakMap[addr];
755    if (bkpt == 0)
756        bkpt = new HardBreakpoint(this, addr);
757
758    bkpt->refcount++;
759
760    return true;
761}
762
763bool
764RemoteGDB::removeHardBreak(Addr addr, size_t len)
765{
766    if (len != sizeof(MachInst))
767        panic("invalid length\n");
768
769    DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr);
770
771    break_iter_t i = hardBreakMap.find(addr);
772    if (i == hardBreakMap.end())
773        return false;
774
775    HardBreakpoint *hbp = (*i).second;
776    if (--hbp->refcount == 0) {
777        delete hbp;
778        hardBreakMap.erase(i);
779    }
780
781    return true;
782}
783
784const char *
785break_type(char c)
786{
787    switch(c) {
788      case '0': return "software breakpoint";
789      case '1': return "hardware breakpoint";
790      case '2': return "write watchpoint";
791      case '3': return "read watchpoint";
792      case '4': return "access watchpoint";
793      default: return "unknown breakpoint/watchpoint";
794    }
795}
796
797// This function does all command processing for interfacing to a
798// remote gdb.  Note that the error codes are ignored by gdb at
799// present, but might eventually become meaningful. (XXX) It might
800// makes sense to use POSIX errno values, because that is what the
801// gdb/remote.c functions want to return.
802bool
803RemoteGDB::trap(int type)
804{
805    uint64_t val;
806    size_t datalen, len;
807    char data[KGDB_BUFLEN + 1];
808    char buffer[sizeof(gdbregs) * 2 + 256];
809    char temp[KGDB_BUFLEN];
810    const char *p;
811    char command, subcmd;
812    string var;
813    bool ret;
814
815    if (!attached)
816        return false;
817
818    DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n",
819            context->regs.pc, context->regs.npc);
820
821    clearSingleStep();
822
823    /*
824     * The first entry to this function is normally through
825     * a breakpoint trap in kgdb_connect(), in which case we
826     * must advance past the breakpoint because gdb will not.
827     *
828     * On the first entry here, we expect that gdb is not yet
829     * listening to us, so just enter the interaction loop.
830     * After the debugger is "active" (connected) it will be
831     * waiting for a "signaled" message from us.
832     */
833    if (!active)
834        active = true;
835    else
836        // Tell remote host that an exception has occurred.
837        sprintf((char *)buffer, "S%02x", signal(type));
838        send(buffer);
839
840    // Stick frame regs into our reg cache.
841    getregs();
842
843    for (;;) {
844        datalen = recv(data, sizeof(data));
845        data[sizeof(data) - 1] = 0; // Sentinel
846        command = data[0];
847        subcmd = 0;
848        p = data + 1;
849        switch (command) {
850
851          case KGDB_SIGNAL:
852            // if this command came from a running gdb, answer it --
853            // the other guy has no way of knowing if we're in or out
854            // of this loop when he issues a "remote-signal".
855            sprintf((char *)buffer, "S%02x", signal(type));
856            send(buffer);
857            continue;
858
859          case KGDB_REG_R:
860            if (2 * sizeof(gdbregs) > sizeof(buffer))
861                panic("buffer too small");
862
863            mem2hex(buffer, gdbregs, sizeof(gdbregs));
864            send(buffer);
865            continue;
866
867          case KGDB_REG_W:
868            p = hex2mem(gdbregs, p, sizeof(gdbregs));
869            if (p == NULL || *p != '\0')
870                send("E01");
871            else {
872                setregs();
873                send("OK");
874            }
875            continue;
876
877#if 0
878          case KGDB_SET_REG:
879            val = hex2i(&p);
880            if (*p++ != '=') {
881                send("E01");
882                continue;
883            }
884            if (val < 0 && val >= KGDB_NUMREGS) {
885                send("E01");
886                continue;
887            }
888
889            gdbregs[val] = hex2i(&p);
890            setregs();
891            send("OK");
892
893            continue;
894#endif
895
896          case KGDB_MEM_R:
897            val = hex2i(&p);
898            if (*p++ != ',') {
899                send("E02");
900                continue;
901            }
902            len = hex2i(&p);
903            if (*p != '\0') {
904                send("E03");
905                continue;
906            }
907            if (len > sizeof(buffer)) {
908                send("E04");
909                continue;
910            }
911            if (!acc(val, len)) {
912                send("E05");
913                continue;
914            }
915
916            if (read(val, (size_t)len, (char *)buffer)) {
917              mem2hex(temp, buffer, len);
918              send(temp);
919            } else {
920              send("E05");
921            }
922            continue;
923
924          case KGDB_MEM_W:
925            val = hex2i(&p);
926            if (*p++ != ',') {
927                send("E06");
928                continue;
929            }
930            len = hex2i(&p);
931            if (*p++ != ':') {
932                send("E07");
933                continue;
934            }
935            if (len > datalen - (p - data)) {
936                send("E08");
937                continue;
938            }
939            p = hex2mem(buffer, p, sizeof(buffer));
940            if (p == NULL) {
941                send("E09");
942                continue;
943            }
944            if (!acc(val, len)) {
945                send("E0A");
946                continue;
947            }
948            if (write(val, (size_t)len, (char *)buffer))
949              send("OK");
950            else
951              send("E0B");
952            continue;
953
954          case KGDB_SET_THREAD:
955            subcmd = *p++;
956            val = hex2i(&p);
957            if (val == 0)
958                send("OK");
959            else
960                send("E01");
961            continue;
962
963          case KGDB_DETACH:
964          case KGDB_KILL:
965            active = false;
966            clearSingleStep();
967            detach();
968            goto out;
969
970          case KGDB_ASYNC_CONT:
971            subcmd = hex2i(&p);
972            if (*p++ == ';') {
973                val = hex2i(&p);
974                context->regs.pc = val;
975                context->regs.npc = val + sizeof(MachInst);
976            }
977            clearSingleStep();
978            goto out;
979
980          case KGDB_CONT:
981            if (p - data < datalen) {
982                val = hex2i(&p);
983                context->regs.pc = val;
984                context->regs.npc = val + sizeof(MachInst);
985            }
986            clearSingleStep();
987            goto out;
988
989          case KGDB_ASYNC_STEP:
990            subcmd = hex2i(&p);
991            if (*p++ == ';') {
992                val = hex2i(&p);
993                context->regs.pc = val;
994                context->regs.npc = val + sizeof(MachInst);
995            }
996            setSingleStep();
997            goto out;
998
999          case KGDB_STEP:
1000            if (p - data < datalen) {
1001                val = hex2i(&p);
1002                context->regs.pc = val;
1003                context->regs.npc = val + sizeof(MachInst);
1004            }
1005            setSingleStep();
1006            goto out;
1007
1008          case KGDB_CLR_HW_BKPT:
1009            subcmd = *p++;
1010            if (*p++ != ',') send("E0D");
1011            val = hex2i(&p);
1012            if (*p++ != ',') send("E0D");
1013            len = hex2i(&p);
1014
1015            DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
1016                    break_type(subcmd), val, len);
1017
1018            ret = false;
1019
1020            switch (subcmd) {
1021              case '0': // software breakpoint
1022                ret = removeSoftBreak(val, len);
1023                break;
1024
1025              case '1': // hardware breakpoint
1026                ret = removeHardBreak(val, len);
1027                break;
1028
1029              case '2': // write watchpoint
1030              case '3': // read watchpoint
1031              case '4': // access watchpoint
1032              default: // unknown
1033                send("");
1034                break;
1035            }
1036
1037            send(ret ? "OK" : "E0C");
1038            continue;
1039
1040          case KGDB_SET_HW_BKPT:
1041            subcmd = *p++;
1042            if (*p++ != ',') send("E0D");
1043            val = hex2i(&p);
1044            if (*p++ != ',') send("E0D");
1045            len = hex2i(&p);
1046
1047            DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
1048                    break_type(subcmd), val, len);
1049
1050            ret = false;
1051
1052            switch (subcmd) {
1053              case '0': // software breakpoint
1054                ret = insertSoftBreak(val, len);
1055                break;
1056
1057              case '1': // hardware breakpoint
1058                ret = insertHardBreak(val, len);
1059                break;
1060
1061              case '2': // write watchpoint
1062              case '3': // read watchpoint
1063              case '4': // access watchpoint
1064              default: // unknown
1065                send("");
1066                break;
1067            }
1068
1069            send(ret ? "OK" : "E0C");
1070            continue;
1071
1072          case KGDB_QUERY_VAR:
1073            var = string(p, datalen - 1);
1074            if (var == "C")
1075                send("QC0");
1076            else
1077                send("");
1078            continue;
1079
1080          case KGDB_SET_BAUD:
1081          case KGDB_SET_BREAK:
1082          case KGDB_DEBUG:
1083          case KGDB_CYCLE_STEP:
1084          case KGDB_SIG_CYCLE_STEP:
1085          case KGDB_READ_REG:
1086          case KGDB_SET_VAR:
1087          case KGDB_RESET:
1088          case KGDB_THREAD_ALIVE:
1089          case KGDB_TARGET_EXIT:
1090          case KGDB_BINARY_DLOAD:
1091            // Unsupported command
1092            DPRINTF(GDBMisc, "Unsupported command: %s\n",
1093                    gdb_command(command));
1094            DDUMP(GDBMisc, (uint8_t *)data, datalen);
1095            send("");
1096            continue;
1097
1098          default:
1099            // Unknown command.
1100            DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
1101                    command, command);
1102            send("");
1103            continue;
1104
1105
1106        }
1107    }
1108
1109  out:
1110    return true;
1111}
1112
1113// Convert a hex digit into an integer.
1114// This returns -1 if the argument passed is no valid hex digit.
1115int
1116digit2i(char c)
1117{
1118    if (c >= '0' && c <= '9')
1119        return (c - '0');
1120    else if (c >= 'a' && c <= 'f')
1121        return (c - 'a' + 10);
1122    else if (c >= 'A' && c <= 'F')
1123
1124        return (c - 'A' + 10);
1125    else
1126        return (-1);
1127}
1128
1129// Convert the low 4 bits of an integer into an hex digit.
1130char
1131i2digit(int n)
1132{
1133    return ("0123456789abcdef"[n & 0x0f]);
1134}
1135
1136// Convert a byte array into an hex string.
1137void
1138mem2hex(void *vdst, const void *vsrc, int len)
1139{
1140    char *dst = (char *)vdst;
1141    const char *src = (const char *)vsrc;
1142
1143    while (len--) {
1144        *dst++ = i2digit(*src >> 4);
1145        *dst++ = i2digit(*src++);
1146    }
1147    *dst = '\0';
1148}
1149
1150// Convert an hex string into a byte array.
1151// This returns a pointer to the character following the last valid
1152// hex digit. If the string ends in the middle of a byte, NULL is
1153// returned.
1154const char *
1155hex2mem(void *vdst, const char *src, int maxlen)
1156{
1157    char *dst = (char *)vdst;
1158    int msb, lsb;
1159
1160    while (*src && maxlen--) {
1161        msb = digit2i(*src++);
1162        if (msb < 0)
1163            return (src - 1);
1164        lsb = digit2i(*src++);
1165        if (lsb < 0)
1166            return (NULL);
1167        *dst++ = (msb << 4) | lsb;
1168    }
1169    return (src);
1170}
1171
1172// Convert an hex string into an integer.
1173// This returns a pointer to the character following the last valid
1174// hex digit.
1175Addr
1176hex2i(const char **srcp)
1177{
1178    const char *src = *srcp;
1179    Addr r = 0;
1180    int nibble;
1181
1182    while ((nibble = digit2i(*src)) >= 0) {
1183        r *= 16;
1184        r += nibble;
1185        src++;
1186    }
1187    *srcp = src;
1188    return (r);
1189}
1190
1191