remote_gdb.cc revision 8332
112854Sgabeblack@google.com/* 212854Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 312854Sgabeblack@google.com * All rights reserved. 412854Sgabeblack@google.com * 512854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612854Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112854Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412854Sgabeblack@google.com * this software without specific prior written permission. 1512854Sgabeblack@google.com * 1612854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712854Sgabeblack@google.com * 2812854Sgabeblack@google.com * Authors: Nathan Binkert 2912854Sgabeblack@google.com */ 3012854Sgabeblack@google.com 3112854Sgabeblack@google.com/* 3212854Sgabeblack@google.com * Copyright (c) 1990, 1993 The Regents of the University of California 3312854Sgabeblack@google.com * All rights reserved 3412854Sgabeblack@google.com * 3512854Sgabeblack@google.com * This software was developed by the Computer Systems Engineering group 3612854Sgabeblack@google.com * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 3712854Sgabeblack@google.com * contributed to Berkeley. 3812854Sgabeblack@google.com * 3912854Sgabeblack@google.com * All advertising materials mentioning features or use of this software 4012854Sgabeblack@google.com * must display the following acknowledgement: 4112854Sgabeblack@google.com * This product includes software developed by the University of 4212854Sgabeblack@google.com * California, Lawrence Berkeley Laboratories. 4312854Sgabeblack@google.com * 4412854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 4512854Sgabeblack@google.com * modification, are permitted provided that the following conditions 4612854Sgabeblack@google.com * are met: 4712854Sgabeblack@google.com * 1. Redistributions of source code must retain the above copyright 4812854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer. 4912854Sgabeblack@google.com * 2. Redistributions in binary form must reproduce the above copyright 5012854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 5112854Sgabeblack@google.com * documentation and/or other materials provided with the distribution. 5212854Sgabeblack@google.com * 3. All advertising materials mentioning features or use of this software 5312854Sgabeblack@google.com * must display the following acknowledgement: 5412854Sgabeblack@google.com * This product includes software developed by the University of 5512854Sgabeblack@google.com * California, Berkeley and its contributors. 5612854Sgabeblack@google.com * 4. Neither the name of the University nor the names of its contributors 5712854Sgabeblack@google.com * may be used to endorse or promote products derived from this software 5812854Sgabeblack@google.com * without specific prior written permission. 5912854Sgabeblack@google.com * 6012854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 6112854Sgabeblack@google.com * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6212854Sgabeblack@google.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6312854Sgabeblack@google.com * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 6412854Sgabeblack@google.com * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6512854Sgabeblack@google.com * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 6612854Sgabeblack@google.com * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6712854Sgabeblack@google.com * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6812854Sgabeblack@google.com * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6912854Sgabeblack@google.com * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 7012854Sgabeblack@google.com * SUCH DAMAGE. 7112854Sgabeblack@google.com * 7212854Sgabeblack@google.com * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 7312854Sgabeblack@google.com */ 7412854Sgabeblack@google.com 7512854Sgabeblack@google.com/*- 7612854Sgabeblack@google.com * Copyright (c) 2001 The NetBSD Foundation, Inc. 7712854Sgabeblack@google.com * All rights reserved. 7812854Sgabeblack@google.com * 7912854Sgabeblack@google.com * This code is derived from software contributed to The NetBSD Foundation 8012854Sgabeblack@google.com * by Jason R. Thorpe. 8112854Sgabeblack@google.com * 8212854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 8312854Sgabeblack@google.com * modification, are permitted provided that the following conditions 8412854Sgabeblack@google.com * are met: 8513325Sgabeblack@google.com * 1. Redistributions of source code must retain the above copyright 8612854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer. 8712854Sgabeblack@google.com * 2. Redistributions in binary form must reproduce the above copyright 8812854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 8912854Sgabeblack@google.com * documentation and/or other materials provided with the distribution. 9012854Sgabeblack@google.com * 3. All advertising materials mentioning features or use of this software 9112854Sgabeblack@google.com * must display the following acknowledgement: 9212854Sgabeblack@google.com * This product includes software developed by the NetBSD 9312854Sgabeblack@google.com * Foundation, Inc. and its contributors. 9412854Sgabeblack@google.com * 4. Neither the name of The NetBSD Foundation nor the names of its 9512854Sgabeblack@google.com * contributors may be used to endorse or promote products derived 9612854Sgabeblack@google.com * from this software without specific prior written permission. 9712854Sgabeblack@google.com * 9812854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 9912854Sgabeblack@google.com * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 10012854Sgabeblack@google.com * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 10112854Sgabeblack@google.com * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 10212854Sgabeblack@google.com * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 10312854Sgabeblack@google.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 10412854Sgabeblack@google.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 10512854Sgabeblack@google.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 10612854Sgabeblack@google.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10712854Sgabeblack@google.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 10812854Sgabeblack@google.com * POSSIBILITY OF SUCH DAMAGE. 10912854Sgabeblack@google.com */ 11012854Sgabeblack@google.com 11112854Sgabeblack@google.com/* 11212854Sgabeblack@google.com * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ 11312854Sgabeblack@google.com * 11413325Sgabeblack@google.com * Taken from NetBSD 11512854Sgabeblack@google.com * 11612854Sgabeblack@google.com * "Stub" to allow remote cpu to debug over a serial line using gdb. 11712854Sgabeblack@google.com */ 11812854Sgabeblack@google.com 11912854Sgabeblack@google.com#include <sys/signal.h> 12012854Sgabeblack@google.com#include <unistd.h> 12112854Sgabeblack@google.com 12212854Sgabeblack@google.com#include <cstdio> 12312854Sgabeblack@google.com#include <string> 12412854Sgabeblack@google.com 12512854Sgabeblack@google.com#include "config/full_system.hh" 12612854Sgabeblack@google.com 12713322Sgabeblack@google.com#if FULL_SYSTEM 12812854Sgabeblack@google.com#include "arch/vtophys.hh" 12912854Sgabeblack@google.com#include "mem/vport.hh" 13012854Sgabeblack@google.com#endif 13112854Sgabeblack@google.com 13212854Sgabeblack@google.com#include "base/intmath.hh" 13312854Sgabeblack@google.com#include "base/remote_gdb.hh" 13412854Sgabeblack@google.com#include "base/socket.hh" 13512854Sgabeblack@google.com#include "base/trace.hh" 13613160Sgabeblack@google.com#include "config/the_isa.hh" 13712854Sgabeblack@google.com#include "cpu/static_inst.hh" 13812854Sgabeblack@google.com#include "cpu/thread_context.hh" 13913322Sgabeblack@google.com#include "debug/GDBAll.hh" 14012854Sgabeblack@google.com#include "mem/port.hh" 14112854Sgabeblack@google.com#include "mem/translating_port.hh" 14212854Sgabeblack@google.com#include "sim/system.hh" 14312854Sgabeblack@google.com 14412854Sgabeblack@google.comusing namespace std; 14512854Sgabeblack@google.comusing namespace Debug; 14612854Sgabeblack@google.comusing namespace TheISA; 14712854Sgabeblack@google.com 14812854Sgabeblack@google.com#ifndef NDEBUG 14912854Sgabeblack@google.comvector<BaseRemoteGDB *> debuggers; 15012854Sgabeblack@google.com 15112854Sgabeblack@google.comvoid 15212854Sgabeblack@google.comdebugger() 15312854Sgabeblack@google.com{ 15412854Sgabeblack@google.com static int current_debugger = -1; 15512854Sgabeblack@google.com if (current_debugger >= 0 && current_debugger < (int)debuggers.size()) { 15612854Sgabeblack@google.com BaseRemoteGDB *gdb = debuggers[current_debugger]; 15712854Sgabeblack@google.com if (!gdb->isattached()) 15812854Sgabeblack@google.com gdb->listener->accept(); 15912854Sgabeblack@google.com if (gdb->isattached()) 16012854Sgabeblack@google.com gdb->trap(SIGILL); 16112854Sgabeblack@google.com } 16212854Sgabeblack@google.com} 16312854Sgabeblack@google.com#endif 16412854Sgabeblack@google.com 16512854Sgabeblack@google.com/////////////////////////////////////////////////////////// 16612854Sgabeblack@google.com// 16712854Sgabeblack@google.com// 16812854Sgabeblack@google.com// 16912854Sgabeblack@google.com 17012854Sgabeblack@google.comGDBListener::Event::Event(GDBListener *l, int fd, int e) 17112854Sgabeblack@google.com : PollEvent(fd, e), listener(l) 17212854Sgabeblack@google.com{} 17312854Sgabeblack@google.com 17412854Sgabeblack@google.comvoid 17512854Sgabeblack@google.comGDBListener::Event::process(int revent) 17612854Sgabeblack@google.com{ 17712854Sgabeblack@google.com listener->accept(); 17812854Sgabeblack@google.com} 17912854Sgabeblack@google.com 18012854Sgabeblack@google.comGDBListener::GDBListener(BaseRemoteGDB *g, int p) 18112854Sgabeblack@google.com : event(NULL), gdb(g), port(p) 18212854Sgabeblack@google.com{ 18312854Sgabeblack@google.com assert(!gdb->listener); 18412854Sgabeblack@google.com gdb->listener = this; 18512854Sgabeblack@google.com} 18612854Sgabeblack@google.com 18712854Sgabeblack@google.comGDBListener::~GDBListener() 18812854Sgabeblack@google.com{ 18912854Sgabeblack@google.com if (event) 19012854Sgabeblack@google.com delete event; 19112854Sgabeblack@google.com} 19212854Sgabeblack@google.com 19312854Sgabeblack@google.comstring 19412854Sgabeblack@google.comGDBListener::name() 19512854Sgabeblack@google.com{ 19612854Sgabeblack@google.com return gdb->name() + ".listener"; 19712854Sgabeblack@google.com} 19812854Sgabeblack@google.com 19912854Sgabeblack@google.comvoid 20012854Sgabeblack@google.comGDBListener::listen() 20112854Sgabeblack@google.com{ 20212854Sgabeblack@google.com if (ListenSocket::allDisabled()) { 20312854Sgabeblack@google.com warn_once("Sockets disabled, not accepting gdb connections"); 20412854Sgabeblack@google.com return; 20512854Sgabeblack@google.com } 20612854Sgabeblack@google.com 20712854Sgabeblack@google.com while (!listener.listen(port, true)) { 20812854Sgabeblack@google.com DPRINTF(GDBMisc, "Can't bind port %d\n", port); 20912854Sgabeblack@google.com port++; 21012854Sgabeblack@google.com } 21112854Sgabeblack@google.com 21212854Sgabeblack@google.com event = new Event(this, listener.getfd(), POLLIN); 21312854Sgabeblack@google.com pollQueue.schedule(event); 21412854Sgabeblack@google.com 21512854Sgabeblack@google.com#ifndef NDEBUG 21612854Sgabeblack@google.com gdb->number = debuggers.size(); 21712854Sgabeblack@google.com debuggers.push_back(gdb); 21812854Sgabeblack@google.com#endif 21912854Sgabeblack@google.com 22012854Sgabeblack@google.com#ifndef NDEBUG 22112854Sgabeblack@google.com ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n", 22212854Sgabeblack@google.com curTick(), name(), gdb->number, port); 22312854Sgabeblack@google.com#else 22412854Sgabeblack@google.com ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n", 22512854Sgabeblack@google.com curTick(), name(), port); 22612854Sgabeblack@google.com#endif 22712854Sgabeblack@google.com} 22812854Sgabeblack@google.com 22912854Sgabeblack@google.comvoid 23012854Sgabeblack@google.comGDBListener::accept() 23112854Sgabeblack@google.com{ 23212854Sgabeblack@google.com if (!listener.islistening()) 23312854Sgabeblack@google.com panic("GDBListener::accept(): cannot accept if we're not listening!"); 23412854Sgabeblack@google.com 23512854Sgabeblack@google.com int sfd = listener.accept(true); 23612854Sgabeblack@google.com 23712854Sgabeblack@google.com if (sfd != -1) { 23812854Sgabeblack@google.com if (gdb->isattached()) 23912854Sgabeblack@google.com close(sfd); 24012854Sgabeblack@google.com else 24112854Sgabeblack@google.com gdb->attach(sfd); 24212854Sgabeblack@google.com } 24312854Sgabeblack@google.com} 24412854Sgabeblack@google.com 24512854Sgabeblack@google.comBaseRemoteGDB::Event::Event(BaseRemoteGDB *g, int fd, int e) 24612854Sgabeblack@google.com : PollEvent(fd, e), gdb(g) 24712854Sgabeblack@google.com{} 24812854Sgabeblack@google.com 24912854Sgabeblack@google.comvoid 25012854Sgabeblack@google.comBaseRemoteGDB::Event::process(int revent) 25112854Sgabeblack@google.com{ 25212854Sgabeblack@google.com if (revent & POLLIN) 25312854Sgabeblack@google.com gdb->trap(SIGILL); 25412854Sgabeblack@google.com else if (revent & POLLNVAL) 25512854Sgabeblack@google.com gdb->detach(); 25612854Sgabeblack@google.com} 25712854Sgabeblack@google.com 25812854Sgabeblack@google.comBaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, size_t cacheSize) 25912854Sgabeblack@google.com : event(NULL), listener(NULL), number(-1), fd(-1), 26012854Sgabeblack@google.com active(false), attached(false), 26112854Sgabeblack@google.com system(_system), pmem(_system->physmem), context(c), 26212854Sgabeblack@google.com gdbregs(cacheSize) 26312854Sgabeblack@google.com{ 26412854Sgabeblack@google.com memset(gdbregs.regs, 0, gdbregs.bytes()); 26512854Sgabeblack@google.com} 26612854Sgabeblack@google.com 26712854Sgabeblack@google.comBaseRemoteGDB::~BaseRemoteGDB() 26812854Sgabeblack@google.com{ 26912854Sgabeblack@google.com if (event) 27012854Sgabeblack@google.com delete event; 27112854Sgabeblack@google.com} 27212854Sgabeblack@google.com 27312854Sgabeblack@google.comstring 27412854Sgabeblack@google.comBaseRemoteGDB::name() 27512854Sgabeblack@google.com{ 27612854Sgabeblack@google.com return system->name() + ".remote_gdb"; 27712854Sgabeblack@google.com} 27812854Sgabeblack@google.com 27912854Sgabeblack@google.combool 28012854Sgabeblack@google.comBaseRemoteGDB::isattached() 28112854Sgabeblack@google.com{ return attached; } 28212854Sgabeblack@google.com 28312854Sgabeblack@google.comvoid 28412854Sgabeblack@google.comBaseRemoteGDB::attach(int f) 28512854Sgabeblack@google.com{ 28612854Sgabeblack@google.com fd = f; 28712854Sgabeblack@google.com 28812854Sgabeblack@google.com event = new Event(this, fd, POLLIN); 28912854Sgabeblack@google.com pollQueue.schedule(event); 29012854Sgabeblack@google.com 29112854Sgabeblack@google.com attached = true; 29212854Sgabeblack@google.com DPRINTFN("remote gdb attached\n"); 29312854Sgabeblack@google.com} 29412854Sgabeblack@google.com 29512854Sgabeblack@google.comvoid 29612854Sgabeblack@google.comBaseRemoteGDB::detach() 29712854Sgabeblack@google.com{ 29812854Sgabeblack@google.com attached = false; 29912854Sgabeblack@google.com close(fd); 30012854Sgabeblack@google.com fd = -1; 30112854Sgabeblack@google.com 30212854Sgabeblack@google.com pollQueue.remove(event); 30312854Sgabeblack@google.com DPRINTFN("remote gdb detached\n"); 30412854Sgabeblack@google.com} 30512854Sgabeblack@google.com 30612854Sgabeblack@google.comconst char * 30712854Sgabeblack@google.comBaseRemoteGDB::gdb_command(char cmd) 30812854Sgabeblack@google.com{ 30912854Sgabeblack@google.com switch (cmd) { 31012854Sgabeblack@google.com case GDBSignal: return "KGDB_SIGNAL"; 31112854Sgabeblack@google.com case GDBSetBaud: return "KGDB_SET_BAUD"; 31212854Sgabeblack@google.com case GDBSetBreak: return "KGDB_SET_BREAK"; 31312854Sgabeblack@google.com case GDBCont: return "KGDB_CONT"; 31412854Sgabeblack@google.com case GDBAsyncCont: return "KGDB_ASYNC_CONT"; 31512854Sgabeblack@google.com case GDBDebug: return "KGDB_DEBUG"; 31612854Sgabeblack@google.com case GDBDetach: return "KGDB_DETACH"; 31712854Sgabeblack@google.com case GDBRegR: return "KGDB_REG_R"; 31812854Sgabeblack@google.com case GDBRegW: return "KGDB_REG_W"; 31912854Sgabeblack@google.com case GDBSetThread: return "KGDB_SET_THREAD"; 32012854Sgabeblack@google.com case GDBCycleStep: return "KGDB_CYCLE_STEP"; 32112854Sgabeblack@google.com case GDBSigCycleStep: return "KGDB_SIG_CYCLE_STEP"; 32212854Sgabeblack@google.com case GDBKill: return "KGDB_KILL"; 32312854Sgabeblack@google.com case GDBMemW: return "KGDB_MEM_W"; 32412854Sgabeblack@google.com case GDBMemR: return "KGDB_MEM_R"; 32512854Sgabeblack@google.com case GDBSetReg: return "KGDB_SET_REG"; 32612854Sgabeblack@google.com case GDBReadReg: return "KGDB_READ_REG"; 32712854Sgabeblack@google.com case GDBQueryVar: return "KGDB_QUERY_VAR"; 32812854Sgabeblack@google.com case GDBSetVar: return "KGDB_SET_VAR"; 32912854Sgabeblack@google.com case GDBReset: return "KGDB_RESET"; 33012854Sgabeblack@google.com case GDBStep: return "KGDB_STEP"; 33112854Sgabeblack@google.com case GDBAsyncStep: return "KGDB_ASYNC_STEP"; 33212854Sgabeblack@google.com case GDBThreadAlive: return "KGDB_THREAD_ALIVE"; 33312854Sgabeblack@google.com case GDBTargetExit: return "KGDB_TARGET_EXIT"; 33412854Sgabeblack@google.com case GDBBinaryDload: return "KGDB_BINARY_DLOAD"; 33512854Sgabeblack@google.com case GDBClrHwBkpt: return "KGDB_CLR_HW_BKPT"; 33612854Sgabeblack@google.com case GDBSetHwBkpt: return "KGDB_SET_HW_BKPT"; 33712854Sgabeblack@google.com case GDBStart: return "KGDB_START"; 33812854Sgabeblack@google.com case GDBEnd: return "KGDB_END"; 33912854Sgabeblack@google.com case GDBGoodP: return "KGDB_GOODP"; 34012854Sgabeblack@google.com case GDBBadP: return "KGDB_BADP"; 34112854Sgabeblack@google.com default: return "KGDB_UNKNOWN"; 34212854Sgabeblack@google.com } 34312854Sgabeblack@google.com} 34412854Sgabeblack@google.com 34512854Sgabeblack@google.com///////////////////////// 34612854Sgabeblack@google.com// 34712854Sgabeblack@google.com// 34812854Sgabeblack@google.com 34912854Sgabeblack@google.comuint8_t 35012854Sgabeblack@google.comBaseRemoteGDB::getbyte() 35112854Sgabeblack@google.com{ 35212854Sgabeblack@google.com uint8_t b; 35312854Sgabeblack@google.com if (::read(fd, &b, 1) != 1) 35412854Sgabeblack@google.com warn("could not read byte from debugger"); 35512854Sgabeblack@google.com return b; 35612854Sgabeblack@google.com} 35712854Sgabeblack@google.com 35812854Sgabeblack@google.comvoid 35912854Sgabeblack@google.comBaseRemoteGDB::putbyte(uint8_t b) 36012854Sgabeblack@google.com{ 36112854Sgabeblack@google.com if (::write(fd, &b, 1) != 1) 36212854Sgabeblack@google.com warn("could not write byte to debugger"); 36312854Sgabeblack@google.com} 36412854Sgabeblack@google.com 36512854Sgabeblack@google.com// Send a packet to gdb 36612854Sgabeblack@google.comvoid 36712854Sgabeblack@google.comBaseRemoteGDB::send(const char *bp) 36812854Sgabeblack@google.com{ 36912854Sgabeblack@google.com const char *p; 37012854Sgabeblack@google.com uint8_t csum, c; 37112854Sgabeblack@google.com 37212854Sgabeblack@google.com DPRINTF(GDBSend, "send: %s\n", bp); 37312854Sgabeblack@google.com 37412854Sgabeblack@google.com do { 37512854Sgabeblack@google.com p = bp; 37612854Sgabeblack@google.com //Start sending a packet 37712854Sgabeblack@google.com putbyte(GDBStart); 37812854Sgabeblack@google.com //Send the contents, and also keep a check sum. 37912854Sgabeblack@google.com for (csum = 0; (c = *p); p++) { 38012854Sgabeblack@google.com putbyte(c); 38112854Sgabeblack@google.com csum += c; 38212854Sgabeblack@google.com } 38312854Sgabeblack@google.com //Send the ending character. 38412854Sgabeblack@google.com putbyte(GDBEnd); 38512854Sgabeblack@google.com //Sent the checksum. 38612854Sgabeblack@google.com putbyte(i2digit(csum >> 4)); 38712854Sgabeblack@google.com putbyte(i2digit(csum)); 38812854Sgabeblack@google.com //Try transmitting over and over again until the other end doesn't send an 38912854Sgabeblack@google.com //error back. 39012854Sgabeblack@google.com } while ((c = getbyte() & 0x7f) == GDBBadP); 39112854Sgabeblack@google.com} 39212854Sgabeblack@google.com 39312854Sgabeblack@google.com// Receive a packet from gdb 39412854Sgabeblack@google.comint 39512854Sgabeblack@google.comBaseRemoteGDB::recv(char *bp, int maxlen) 39612854Sgabeblack@google.com{ 39712854Sgabeblack@google.com char *p; 39812854Sgabeblack@google.com int c, csum; 39912854Sgabeblack@google.com int len; 40012854Sgabeblack@google.com 40112854Sgabeblack@google.com do { 40212854Sgabeblack@google.com p = bp; 40312854Sgabeblack@google.com csum = len = 0; 40412854Sgabeblack@google.com //Find the beginning of a packet 40512854Sgabeblack@google.com while ((c = getbyte()) != GDBStart) 40612854Sgabeblack@google.com ; 40712854Sgabeblack@google.com 40812854Sgabeblack@google.com //Read until you find the end of the data in the packet, and keep 40912854Sgabeblack@google.com //track of the check sum. 41012854Sgabeblack@google.com while ((c = getbyte()) != GDBEnd && len < maxlen) { 41112854Sgabeblack@google.com c &= 0x7f; 41212854Sgabeblack@google.com csum += c; 41312854Sgabeblack@google.com *p++ = c; 41412854Sgabeblack@google.com len++; 41512854Sgabeblack@google.com } 41612854Sgabeblack@google.com 41712854Sgabeblack@google.com //Mask the check sum, and terminate the command string. 41812854Sgabeblack@google.com csum &= 0xff; 41912854Sgabeblack@google.com *p = '\0'; 42012854Sgabeblack@google.com 42112854Sgabeblack@google.com //If the command was too long, report an error. 42212854Sgabeblack@google.com if (len >= maxlen) { 42312854Sgabeblack@google.com putbyte(GDBBadP); 42412854Sgabeblack@google.com continue; 42512854Sgabeblack@google.com } 42612854Sgabeblack@google.com 42712854Sgabeblack@google.com //Bring in the checksum. If the check sum matches, csum will be 0. 42812854Sgabeblack@google.com csum -= digit2i(getbyte()) * 16; 42912854Sgabeblack@google.com csum -= digit2i(getbyte()); 43012854Sgabeblack@google.com 43112854Sgabeblack@google.com //If the check sum was correct 43212854Sgabeblack@google.com if (csum == 0) { 43312854Sgabeblack@google.com //Report that the packet was received correctly 43412854Sgabeblack@google.com putbyte(GDBGoodP); 43512854Sgabeblack@google.com // Sequence present? 43612854Sgabeblack@google.com if (bp[2] == ':') { 43712854Sgabeblack@google.com putbyte(bp[0]); 43812854Sgabeblack@google.com putbyte(bp[1]); 43912854Sgabeblack@google.com len -= 3; 44012854Sgabeblack@google.com memcpy(bp, bp+3, len); 44112854Sgabeblack@google.com } 44212854Sgabeblack@google.com break; 44312854Sgabeblack@google.com } 44413325Sgabeblack@google.com //Otherwise, report that there was a mistake. 44512854Sgabeblack@google.com putbyte(GDBBadP); 44612854Sgabeblack@google.com } while (1); 44713325Sgabeblack@google.com 44812854Sgabeblack@google.com DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp); 44912854Sgabeblack@google.com 45012854Sgabeblack@google.com return (len); 45112854Sgabeblack@google.com} 45212854Sgabeblack@google.com 45312854Sgabeblack@google.com// Read bytes from kernel address space for debugger. 45412854Sgabeblack@google.combool 45512854Sgabeblack@google.comBaseRemoteGDB::read(Addr vaddr, size_t size, char *data) 45613325Sgabeblack@google.com{ 45712854Sgabeblack@google.com static Addr lastaddr = 0; 45812854Sgabeblack@google.com static size_t lastsize = 0; 45912854Sgabeblack@google.com 46012854Sgabeblack@google.com if (vaddr < 10) { 46112854Sgabeblack@google.com DPRINTF(GDBRead, "read: reading memory location zero!\n"); 46212854Sgabeblack@google.com vaddr = lastaddr + lastsize; 46312854Sgabeblack@google.com } 46412854Sgabeblack@google.com 46512854Sgabeblack@google.com DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size); 46612854Sgabeblack@google.com 46712854Sgabeblack@google.com#if FULL_SYSTEM 46812854Sgabeblack@google.com VirtualPort *port = context->getVirtPort(); 46912854Sgabeblack@google.com#else 47012854Sgabeblack@google.com TranslatingPort *port = context->getMemPort(); 47112854Sgabeblack@google.com#endif 47212854Sgabeblack@google.com port->readBlob(vaddr, (uint8_t*)data, size); 47312854Sgabeblack@google.com 47412854Sgabeblack@google.com#if TRACING_ON 47512854Sgabeblack@google.com if (DTRACE(GDBRead)) { 47612854Sgabeblack@google.com if (DTRACE(GDBExtra)) { 47712854Sgabeblack@google.com char buf[1024]; 47812854Sgabeblack@google.com mem2hex(buf, data, size); 47912854Sgabeblack@google.com DPRINTFNR(": %s\n", buf); 48012854Sgabeblack@google.com } else 48112854Sgabeblack@google.com DPRINTFNR("\n"); 48212854Sgabeblack@google.com } 48312854Sgabeblack@google.com#endif 48412854Sgabeblack@google.com 48512854Sgabeblack@google.com return true; 48612854Sgabeblack@google.com} 48712854Sgabeblack@google.com 48812854Sgabeblack@google.com// Write bytes to kernel address space for debugger. 48912854Sgabeblack@google.combool 49012854Sgabeblack@google.comBaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) 49112854Sgabeblack@google.com{ 49212854Sgabeblack@google.com static Addr lastaddr = 0; 49312854Sgabeblack@google.com static size_t lastsize = 0; 49412854Sgabeblack@google.com 49512854Sgabeblack@google.com if (vaddr < 10) { 49612854Sgabeblack@google.com DPRINTF(GDBWrite, "write: writing memory location zero!\n"); 49712854Sgabeblack@google.com vaddr = lastaddr + lastsize; 49812854Sgabeblack@google.com } 49912854Sgabeblack@google.com 50012854Sgabeblack@google.com if (DTRACE(GDBWrite)) { 50112854Sgabeblack@google.com DPRINTFN("write: addr=%#x, size=%d", vaddr, size); 50212854Sgabeblack@google.com if (DTRACE(GDBExtra)) { 50312854Sgabeblack@google.com char buf[1024]; 50412854Sgabeblack@google.com mem2hex(buf, data, size); 50512854Sgabeblack@google.com DPRINTFNR(": %s\n", buf); 50612854Sgabeblack@google.com } else 50712854Sgabeblack@google.com DPRINTFNR("\n"); 50812854Sgabeblack@google.com } 50912854Sgabeblack@google.com#if FULL_SYSTEM 51012854Sgabeblack@google.com VirtualPort *port = context->getVirtPort(); 51112854Sgabeblack@google.com#else 51212854Sgabeblack@google.com TranslatingPort *port = context->getMemPort(); 51312854Sgabeblack@google.com#endif 51412854Sgabeblack@google.com port->writeBlob(vaddr, (uint8_t*)data, size); 51512854Sgabeblack@google.com#if !FULL_SYSTEM 51612854Sgabeblack@google.com delete port; 51712854Sgabeblack@google.com#endif 51812854Sgabeblack@google.com 51912854Sgabeblack@google.com return true; 52012854Sgabeblack@google.com} 52112854Sgabeblack@google.com 52212854Sgabeblack@google.comPCEventQueue *BaseRemoteGDB::getPcEventQueue() 52312854Sgabeblack@google.com{ 52412854Sgabeblack@google.com return &system->pcEventQueue; 52512854Sgabeblack@google.com} 52612854Sgabeblack@google.com 52712854Sgabeblack@google.comBaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc) 52812854Sgabeblack@google.com : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc), 52912854Sgabeblack@google.com gdb(_gdb), refcount(0) 53012854Sgabeblack@google.com{ 53112854Sgabeblack@google.com DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc); 53212854Sgabeblack@google.com} 53312854Sgabeblack@google.com 53412854Sgabeblack@google.comvoid 53512854Sgabeblack@google.comBaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc) 53612854Sgabeblack@google.com{ 53712854Sgabeblack@google.com DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc()); 53812854Sgabeblack@google.com 53912854Sgabeblack@google.com if (tc == gdb->context) 54012854Sgabeblack@google.com gdb->trap(SIGTRAP); 54112854Sgabeblack@google.com} 54212854Sgabeblack@google.com 54312854Sgabeblack@google.combool 54412854Sgabeblack@google.comBaseRemoteGDB::insertSoftBreak(Addr addr, size_t len) 54512854Sgabeblack@google.com{ 54612854Sgabeblack@google.com if (len != sizeof(TheISA::MachInst)) 54712854Sgabeblack@google.com panic("invalid length\n"); 54812854Sgabeblack@google.com 54912854Sgabeblack@google.com return insertHardBreak(addr, len); 55012854Sgabeblack@google.com} 55112854Sgabeblack@google.com 55212854Sgabeblack@google.combool 55312854Sgabeblack@google.comBaseRemoteGDB::removeSoftBreak(Addr addr, size_t len) 55412854Sgabeblack@google.com{ 55512854Sgabeblack@google.com if (len != sizeof(MachInst)) 55612854Sgabeblack@google.com panic("invalid length\n"); 55712854Sgabeblack@google.com 55812854Sgabeblack@google.com return removeHardBreak(addr, len); 55912854Sgabeblack@google.com} 56012854Sgabeblack@google.com 56112854Sgabeblack@google.combool 56212854Sgabeblack@google.comBaseRemoteGDB::insertHardBreak(Addr addr, size_t len) 56312854Sgabeblack@google.com{ 56412854Sgabeblack@google.com if (len != sizeof(MachInst)) 56512854Sgabeblack@google.com panic("invalid length\n"); 56612854Sgabeblack@google.com 56712854Sgabeblack@google.com DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr); 56812854Sgabeblack@google.com 56912854Sgabeblack@google.com HardBreakpoint *&bkpt = hardBreakMap[addr]; 57012854Sgabeblack@google.com if (bkpt == 0) 57112854Sgabeblack@google.com bkpt = new HardBreakpoint(this, addr); 57212854Sgabeblack@google.com 57312854Sgabeblack@google.com bkpt->refcount++; 57412854Sgabeblack@google.com 57512854Sgabeblack@google.com return true; 57612854Sgabeblack@google.com} 57712854Sgabeblack@google.com 57812854Sgabeblack@google.combool 57912854Sgabeblack@google.comBaseRemoteGDB::removeHardBreak(Addr addr, size_t len) 58012854Sgabeblack@google.com{ 58112854Sgabeblack@google.com if (len != sizeof(MachInst)) 58212854Sgabeblack@google.com panic("invalid length\n"); 58312854Sgabeblack@google.com 58412854Sgabeblack@google.com DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr); 58512854Sgabeblack@google.com 58612854Sgabeblack@google.com break_iter_t i = hardBreakMap.find(addr); 58712854Sgabeblack@google.com if (i == hardBreakMap.end()) 58812854Sgabeblack@google.com return false; 58912854Sgabeblack@google.com 59012854Sgabeblack@google.com HardBreakpoint *hbp = (*i).second; 59112854Sgabeblack@google.com if (--hbp->refcount == 0) { 59212854Sgabeblack@google.com delete hbp; 59312854Sgabeblack@google.com hardBreakMap.erase(i); 59412854Sgabeblack@google.com } 59512854Sgabeblack@google.com 59612854Sgabeblack@google.com return true; 59712854Sgabeblack@google.com} 59812854Sgabeblack@google.com 59912854Sgabeblack@google.comvoid 60012854Sgabeblack@google.comBaseRemoteGDB::setTempBreakpoint(Addr bkpt) 60112854Sgabeblack@google.com{ 60212854Sgabeblack@google.com DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt); 60312854Sgabeblack@google.com insertHardBreak(bkpt, sizeof(TheISA::MachInst)); 60412854Sgabeblack@google.com} 60512854Sgabeblack@google.com 60612854Sgabeblack@google.comvoid 60712854Sgabeblack@google.comBaseRemoteGDB::clearTempBreakpoint(Addr &bkpt) 60812854Sgabeblack@google.com{ 60912854Sgabeblack@google.com DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt); 61012854Sgabeblack@google.com removeHardBreak(bkpt, sizeof(TheISA::MachInst)); 61112854Sgabeblack@google.com bkpt = 0; 61212854Sgabeblack@google.com} 61312854Sgabeblack@google.com 61412854Sgabeblack@google.comconst char * 61512854Sgabeblack@google.comBaseRemoteGDB::break_type(char c) 61612854Sgabeblack@google.com{ 61712854Sgabeblack@google.com switch(c) { 61812854Sgabeblack@google.com case '0': return "software breakpoint"; 61912854Sgabeblack@google.com case '1': return "hardware breakpoint"; 62012854Sgabeblack@google.com case '2': return "write watchpoint"; 62112854Sgabeblack@google.com case '3': return "read watchpoint"; 62212854Sgabeblack@google.com case '4': return "access watchpoint"; 62312854Sgabeblack@google.com default: return "unknown breakpoint/watchpoint"; 62412854Sgabeblack@google.com } 62512854Sgabeblack@google.com} 62612854Sgabeblack@google.com 62712854Sgabeblack@google.com// This function does all command processing for interfacing to a 62812854Sgabeblack@google.com// remote gdb. Note that the error codes are ignored by gdb at 62912854Sgabeblack@google.com// present, but might eventually become meaningful. (XXX) It might 63012854Sgabeblack@google.com// makes sense to use POSIX errno values, because that is what the 63112854Sgabeblack@google.com// gdb/remote.c functions want to return. 63212854Sgabeblack@google.combool 63312854Sgabeblack@google.comBaseRemoteGDB::trap(int type) 63412854Sgabeblack@google.com{ 63512854Sgabeblack@google.com uint64_t val; 63612854Sgabeblack@google.com size_t datalen, len; 63712854Sgabeblack@google.com char data[GDBPacketBufLen + 1]; 63812854Sgabeblack@google.com char *buffer; 63912854Sgabeblack@google.com size_t bufferSize; 64012854Sgabeblack@google.com const char *p; 64112854Sgabeblack@google.com char command, subcmd; 64212854Sgabeblack@google.com string var; 64312854Sgabeblack@google.com bool ret; 64412854Sgabeblack@google.com 64512854Sgabeblack@google.com if (!attached) 64612854Sgabeblack@google.com return false; 64712854Sgabeblack@google.com 64812854Sgabeblack@google.com bufferSize = gdbregs.bytes() * 2 + 256; 64912854Sgabeblack@google.com buffer = (char*)malloc(bufferSize); 65012854Sgabeblack@google.com 65112854Sgabeblack@google.com TheISA::PCState pc = context->pcState(); 65212854Sgabeblack@google.com DPRINTF(GDBMisc, "trap: PC=%s\n", pc); 65312854Sgabeblack@google.com 65412854Sgabeblack@google.com clearSingleStep(); 65512854Sgabeblack@google.com 65612854Sgabeblack@google.com /* 65712854Sgabeblack@google.com * The first entry to this function is normally through 65812854Sgabeblack@google.com * a breakpoint trap in kgdb_connect(), in which case we 65912854Sgabeblack@google.com * must advance past the breakpoint because gdb will not. 66012854Sgabeblack@google.com * 66112854Sgabeblack@google.com * On the first entry here, we expect that gdb is not yet 66212854Sgabeblack@google.com * listening to us, so just enter the interaction loop. 66312854Sgabeblack@google.com * After the debugger is "active" (connected) it will be 66412854Sgabeblack@google.com * waiting for a "signaled" message from us. 66512854Sgabeblack@google.com */ 66612854Sgabeblack@google.com if (!active) 66712854Sgabeblack@google.com active = true; 66812854Sgabeblack@google.com else 66912854Sgabeblack@google.com // Tell remote host that an exception has occurred. 67012854Sgabeblack@google.com snprintf((char *)buffer, bufferSize, "S%02x", type); 67112854Sgabeblack@google.com send(buffer); 67212854Sgabeblack@google.com 67312854Sgabeblack@google.com // Stick frame regs into our reg cache. 67412854Sgabeblack@google.com getregs(); 67512854Sgabeblack@google.com 67612854Sgabeblack@google.com for (;;) { 67712854Sgabeblack@google.com datalen = recv(data, sizeof(data)); 67812854Sgabeblack@google.com data[sizeof(data) - 1] = 0; // Sentinel 67912854Sgabeblack@google.com command = data[0]; 68012854Sgabeblack@google.com subcmd = 0; 68112854Sgabeblack@google.com p = data + 1; 68212854Sgabeblack@google.com switch (command) { 68312854Sgabeblack@google.com 68412854Sgabeblack@google.com case GDBSignal: 68512854Sgabeblack@google.com // if this command came from a running gdb, answer it -- 68612854Sgabeblack@google.com // the other guy has no way of knowing if we're in or out 68712854Sgabeblack@google.com // of this loop when he issues a "remote-signal". 68812854Sgabeblack@google.com snprintf((char *)buffer, bufferSize, 68912854Sgabeblack@google.com "S%02x", type); 69012854Sgabeblack@google.com send(buffer); 69112854Sgabeblack@google.com continue; 69212854Sgabeblack@google.com 69312854Sgabeblack@google.com case GDBRegR: 69412854Sgabeblack@google.com if (2 * gdbregs.bytes() > bufferSize) 69512854Sgabeblack@google.com panic("buffer too small"); 69612854Sgabeblack@google.com 69712854Sgabeblack@google.com mem2hex(buffer, gdbregs.regs, gdbregs.bytes()); 69812854Sgabeblack@google.com send(buffer); 69912854Sgabeblack@google.com continue; 70012854Sgabeblack@google.com 70112854Sgabeblack@google.com case GDBRegW: 70212854Sgabeblack@google.com p = hex2mem(gdbregs.regs, p, gdbregs.bytes()); 70312854Sgabeblack@google.com if (p == NULL || *p != '\0') 70412854Sgabeblack@google.com send("E01"); 70512854Sgabeblack@google.com else { 70612854Sgabeblack@google.com setregs(); 70712854Sgabeblack@google.com send("OK"); 70812854Sgabeblack@google.com } 70912854Sgabeblack@google.com continue; 71012854Sgabeblack@google.com 71112854Sgabeblack@google.com#if 0 71212854Sgabeblack@google.com case GDBSetReg: 71312854Sgabeblack@google.com val = hex2i(&p); 71412854Sgabeblack@google.com if (*p++ != '=') { 71512854Sgabeblack@google.com send("E01"); 71612854Sgabeblack@google.com continue; 71712854Sgabeblack@google.com } 71812854Sgabeblack@google.com if (val < 0 && val >= KGDB_NUMREGS) { 71912854Sgabeblack@google.com send("E01"); 72012854Sgabeblack@google.com continue; 72112854Sgabeblack@google.com } 72212854Sgabeblack@google.com 72312854Sgabeblack@google.com gdbregs.regs[val] = hex2i(&p); 72412854Sgabeblack@google.com setregs(); 72512854Sgabeblack@google.com send("OK"); 72612854Sgabeblack@google.com 72712854Sgabeblack@google.com continue; 72812854Sgabeblack@google.com#endif 72912854Sgabeblack@google.com 73012854Sgabeblack@google.com case GDBMemR: 73112854Sgabeblack@google.com val = hex2i(&p); 73212854Sgabeblack@google.com if (*p++ != ',') { 73312854Sgabeblack@google.com send("E02"); 73412854Sgabeblack@google.com continue; 73512854Sgabeblack@google.com } 73612854Sgabeblack@google.com len = hex2i(&p); 73712854Sgabeblack@google.com if (*p != '\0') { 73812854Sgabeblack@google.com send("E03"); 73912854Sgabeblack@google.com continue; 74012854Sgabeblack@google.com } 74112854Sgabeblack@google.com if (len > bufferSize) { 74212854Sgabeblack@google.com send("E04"); 74312854Sgabeblack@google.com continue; 74412854Sgabeblack@google.com } 74512854Sgabeblack@google.com if (!acc(val, len)) { 74612854Sgabeblack@google.com send("E05"); 74712854Sgabeblack@google.com continue; 74812854Sgabeblack@google.com } 74912854Sgabeblack@google.com 75012854Sgabeblack@google.com if (read(val, (size_t)len, (char *)buffer)) { 75112854Sgabeblack@google.com // variable length array would be nice, but C++ doesn't 75212854Sgabeblack@google.com // officially support those... 75312854Sgabeblack@google.com char *temp = new char[2*len+1]; 75412854Sgabeblack@google.com mem2hex(temp, buffer, len); 75512854Sgabeblack@google.com send(temp); 75612854Sgabeblack@google.com delete [] temp; 75712854Sgabeblack@google.com } else { 75812854Sgabeblack@google.com send("E05"); 75912854Sgabeblack@google.com } 76012854Sgabeblack@google.com continue; 76112854Sgabeblack@google.com 76212854Sgabeblack@google.com case GDBMemW: 76312854Sgabeblack@google.com val = hex2i(&p); 76412854Sgabeblack@google.com if (*p++ != ',') { 76512854Sgabeblack@google.com send("E06"); 76612854Sgabeblack@google.com continue; 76712854Sgabeblack@google.com } 76812854Sgabeblack@google.com len = hex2i(&p); 76912854Sgabeblack@google.com if (*p++ != ':') { 77012854Sgabeblack@google.com send("E07"); 77112854Sgabeblack@google.com continue; 77212854Sgabeblack@google.com } 77312854Sgabeblack@google.com if (len > datalen - (p - data)) { 77412854Sgabeblack@google.com send("E08"); 77512854Sgabeblack@google.com continue; 77612854Sgabeblack@google.com } 77712854Sgabeblack@google.com p = hex2mem(buffer, p, bufferSize); 77812854Sgabeblack@google.com if (p == NULL) { 77912854Sgabeblack@google.com send("E09"); 78012854Sgabeblack@google.com continue; 78112854Sgabeblack@google.com } 78212854Sgabeblack@google.com if (!acc(val, len)) { 78312854Sgabeblack@google.com send("E0A"); 78412854Sgabeblack@google.com continue; 78512854Sgabeblack@google.com } 78612854Sgabeblack@google.com if (write(val, (size_t)len, (char *)buffer)) 78712854Sgabeblack@google.com send("OK"); 78812854Sgabeblack@google.com else 78912854Sgabeblack@google.com send("E0B"); 79012854Sgabeblack@google.com continue; 79112854Sgabeblack@google.com 79212854Sgabeblack@google.com case GDBSetThread: 79312854Sgabeblack@google.com subcmd = *p++; 79412854Sgabeblack@google.com val = hex2i(&p); 79512854Sgabeblack@google.com if (val == 0) 79612854Sgabeblack@google.com send("OK"); 79712854Sgabeblack@google.com else 79812854Sgabeblack@google.com send("E01"); 79912854Sgabeblack@google.com continue; 80012854Sgabeblack@google.com 80112854Sgabeblack@google.com case GDBDetach: 80212854Sgabeblack@google.com case GDBKill: 80312854Sgabeblack@google.com active = false; 80412854Sgabeblack@google.com clearSingleStep(); 80512854Sgabeblack@google.com detach(); 80612854Sgabeblack@google.com goto out; 80712854Sgabeblack@google.com 80812854Sgabeblack@google.com case GDBAsyncCont: 80912854Sgabeblack@google.com subcmd = hex2i(&p); 81012854Sgabeblack@google.com if (*p++ == ';') { 81112854Sgabeblack@google.com val = hex2i(&p); 81212854Sgabeblack@google.com context->pcState(val); 81312854Sgabeblack@google.com } 81412854Sgabeblack@google.com clearSingleStep(); 81512854Sgabeblack@google.com goto out; 81612854Sgabeblack@google.com 81712854Sgabeblack@google.com case GDBCont: 81812854Sgabeblack@google.com if (p - data < (ptrdiff_t)datalen) { 81912854Sgabeblack@google.com val = hex2i(&p); 82012854Sgabeblack@google.com context->pcState(val); 82112854Sgabeblack@google.com } 82212854Sgabeblack@google.com clearSingleStep(); 82312854Sgabeblack@google.com goto out; 82412854Sgabeblack@google.com 82512854Sgabeblack@google.com case GDBAsyncStep: 82612854Sgabeblack@google.com subcmd = hex2i(&p); 82712854Sgabeblack@google.com if (*p++ == ';') { 82812854Sgabeblack@google.com val = hex2i(&p); 82912854Sgabeblack@google.com context->pcState(val); 83012854Sgabeblack@google.com } 83112854Sgabeblack@google.com setSingleStep(); 83212854Sgabeblack@google.com goto out; 83312854Sgabeblack@google.com 83412854Sgabeblack@google.com case GDBStep: 83512854Sgabeblack@google.com if (p - data < (ptrdiff_t)datalen) { 83612854Sgabeblack@google.com val = hex2i(&p); 83712854Sgabeblack@google.com context->pcState(val); 83812854Sgabeblack@google.com } 83912854Sgabeblack@google.com setSingleStep(); 84012854Sgabeblack@google.com goto out; 84112854Sgabeblack@google.com 84212854Sgabeblack@google.com case GDBClrHwBkpt: 84312854Sgabeblack@google.com subcmd = *p++; 84412854Sgabeblack@google.com if (*p++ != ',') send("E0D"); 84512854Sgabeblack@google.com val = hex2i(&p); 84612854Sgabeblack@google.com if (*p++ != ',') send("E0D"); 84712854Sgabeblack@google.com len = hex2i(&p); 84812854Sgabeblack@google.com 84912854Sgabeblack@google.com DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n", 85012854Sgabeblack@google.com break_type(subcmd), val, len); 85112854Sgabeblack@google.com 85212854Sgabeblack@google.com ret = false; 85312854Sgabeblack@google.com 85412854Sgabeblack@google.com switch (subcmd) { 85512854Sgabeblack@google.com case '0': // software breakpoint 85612854Sgabeblack@google.com ret = removeSoftBreak(val, len); 85712854Sgabeblack@google.com break; 85812854Sgabeblack@google.com 85912854Sgabeblack@google.com case '1': // hardware breakpoint 86012854Sgabeblack@google.com ret = removeHardBreak(val, len); 86112854Sgabeblack@google.com break; 86212854Sgabeblack@google.com 86312854Sgabeblack@google.com case '2': // write watchpoint 86412854Sgabeblack@google.com case '3': // read watchpoint 86512854Sgabeblack@google.com case '4': // access watchpoint 86612854Sgabeblack@google.com default: // unknown 86712854Sgabeblack@google.com send(""); 86812854Sgabeblack@google.com break; 86912854Sgabeblack@google.com } 87012854Sgabeblack@google.com 87112854Sgabeblack@google.com send(ret ? "OK" : "E0C"); 87212854Sgabeblack@google.com continue; 87312854Sgabeblack@google.com 87412854Sgabeblack@google.com case GDBSetHwBkpt: 87512854Sgabeblack@google.com subcmd = *p++; 87612854Sgabeblack@google.com if (*p++ != ',') send("E0D"); 87712854Sgabeblack@google.com val = hex2i(&p); 87812854Sgabeblack@google.com if (*p++ != ',') send("E0D"); 87912854Sgabeblack@google.com len = hex2i(&p); 88012854Sgabeblack@google.com 88112854Sgabeblack@google.com DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n", 88212854Sgabeblack@google.com break_type(subcmd), val, len); 88312854Sgabeblack@google.com 88412854Sgabeblack@google.com ret = false; 88512854Sgabeblack@google.com 88612854Sgabeblack@google.com switch (subcmd) { 88712854Sgabeblack@google.com case '0': // software breakpoint 88812854Sgabeblack@google.com ret = insertSoftBreak(val, len); 88912854Sgabeblack@google.com break; 89012854Sgabeblack@google.com 89112854Sgabeblack@google.com case '1': // hardware breakpoint 89212854Sgabeblack@google.com ret = insertHardBreak(val, len); 89312854Sgabeblack@google.com break; 89412854Sgabeblack@google.com 89512854Sgabeblack@google.com case '2': // write watchpoint 89612854Sgabeblack@google.com case '3': // read watchpoint 89712854Sgabeblack@google.com case '4': // access watchpoint 89812854Sgabeblack@google.com default: // unknown 89912854Sgabeblack@google.com send(""); 90012854Sgabeblack@google.com break; 90112854Sgabeblack@google.com } 90212854Sgabeblack@google.com 90312854Sgabeblack@google.com send(ret ? "OK" : "E0C"); 90412854Sgabeblack@google.com continue; 90512854Sgabeblack@google.com 90612854Sgabeblack@google.com case GDBQueryVar: 90712854Sgabeblack@google.com var = string(p, datalen - 1); 90812854Sgabeblack@google.com if (var == "C") 90912854Sgabeblack@google.com send("QC0"); 91012854Sgabeblack@google.com else 91112854Sgabeblack@google.com send(""); 91212854Sgabeblack@google.com continue; 91312854Sgabeblack@google.com 91412854Sgabeblack@google.com case GDBSetBaud: 91512854Sgabeblack@google.com case GDBSetBreak: 91612854Sgabeblack@google.com case GDBDebug: 91712854Sgabeblack@google.com case GDBCycleStep: 91812854Sgabeblack@google.com case GDBSigCycleStep: 91912854Sgabeblack@google.com case GDBReadReg: 92012854Sgabeblack@google.com case GDBSetVar: 92112854Sgabeblack@google.com case GDBReset: 92212854Sgabeblack@google.com case GDBThreadAlive: 92312854Sgabeblack@google.com case GDBTargetExit: 92412854Sgabeblack@google.com case GDBBinaryDload: 92512854Sgabeblack@google.com // Unsupported command 92612854Sgabeblack@google.com DPRINTF(GDBMisc, "Unsupported command: %s\n", 92712854Sgabeblack@google.com gdb_command(command)); 92812854Sgabeblack@google.com DDUMP(GDBMisc, (uint8_t *)data, datalen); 92912854Sgabeblack@google.com send(""); 93012854Sgabeblack@google.com continue; 93112854Sgabeblack@google.com 93212854Sgabeblack@google.com default: 93312854Sgabeblack@google.com // Unknown command. 93412854Sgabeblack@google.com DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n", 93512854Sgabeblack@google.com command, command); 93612854Sgabeblack@google.com send(""); 93712854Sgabeblack@google.com continue; 93812854Sgabeblack@google.com 93912854Sgabeblack@google.com 94012854Sgabeblack@google.com } 94112854Sgabeblack@google.com } 94212854Sgabeblack@google.com 94312854Sgabeblack@google.com out: 94412854Sgabeblack@google.com free(buffer); 94512854Sgabeblack@google.com return true; 94612854Sgabeblack@google.com} 94712854Sgabeblack@google.com 94812854Sgabeblack@google.com// Convert a hex digit into an integer. 94912854Sgabeblack@google.com// This returns -1 if the argument passed is no valid hex digit. 95012854Sgabeblack@google.comint 95112854Sgabeblack@google.comBaseRemoteGDB::digit2i(char c) 95212854Sgabeblack@google.com{ 95312854Sgabeblack@google.com if (c >= '0' && c <= '9') 95412854Sgabeblack@google.com return (c - '0'); 95512854Sgabeblack@google.com else if (c >= 'a' && c <= 'f') 95612854Sgabeblack@google.com return (c - 'a' + 10); 95712854Sgabeblack@google.com else if (c >= 'A' && c <= 'F') 95812854Sgabeblack@google.com 95912854Sgabeblack@google.com return (c - 'A' + 10); 96012854Sgabeblack@google.com else 96112854Sgabeblack@google.com return (-1); 96212854Sgabeblack@google.com} 96312854Sgabeblack@google.com 96412854Sgabeblack@google.com// Convert the low 4 bits of an integer into an hex digit. 96512854Sgabeblack@google.comchar 96612854Sgabeblack@google.comBaseRemoteGDB::i2digit(int n) 96712854Sgabeblack@google.com{ 96812854Sgabeblack@google.com return ("0123456789abcdef"[n & 0x0f]); 96912854Sgabeblack@google.com} 97012854Sgabeblack@google.com 97112854Sgabeblack@google.com// Convert a byte array into an hex string. 97212854Sgabeblack@google.comvoid 97312854Sgabeblack@google.comBaseRemoteGDB::mem2hex(void *vdst, const void *vsrc, int len) 97412854Sgabeblack@google.com{ 97512854Sgabeblack@google.com char *dst = (char *)vdst; 97612854Sgabeblack@google.com const char *src = (const char *)vsrc; 97712854Sgabeblack@google.com 97812854Sgabeblack@google.com while (len--) { 97912854Sgabeblack@google.com *dst++ = i2digit(*src >> 4); 98012854Sgabeblack@google.com *dst++ = i2digit(*src++); 98112854Sgabeblack@google.com } 98212854Sgabeblack@google.com *dst = '\0'; 98312854Sgabeblack@google.com} 98412854Sgabeblack@google.com 98512854Sgabeblack@google.com// Convert an hex string into a byte array. 98612854Sgabeblack@google.com// This returns a pointer to the character following the last valid 98712854Sgabeblack@google.com// hex digit. If the string ends in the middle of a byte, NULL is 98812854Sgabeblack@google.com// returned. 98912854Sgabeblack@google.comconst char * 99012854Sgabeblack@google.comBaseRemoteGDB::hex2mem(void *vdst, const char *src, int maxlen) 99112854Sgabeblack@google.com{ 99212854Sgabeblack@google.com char *dst = (char *)vdst; 99312854Sgabeblack@google.com int msb, lsb; 99412854Sgabeblack@google.com 99512854Sgabeblack@google.com while (*src && maxlen--) { 99612854Sgabeblack@google.com msb = digit2i(*src++); 99712854Sgabeblack@google.com if (msb < 0) 99812854Sgabeblack@google.com return (src - 1); 99912854Sgabeblack@google.com lsb = digit2i(*src++); 100012854Sgabeblack@google.com if (lsb < 0) 100112854Sgabeblack@google.com return (NULL); 100212854Sgabeblack@google.com *dst++ = (msb << 4) | lsb; 100312854Sgabeblack@google.com } 100412854Sgabeblack@google.com return (src); 100512854Sgabeblack@google.com} 100612854Sgabeblack@google.com 100712854Sgabeblack@google.com// Convert an hex string into an integer. 100812854Sgabeblack@google.com// This returns a pointer to the character following the last valid 100912854Sgabeblack@google.com// hex digit. 101012854Sgabeblack@google.comAddr 101112854Sgabeblack@google.comBaseRemoteGDB::hex2i(const char **srcp) 101212854Sgabeblack@google.com{ 101312854Sgabeblack@google.com const char *src = *srcp; 101412854Sgabeblack@google.com Addr r = 0; 101512854Sgabeblack@google.com int nibble; 101612854Sgabeblack@google.com 101712854Sgabeblack@google.com while ((nibble = digit2i(*src)) >= 0) { 101812854Sgabeblack@google.com r *= 16; 101912854Sgabeblack@google.com r += nibble; 102012854Sgabeblack@google.com src++; 102112854Sgabeblack@google.com } 102212854Sgabeblack@google.com *srcp = src; 102312854Sgabeblack@google.com return (r); 102412854Sgabeblack@google.com} 102512854Sgabeblack@google.com 102612854Sgabeblack@google.com