📄 remote_gdb.cc
字号:
/* * Copyright (c) 2002, 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Nathan L. Binkert *//* * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratories. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 *//*- * Copyright (c) 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *//* * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ * * Taken from NetBSD * * "Stub" to allow remote cpu to debug over a serial line using gdb. */#include <sys/signal.h>#include <string>#include <unistd.h>#include "config/full_system.hh"#if FULL_SYSTEM#include "arch/vtophys.hh"#endif#include "base/intmath.hh"#include "base/remote_gdb.hh"#include "base/socket.hh"#include "base/trace.hh"#include "cpu/thread_context.hh"#include "cpu/static_inst.hh"//#include "mem/physical.hh"#include "mem/port.hh"#include "mem/translating_port.hh"#include "sim/system.hh"using namespace std;using namespace TheISA;#ifndef NDEBUGvector<BaseRemoteGDB *> debuggers;voiddebugger(){ static int current_debugger = -1; if (current_debugger >= 0 && current_debugger < debuggers.size()) { BaseRemoteGDB *gdb = debuggers[current_debugger]; if (!gdb->isattached()) gdb->listener->accept(); if (gdb->isattached()) gdb->trap(SIGILL); }}#endif/////////////////////////////////////////////////////////////////GDBListener::Event::Event(GDBListener *l, int fd, int e) : PollEvent(fd, e), listener(l){}voidGDBListener::Event::process(int revent){ listener->accept();}GDBListener::GDBListener(BaseRemoteGDB *g, int p) : event(NULL), gdb(g), port(p){ assert(!gdb->listener); gdb->listener = this;}GDBListener::~GDBListener(){ if (event) delete event;}stringGDBListener::name(){ return gdb->name() + ".listener";}voidGDBListener::listen(){ while (!listener.listen(port, true)) { DPRINTF(GDBMisc, "Can't bind port %d\n", port); port++; } event = new Event(this, listener.getfd(), POLLIN); pollQueue.schedule(event);#ifndef NDEBUG gdb->number = debuggers.size(); debuggers.push_back(gdb);#endif#ifndef NDEBUG ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n", curTick, name(), gdb->number, port);#else ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n", curTick, name(), port);#endif}voidGDBListener::accept(){ if (!listener.islistening()) panic("GDBListener::accept(): cannot accept if we're not listening!"); int sfd = listener.accept(true); if (sfd != -1) { if (gdb->isattached()) close(sfd); else gdb->attach(sfd); }}BaseRemoteGDB::Event::Event(BaseRemoteGDB *g, int fd, int e) : PollEvent(fd, e), gdb(g){}voidBaseRemoteGDB::Event::process(int revent){ if (revent & POLLIN) gdb->trap(SIGILL); else if (revent & POLLNVAL) gdb->detach();}BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, size_t cacheSize) : event(NULL), listener(NULL), number(-1), fd(-1), active(false), attached(false), system(_system), pmem(_system->physmem), context(c), gdbregs(cacheSize){ memset(gdbregs.regs, 0, gdbregs.bytes());}BaseRemoteGDB::~BaseRemoteGDB(){ if (event) delete event;}stringBaseRemoteGDB::name(){ return system->name() + ".remote_gdb";}boolBaseRemoteGDB::isattached(){ return attached; }voidBaseRemoteGDB::attach(int f){ fd = f; event = new Event(this, fd, POLLIN); pollQueue.schedule(event); attached = true; DPRINTFN("remote gdb attached\n");}voidBaseRemoteGDB::detach(){ attached = false; close(fd); fd = -1; pollQueue.remove(event); DPRINTFN("remote gdb detached\n");}const char *BaseRemoteGDB::gdb_command(char cmd){ switch (cmd) { case GDBSignal: return "KGDB_SIGNAL"; case GDBSetBaud: return "KGDB_SET_BAUD"; case GDBSetBreak: return "KGDB_SET_BREAK"; case GDBCont: return "KGDB_CONT"; case GDBAsyncCont: return "KGDB_ASYNC_CONT"; case GDBDebug: return "KGDB_DEBUG"; case GDBDetach: return "KGDB_DETACH"; case GDBRegR: return "KGDB_REG_R"; case GDBRegW: return "KGDB_REG_W"; case GDBSetThread: return "KGDB_SET_THREAD"; case GDBCycleStep: return "KGDB_CYCLE_STEP"; case GDBSigCycleStep: return "KGDB_SIG_CYCLE_STEP"; case GDBKill: return "KGDB_KILL"; case GDBMemW: return "KGDB_MEM_W"; case GDBMemR: return "KGDB_MEM_R"; case GDBSetReg: return "KGDB_SET_REG"; case GDBReadReg: return "KGDB_READ_REG"; case GDBQueryVar: return "KGDB_QUERY_VAR"; case GDBSetVar: return "KGDB_SET_VAR"; case GDBReset: return "KGDB_RESET"; case GDBStep: return "KGDB_STEP"; case GDBAsyncStep: return "KGDB_ASYNC_STEP"; case GDBThreadAlive: return "KGDB_THREAD_ALIVE"; case GDBTargetExit: return "KGDB_TARGET_EXIT"; case GDBBinaryDload: return "KGDB_BINARY_DLOAD"; case GDBClrHwBkpt: return "KGDB_CLR_HW_BKPT"; case GDBSetHwBkpt: return "KGDB_SET_HW_BKPT"; case GDBStart: return "KGDB_START"; case GDBEnd: return "KGDB_END"; case GDBGoodP: return "KGDB_GOODP"; case GDBBadP: return "KGDB_BADP"; default: return "KGDB_UNKNOWN"; }}/////////////////////////////uint8_tBaseRemoteGDB::getbyte(){ uint8_t b; ::read(fd, &b, 1); return b;}voidBaseRemoteGDB::putbyte(uint8_t b){ ::write(fd, &b, 1);}// Send a packet to gdbvoidBaseRemoteGDB::send(const char *bp){ const char *p; uint8_t csum, c; DPRINTF(GDBSend, "send: %s\n", bp); do { p = bp; //Start sending a packet putbyte(GDBStart); //Send the contents, and also keep a check sum. for (csum = 0; (c = *p); p++) { putbyte(c); csum += c; } //Send the ending character. putbyte(GDBEnd); //Sent the checksum. putbyte(i2digit(csum >> 4)); putbyte(i2digit(csum)); //Try transmitting over and over again until the other end doesn't send an //error back. } while ((c = getbyte() & 0x7f) == GDBBadP);}// Receive a packet from gdbintBaseRemoteGDB::recv(char *bp, int maxlen){ char *p; int c, csum; int len; do { p = bp; csum = len = 0; //Find the beginning of a packet while ((c = getbyte()) != GDBStart) ; //Read until you find the end of the data in the packet, and keep //track of the check sum. while ((c = getbyte()) != GDBEnd && len < maxlen) { c &= 0x7f; csum += c; *p++ = c; len++; } //Mask the check sum, and terminate the command string. csum &= 0xff; *p = '\0'; //If the command was too long, report an error. if (len >= maxlen) { putbyte(GDBBadP); continue; } //Bring in the checksum. If the check sum matches, csum will be 0. csum -= digit2i(getbyte()) * 16; csum -= digit2i(getbyte()); //If the check sum was correct if (csum == 0) { //Report that the packet was received correctly putbyte(GDBGoodP); // Sequence present? if (bp[2] == ':') { putbyte(bp[0]); putbyte(bp[1]); len -= 3; memcpy(bp, bp+3, len); } break; } //Otherwise, report that there was a mistake. putbyte(GDBBadP); } while (1); DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp); return (len);}// Read bytes from kernel address space for debugger.boolBaseRemoteGDB::read(Addr vaddr, size_t size, char *data){ static Addr lastaddr = 0; static size_t lastsize = 0; if (vaddr < 10) { DPRINTF(GDBRead, "read: reading memory location zero!\n"); vaddr = lastaddr + lastsize; } DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);#if FULL_SYSTEM VirtualPort *port = context->getVirtPort(context);#else TranslatingPort *port = context->getMemPort();#endif port->readBlob(vaddr, (uint8_t*)data, size);#if FULL_SYSTEM context->delVirtPort(port);#endif#if TRACING_ON if (DTRACE(GDBRead)) { if (DTRACE(GDBExtra)) { char buf[1024]; mem2hex(buf, data, size); DPRINTFNR(": %s\n", buf); } else DPRINTFNR("\n"); }#endif return true;}// Write bytes to kernel address space for debugger.boolBaseRemoteGDB::write(Addr vaddr, size_t size, const char *data){ static Addr lastaddr = 0; static size_t lastsize = 0; if (vaddr < 10) { DPRINTF(GDBWrite, "write: writing memory location zero!\n"); vaddr = lastaddr + lastsize; } if (DTRACE(GDBWrite)) { DPRINTFN("write: addr=%#x, size=%d", vaddr, size); if (DTRACE(GDBExtra)) { char buf[1024]; mem2hex(buf, data, size); DPRINTFNR(": %s\n", buf); } else DPRINTFNR("\n"); }#if FULL_SYSTEM VirtualPort *port = context->getVirtPort(context);#else TranslatingPort *port = context->getMemPort();#endif port->writeBlob(vaddr, (uint8_t*)data, size);#if FULL_SYSTEM context->delVirtPort(port);#else delete port;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -