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