remote_gdb.cc revision 8706
113531Sjairo.balart@metempsy.com/* 214227Sgiacomo.travaglini@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 314227Sgiacomo.travaglini@arm.com * All rights reserved. 414227Sgiacomo.travaglini@arm.com * 514227Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without 614227Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions are 714227Sgiacomo.travaglini@arm.com * met: redistributions of source code must retain the above copyright 814227Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer; 914227Sgiacomo.travaglini@arm.com * redistributions in binary form must reproduce the above copyright 1014227Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer in the 1114227Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution; 1214227Sgiacomo.travaglini@arm.com * neither the name of the copyright holders nor the names of its 1314227Sgiacomo.travaglini@arm.com * contributors may be used to endorse or promote products derived from 1413531Sjairo.balart@metempsy.com * this software without specific prior written permission. 1513531Sjairo.balart@metempsy.com * 1613531Sjairo.balart@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1713531Sjairo.balart@metempsy.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1813531Sjairo.balart@metempsy.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1913531Sjairo.balart@metempsy.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2013531Sjairo.balart@metempsy.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2113531Sjairo.balart@metempsy.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2213531Sjairo.balart@metempsy.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2313531Sjairo.balart@metempsy.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2413531Sjairo.balart@metempsy.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2513531Sjairo.balart@metempsy.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2613531Sjairo.balart@metempsy.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2713531Sjairo.balart@metempsy.com * 2813531Sjairo.balart@metempsy.com * Authors: Nathan Binkert 2913531Sjairo.balart@metempsy.com */ 3013531Sjairo.balart@metempsy.com 3113531Sjairo.balart@metempsy.com/* 3213531Sjairo.balart@metempsy.com * Copyright (c) 1990, 1993 The Regents of the University of California 3313531Sjairo.balart@metempsy.com * All rights reserved 3413531Sjairo.balart@metempsy.com * 3513531Sjairo.balart@metempsy.com * This software was developed by the Computer Systems Engineering group 3613531Sjairo.balart@metempsy.com * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 3713531Sjairo.balart@metempsy.com * contributed to Berkeley. 3813531Sjairo.balart@metempsy.com * 3913531Sjairo.balart@metempsy.com * All advertising materials mentioning features or use of this software 4013531Sjairo.balart@metempsy.com * must display the following acknowledgement: 4113531Sjairo.balart@metempsy.com * This product includes software developed by the University of 4213531Sjairo.balart@metempsy.com * California, Lawrence Berkeley Laboratories. 4313531Sjairo.balart@metempsy.com * 4413531Sjairo.balart@metempsy.com * Redistribution and use in source and binary forms, with or without 4513531Sjairo.balart@metempsy.com * modification, are permitted provided that the following conditions 4613531Sjairo.balart@metempsy.com * are met: 4713531Sjairo.balart@metempsy.com * 1. Redistributions of source code must retain the above copyright 4813531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer. 4913531Sjairo.balart@metempsy.com * 2. Redistributions in binary form must reproduce the above copyright 5013531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer in the 5113926Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution. 5213926Sgiacomo.travaglini@arm.com * 3. All advertising materials mentioning features or use of this software 5313926Sgiacomo.travaglini@arm.com * must display the following acknowledgement: 5413531Sjairo.balart@metempsy.com * This product includes software developed by the University of 5513531Sjairo.balart@metempsy.com * California, Berkeley and its contributors. 5613531Sjairo.balart@metempsy.com * 4. Neither the name of the University nor the names of its contributors 5713531Sjairo.balart@metempsy.com * may be used to endorse or promote products derived from this software 5813531Sjairo.balart@metempsy.com * without specific prior written permission. 5913531Sjairo.balart@metempsy.com * 6013531Sjairo.balart@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 6114258Sgiacomo.travaglini@arm.com * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6214258Sgiacomo.travaglini@arm.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6313531Sjairo.balart@metempsy.com * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 6413531Sjairo.balart@metempsy.com * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6513531Sjairo.balart@metempsy.com * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 6613531Sjairo.balart@metempsy.com * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6713531Sjairo.balart@metempsy.com * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6813531Sjairo.balart@metempsy.com * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6913531Sjairo.balart@metempsy.com * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 7013531Sjairo.balart@metempsy.com * SUCH DAMAGE. 7113531Sjairo.balart@metempsy.com * 7213531Sjairo.balart@metempsy.com * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 7314259Sgiacomo.travaglini@arm.com */ 7414259Sgiacomo.travaglini@arm.com 7514259Sgiacomo.travaglini@arm.com/*- 7614259Sgiacomo.travaglini@arm.com * Copyright (c) 2001 The NetBSD Foundation, Inc. 7714259Sgiacomo.travaglini@arm.com * All rights reserved. 7814259Sgiacomo.travaglini@arm.com * 7914259Sgiacomo.travaglini@arm.com * This code is derived from software contributed to The NetBSD Foundation 8013826Sgiacomo.travaglini@arm.com * by Jason R. Thorpe. 8113826Sgiacomo.travaglini@arm.com * 8213826Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without 8313826Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions 8413826Sgiacomo.travaglini@arm.com * are met: 8513531Sjairo.balart@metempsy.com * 1. Redistributions of source code must retain the above copyright 8613760Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer. 8713531Sjairo.balart@metempsy.com * 2. Redistributions in binary form must reproduce the above copyright 8813531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer in the 8913531Sjairo.balart@metempsy.com * documentation and/or other materials provided with the distribution. 9013531Sjairo.balart@metempsy.com * 3. All advertising materials mentioning features or use of this software 9113531Sjairo.balart@metempsy.com * must display the following acknowledgement: 9213531Sjairo.balart@metempsy.com * This product includes software developed by the NetBSD 9313531Sjairo.balart@metempsy.com * Foundation, Inc. and its contributors. 9413531Sjairo.balart@metempsy.com * 4. Neither the name of The NetBSD Foundation nor the names of its 9513531Sjairo.balart@metempsy.com * contributors may be used to endorse or promote products derived 9613531Sjairo.balart@metempsy.com * from this software without specific prior written permission. 9713531Sjairo.balart@metempsy.com * 9813531Sjairo.balart@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 9913531Sjairo.balart@metempsy.com * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 10013760Sjairo.balart@metempsy.com * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 10113531Sjairo.balart@metempsy.com * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 10213531Sjairo.balart@metempsy.com * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 10313531Sjairo.balart@metempsy.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 10413531Sjairo.balart@metempsy.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 10513531Sjairo.balart@metempsy.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 10613531Sjairo.balart@metempsy.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10713531Sjairo.balart@metempsy.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 10813531Sjairo.balart@metempsy.com * POSSIBILITY OF SUCH DAMAGE. 10913531Sjairo.balart@metempsy.com */ 11013531Sjairo.balart@metempsy.com 11113531Sjairo.balart@metempsy.com/* 11213531Sjairo.balart@metempsy.com * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ 11313580Sgabeblack@google.com * 11413531Sjairo.balart@metempsy.com * Taken from NetBSD 11513531Sjairo.balart@metempsy.com * 11613580Sgabeblack@google.com * "Stub" to allow remote cpu to debug over a serial line using gdb. 11713531Sjairo.balart@metempsy.com */ 11813531Sjairo.balart@metempsy.com 11913531Sjairo.balart@metempsy.com#include <sys/signal.h> 12013531Sjairo.balart@metempsy.com#include <unistd.h> 12113760Sjairo.balart@metempsy.com 12213531Sjairo.balart@metempsy.com#include <cstdio> 12313531Sjairo.balart@metempsy.com#include <string> 12413531Sjairo.balart@metempsy.com 12513531Sjairo.balart@metempsy.com#include "config/full_system.hh" 12613531Sjairo.balart@metempsy.com 12713531Sjairo.balart@metempsy.com#if FULL_SYSTEM 12814246Sgiacomo.travaglini@arm.com#include "arch/vtophys.hh" 12913531Sjairo.balart@metempsy.com#include "mem/fs_translating_port_proxy.hh" 13013531Sjairo.balart@metempsy.com#endif 13113531Sjairo.balart@metempsy.com 13213531Sjairo.balart@metempsy.com#include "base/intmath.hh" 13313531Sjairo.balart@metempsy.com#include "base/remote_gdb.hh" 13413531Sjairo.balart@metempsy.com#include "base/socket.hh" 13513531Sjairo.balart@metempsy.com#include "base/trace.hh" 13613531Sjairo.balart@metempsy.com#include "config/the_isa.hh" 13713531Sjairo.balart@metempsy.com#include "cpu/static_inst.hh" 13813531Sjairo.balart@metempsy.com#include "cpu/thread_context.hh" 13913531Sjairo.balart@metempsy.com#include "debug/GDBAll.hh" 14013531Sjairo.balart@metempsy.com#include "mem/port.hh" 14113531Sjairo.balart@metempsy.com#include "mem/se_translating_port_proxy.hh" 14213531Sjairo.balart@metempsy.com#include "sim/system.hh" 14313531Sjairo.balart@metempsy.com 14413760Sjairo.balart@metempsy.comusing namespace std; 14513531Sjairo.balart@metempsy.comusing namespace Debug; 14613531Sjairo.balart@metempsy.comusing namespace TheISA; 14713531Sjairo.balart@metempsy.com 14813531Sjairo.balart@metempsy.com#ifndef NDEBUG 14913531Sjairo.balart@metempsy.comvector<BaseRemoteGDB *> debuggers; 15013531Sjairo.balart@metempsy.com 15113531Sjairo.balart@metempsy.comvoid 15213531Sjairo.balart@metempsy.comdebugger() 15313531Sjairo.balart@metempsy.com{ 15413531Sjairo.balart@metempsy.com static int current_debugger = -1; 15513531Sjairo.balart@metempsy.com if (current_debugger >= 0 && current_debugger < (int)debuggers.size()) { 15613531Sjairo.balart@metempsy.com BaseRemoteGDB *gdb = debuggers[current_debugger]; 15713531Sjairo.balart@metempsy.com if (!gdb->isattached()) 15813531Sjairo.balart@metempsy.com gdb->listener->accept(); 15913531Sjairo.balart@metempsy.com if (gdb->isattached()) 16013531Sjairo.balart@metempsy.com gdb->trap(SIGILL); 16113531Sjairo.balart@metempsy.com } 16213531Sjairo.balart@metempsy.com} 16313531Sjairo.balart@metempsy.com#endif 16413531Sjairo.balart@metempsy.com 16513531Sjairo.balart@metempsy.com/////////////////////////////////////////////////////////// 16613531Sjairo.balart@metempsy.com// 16713760Sjairo.balart@metempsy.com// 16813531Sjairo.balart@metempsy.com// 16913531Sjairo.balart@metempsy.com 17013531Sjairo.balart@metempsy.comGDBListener::Event::Event(GDBListener *l, int fd, int e) 17114057Sgiacomo.travaglini@arm.com : PollEvent(fd, e), listener(l) 17213531Sjairo.balart@metempsy.com{} 17313531Sjairo.balart@metempsy.com 17413531Sjairo.balart@metempsy.comvoid 17513531Sjairo.balart@metempsy.comGDBListener::Event::process(int revent) 17613531Sjairo.balart@metempsy.com{ 17714057Sgiacomo.travaglini@arm.com listener->accept(); 17814057Sgiacomo.travaglini@arm.com} 17914057Sgiacomo.travaglini@arm.com 18014057Sgiacomo.travaglini@arm.comGDBListener::GDBListener(BaseRemoteGDB *g, int p) 18114057Sgiacomo.travaglini@arm.com : event(NULL), gdb(g), port(p) 18214057Sgiacomo.travaglini@arm.com{ 18314057Sgiacomo.travaglini@arm.com assert(!gdb->listener); 18413760Sjairo.balart@metempsy.com gdb->listener = this; 18513531Sjairo.balart@metempsy.com} 18613531Sjairo.balart@metempsy.com 18713531Sjairo.balart@metempsy.comGDBListener::~GDBListener() 18814057Sgiacomo.travaglini@arm.com{ 18913531Sjairo.balart@metempsy.com if (event) 19013531Sjairo.balart@metempsy.com delete event; 19114247Sgiacomo.travaglini@arm.com} 19213531Sjairo.balart@metempsy.com 19313531Sjairo.balart@metempsy.comstring 19413531Sjairo.balart@metempsy.comGDBListener::name() 19514057Sgiacomo.travaglini@arm.com{ 19614057Sgiacomo.travaglini@arm.com return gdb->name() + ".listener"; 19714057Sgiacomo.travaglini@arm.com} 19814057Sgiacomo.travaglini@arm.com 19914057Sgiacomo.travaglini@arm.comvoid 20014057Sgiacomo.travaglini@arm.comGDBListener::listen() 20114057Sgiacomo.travaglini@arm.com{ 20213760Sjairo.balart@metempsy.com if (ListenSocket::allDisabled()) { 20313760Sjairo.balart@metempsy.com warn_once("Sockets disabled, not accepting gdb connections"); 20414254Sgiacomo.travaglini@arm.com return; 20514254Sgiacomo.travaglini@arm.com } 20614254Sgiacomo.travaglini@arm.com 20714254Sgiacomo.travaglini@arm.com while (!listener.listen(port, true)) { 20814254Sgiacomo.travaglini@arm.com DPRINTF(GDBMisc, "Can't bind port %d\n", port); 20914254Sgiacomo.travaglini@arm.com port++; 21014254Sgiacomo.travaglini@arm.com } 21114254Sgiacomo.travaglini@arm.com 21214254Sgiacomo.travaglini@arm.com event = new Event(this, listener.getfd(), POLLIN); 21313739Sgiacomo.travaglini@arm.com pollQueue.schedule(event); 21414254Sgiacomo.travaglini@arm.com 21513760Sjairo.balart@metempsy.com#ifndef NDEBUG 21613760Sjairo.balart@metempsy.com gdb->number = debuggers.size(); 21713531Sjairo.balart@metempsy.com debuggers.push_back(gdb); 21813531Sjairo.balart@metempsy.com#endif 21913531Sjairo.balart@metempsy.com 22013760Sjairo.balart@metempsy.com#ifndef NDEBUG 22113531Sjairo.balart@metempsy.com ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n", 22213531Sjairo.balart@metempsy.com curTick(), name(), gdb->number, port); 22313531Sjairo.balart@metempsy.com#else 22413531Sjairo.balart@metempsy.com ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n", 22513531Sjairo.balart@metempsy.com curTick(), name(), port); 22613531Sjairo.balart@metempsy.com#endif 22713760Sjairo.balart@metempsy.com} 22813760Sjairo.balart@metempsy.com 22913760Sjairo.balart@metempsy.comvoid 23013531Sjairo.balart@metempsy.comGDBListener::accept() 23113760Sjairo.balart@metempsy.com{ 23213760Sjairo.balart@metempsy.com if (!listener.islistening()) 23313531Sjairo.balart@metempsy.com panic("GDBListener::accept(): cannot accept if we're not listening!"); 23413531Sjairo.balart@metempsy.com 23513760Sjairo.balart@metempsy.com int sfd = listener.accept(true); 23613760Sjairo.balart@metempsy.com 23713760Sjairo.balart@metempsy.com if (sfd != -1) { 23813531Sjairo.balart@metempsy.com if (gdb->isattached()) 23913531Sjairo.balart@metempsy.com close(sfd); 24013531Sjairo.balart@metempsy.com else 24113531Sjairo.balart@metempsy.com gdb->attach(sfd); 24213531Sjairo.balart@metempsy.com } 24313531Sjairo.balart@metempsy.com} 24413531Sjairo.balart@metempsy.com 24513531Sjairo.balart@metempsy.comBaseRemoteGDB::Event::Event(BaseRemoteGDB *g, int fd, int e) 24613760Sjairo.balart@metempsy.com : PollEvent(fd, e), gdb(g) 24713531Sjairo.balart@metempsy.com{} 24813531Sjairo.balart@metempsy.com 24913531Sjairo.balart@metempsy.comvoid 25013531Sjairo.balart@metempsy.comBaseRemoteGDB::Event::process(int revent) 25113531Sjairo.balart@metempsy.com{ 25213760Sjairo.balart@metempsy.com if (revent & POLLIN) 25313531Sjairo.balart@metempsy.com gdb->trap(SIGILL); 25413531Sjairo.balart@metempsy.com else if (revent & POLLNVAL) 25513531Sjairo.balart@metempsy.com gdb->detach(); 25613531Sjairo.balart@metempsy.com} 25713531Sjairo.balart@metempsy.com 25813531Sjairo.balart@metempsy.comBaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, size_t cacheSize) 25913531Sjairo.balart@metempsy.com : event(NULL), listener(NULL), number(-1), fd(-1), 26013531Sjairo.balart@metempsy.com active(false), attached(false), 26113531Sjairo.balart@metempsy.com system(_system), pmem(_system->physmem), context(c), 26213531Sjairo.balart@metempsy.com gdbregs(cacheSize) 26313760Sjairo.balart@metempsy.com{ 26413531Sjairo.balart@metempsy.com memset(gdbregs.regs, 0, gdbregs.bytes()); 26513531Sjairo.balart@metempsy.com} 26613531Sjairo.balart@metempsy.com 26713531Sjairo.balart@metempsy.comBaseRemoteGDB::~BaseRemoteGDB() 26813531Sjairo.balart@metempsy.com{ 26913760Sjairo.balart@metempsy.com if (event) 27013531Sjairo.balart@metempsy.com delete event; 27113531Sjairo.balart@metempsy.com} 27213760Sjairo.balart@metempsy.com 27313531Sjairo.balart@metempsy.comstring 27413531Sjairo.balart@metempsy.comBaseRemoteGDB::name() 27513760Sjairo.balart@metempsy.com{ 27613531Sjairo.balart@metempsy.com return system->name() + ".remote_gdb"; 27713531Sjairo.balart@metempsy.com} 27813531Sjairo.balart@metempsy.com 27913531Sjairo.balart@metempsy.combool 28013531Sjairo.balart@metempsy.comBaseRemoteGDB::isattached() 28113531Sjairo.balart@metempsy.com{ return attached; } 28213760Sjairo.balart@metempsy.com 28313531Sjairo.balart@metempsy.comvoid 28413531Sjairo.balart@metempsy.comBaseRemoteGDB::attach(int f) 28513531Sjairo.balart@metempsy.com{ 28613531Sjairo.balart@metempsy.com fd = f; 28713531Sjairo.balart@metempsy.com 28813531Sjairo.balart@metempsy.com event = new Event(this, fd, POLLIN); 28913531Sjairo.balart@metempsy.com pollQueue.schedule(event); 29013531Sjairo.balart@metempsy.com 29113531Sjairo.balart@metempsy.com attached = true; 29213531Sjairo.balart@metempsy.com DPRINTFN("remote gdb attached\n"); 29313760Sjairo.balart@metempsy.com} 29413531Sjairo.balart@metempsy.com 29513531Sjairo.balart@metempsy.comvoid 29613531Sjairo.balart@metempsy.comBaseRemoteGDB::detach() 29713531Sjairo.balart@metempsy.com{ 29813531Sjairo.balart@metempsy.com attached = false; 29913760Sjairo.balart@metempsy.com close(fd); 30013531Sjairo.balart@metempsy.com fd = -1; 30113531Sjairo.balart@metempsy.com 30213760Sjairo.balart@metempsy.com pollQueue.remove(event); 30313531Sjairo.balart@metempsy.com DPRINTFN("remote gdb detached\n"); 30413531Sjairo.balart@metempsy.com} 30513760Sjairo.balart@metempsy.com 30613531Sjairo.balart@metempsy.comconst char * 30713531Sjairo.balart@metempsy.comBaseRemoteGDB::gdb_command(char cmd) 30813531Sjairo.balart@metempsy.com{ 30913531Sjairo.balart@metempsy.com switch (cmd) { 31013531Sjairo.balart@metempsy.com case GDBSignal: return "KGDB_SIGNAL"; 31113531Sjairo.balart@metempsy.com case GDBSetBaud: return "KGDB_SET_BAUD"; 31213760Sjairo.balart@metempsy.com case GDBSetBreak: return "KGDB_SET_BREAK"; 31313531Sjairo.balart@metempsy.com case GDBCont: return "KGDB_CONT"; 31414237Sgiacomo.travaglini@arm.com case GDBAsyncCont: return "KGDB_ASYNC_CONT"; 31513531Sjairo.balart@metempsy.com case GDBDebug: return "KGDB_DEBUG"; 31613531Sjairo.balart@metempsy.com case GDBDetach: return "KGDB_DETACH"; 31713531Sjairo.balart@metempsy.com case GDBRegR: return "KGDB_REG_R"; 31813531Sjairo.balart@metempsy.com case GDBRegW: return "KGDB_REG_W"; 31914237Sgiacomo.travaglini@arm.com case GDBSetThread: return "KGDB_SET_THREAD"; 32014237Sgiacomo.travaglini@arm.com case GDBCycleStep: return "KGDB_CYCLE_STEP"; 32114237Sgiacomo.travaglini@arm.com case GDBSigCycleStep: return "KGDB_SIG_CYCLE_STEP"; 32213531Sjairo.balart@metempsy.com case GDBKill: return "KGDB_KILL"; 32313760Sjairo.balart@metempsy.com case GDBMemW: return "KGDB_MEM_W"; 32413531Sjairo.balart@metempsy.com case GDBMemR: return "KGDB_MEM_R"; 32513760Sjairo.balart@metempsy.com case GDBSetReg: return "KGDB_SET_REG"; 32614237Sgiacomo.travaglini@arm.com case GDBReadReg: return "KGDB_READ_REG"; 32714237Sgiacomo.travaglini@arm.com case GDBQueryVar: return "KGDB_QUERY_VAR"; 32813760Sjairo.balart@metempsy.com case GDBSetVar: return "KGDB_SET_VAR"; 32913760Sjairo.balart@metempsy.com case GDBReset: return "KGDB_RESET"; 33014237Sgiacomo.travaglini@arm.com case GDBStep: return "KGDB_STEP"; 33114237Sgiacomo.travaglini@arm.com case GDBAsyncStep: return "KGDB_ASYNC_STEP"; 33214237Sgiacomo.travaglini@arm.com case GDBThreadAlive: return "KGDB_THREAD_ALIVE"; 33314237Sgiacomo.travaglini@arm.com case GDBTargetExit: return "KGDB_TARGET_EXIT"; 33414237Sgiacomo.travaglini@arm.com case GDBBinaryDload: return "KGDB_BINARY_DLOAD"; 33514237Sgiacomo.travaglini@arm.com case GDBClrHwBkpt: return "KGDB_CLR_HW_BKPT"; 33614237Sgiacomo.travaglini@arm.com case GDBSetHwBkpt: return "KGDB_SET_HW_BKPT"; 33714237Sgiacomo.travaglini@arm.com case GDBStart: return "KGDB_START"; 33814237Sgiacomo.travaglini@arm.com case GDBEnd: return "KGDB_END"; 33913760Sjairo.balart@metempsy.com case GDBGoodP: return "KGDB_GOODP"; 34013531Sjairo.balart@metempsy.com case GDBBadP: return "KGDB_BADP"; 34114237Sgiacomo.travaglini@arm.com default: return "KGDB_UNKNOWN"; 34214237Sgiacomo.travaglini@arm.com } 34314237Sgiacomo.travaglini@arm.com} 34414237Sgiacomo.travaglini@arm.com 34514237Sgiacomo.travaglini@arm.com///////////////////////// 34614237Sgiacomo.travaglini@arm.com// 34714237Sgiacomo.travaglini@arm.com// 34814237Sgiacomo.travaglini@arm.com 34914237Sgiacomo.travaglini@arm.comuint8_t 35014237Sgiacomo.travaglini@arm.comBaseRemoteGDB::getbyte() 35114237Sgiacomo.travaglini@arm.com{ 35214237Sgiacomo.travaglini@arm.com uint8_t b; 35313531Sjairo.balart@metempsy.com if (::read(fd, &b, 1) != 1) 35413531Sjairo.balart@metempsy.com warn("could not read byte from debugger"); 35513760Sjairo.balart@metempsy.com return b; 35613531Sjairo.balart@metempsy.com} 35713760Sjairo.balart@metempsy.com 35813760Sjairo.balart@metempsy.comvoid 35914057Sgiacomo.travaglini@arm.comBaseRemoteGDB::putbyte(uint8_t b) 36013531Sjairo.balart@metempsy.com{ 36113531Sjairo.balart@metempsy.com if (::write(fd, &b, 1) != 1) 36213531Sjairo.balart@metempsy.com warn("could not write byte to debugger"); 36313760Sjairo.balart@metempsy.com} 36413760Sjairo.balart@metempsy.com 36513760Sjairo.balart@metempsy.com// Send a packet to gdb 36613531Sjairo.balart@metempsy.comvoid 36713760Sjairo.balart@metempsy.comBaseRemoteGDB::send(const char *bp) 36813760Sjairo.balart@metempsy.com{ 36913531Sjairo.balart@metempsy.com const char *p; 37013531Sjairo.balart@metempsy.com uint8_t csum, c; 37113760Sjairo.balart@metempsy.com 37213760Sjairo.balart@metempsy.com DPRINTF(GDBSend, "send: %s\n", bp); 37313760Sjairo.balart@metempsy.com 37413531Sjairo.balart@metempsy.com do { 37513531Sjairo.balart@metempsy.com p = bp; 37613531Sjairo.balart@metempsy.com //Start sending a packet 37713531Sjairo.balart@metempsy.com putbyte(GDBStart); 37813531Sjairo.balart@metempsy.com //Send the contents, and also keep a check sum. 37913531Sjairo.balart@metempsy.com for (csum = 0; (c = *p); p++) { 38014057Sgiacomo.travaglini@arm.com putbyte(c); 38114057Sgiacomo.travaglini@arm.com csum += c; 38214057Sgiacomo.travaglini@arm.com } 38314057Sgiacomo.travaglini@arm.com //Send the ending character. 38414057Sgiacomo.travaglini@arm.com putbyte(GDBEnd); 38514057Sgiacomo.travaglini@arm.com //Sent the checksum. 38614057Sgiacomo.travaglini@arm.com putbyte(i2digit(csum >> 4)); 38714057Sgiacomo.travaglini@arm.com putbyte(i2digit(csum)); 38813760Sjairo.balart@metempsy.com //Try transmitting over and over again until the other end doesn't send an 38913531Sjairo.balart@metempsy.com //error back. 39013760Sjairo.balart@metempsy.com } while ((c = getbyte() & 0x7f) == GDBBadP); 39113531Sjairo.balart@metempsy.com} 39213531Sjairo.balart@metempsy.com 39313531Sjairo.balart@metempsy.com// Receive a packet from gdb 39413531Sjairo.balart@metempsy.comint 39513531Sjairo.balart@metempsy.comBaseRemoteGDB::recv(char *bp, int maxlen) 39613531Sjairo.balart@metempsy.com{ 39713531Sjairo.balart@metempsy.com char *p; 39813531Sjairo.balart@metempsy.com int c, csum; 39913531Sjairo.balart@metempsy.com int len; 40013531Sjairo.balart@metempsy.com 40113923Sgiacomo.travaglini@arm.com do { 40213923Sgiacomo.travaglini@arm.com p = bp; 40313531Sjairo.balart@metempsy.com csum = len = 0; 40413531Sjairo.balart@metempsy.com //Find the beginning of a packet 40513531Sjairo.balart@metempsy.com while ((c = getbyte()) != GDBStart) 40613531Sjairo.balart@metempsy.com ; 40713531Sjairo.balart@metempsy.com 40813531Sjairo.balart@metempsy.com //Read until you find the end of the data in the packet, and keep 40913531Sjairo.balart@metempsy.com //track of the check sum. 41013531Sjairo.balart@metempsy.com while ((c = getbyte()) != GDBEnd && len < maxlen) { 41113531Sjairo.balart@metempsy.com c &= 0x7f; 41213531Sjairo.balart@metempsy.com csum += c; 41313760Sjairo.balart@metempsy.com *p++ = c; 41413531Sjairo.balart@metempsy.com len++; 41513531Sjairo.balart@metempsy.com } 41613531Sjairo.balart@metempsy.com 41713531Sjairo.balart@metempsy.com //Mask the check sum, and terminate the command string. 41813531Sjairo.balart@metempsy.com csum &= 0xff; 41913760Sjairo.balart@metempsy.com *p = '\0'; 42013531Sjairo.balart@metempsy.com 42113531Sjairo.balart@metempsy.com //If the command was too long, report an error. 42213760Sjairo.balart@metempsy.com if (len >= maxlen) { 42313760Sjairo.balart@metempsy.com putbyte(GDBBadP); 42413531Sjairo.balart@metempsy.com continue; 42513531Sjairo.balart@metempsy.com } 42613760Sjairo.balart@metempsy.com 42713531Sjairo.balart@metempsy.com //Bring in the checksum. If the check sum matches, csum will be 0. 42813531Sjairo.balart@metempsy.com csum -= digit2i(getbyte()) * 16; 42913531Sjairo.balart@metempsy.com csum -= digit2i(getbyte()); 43013531Sjairo.balart@metempsy.com 43113531Sjairo.balart@metempsy.com //If the check sum was correct 43213760Sjairo.balart@metempsy.com if (csum == 0) { 43313531Sjairo.balart@metempsy.com //Report that the packet was received correctly 43413760Sjairo.balart@metempsy.com putbyte(GDBGoodP); 43513531Sjairo.balart@metempsy.com // Sequence present? 43613531Sjairo.balart@metempsy.com if (bp[2] == ':') { 43713531Sjairo.balart@metempsy.com putbyte(bp[0]); 43813531Sjairo.balart@metempsy.com putbyte(bp[1]); 43913531Sjairo.balart@metempsy.com len -= 3; 44013531Sjairo.balart@metempsy.com memcpy(bp, bp+3, len); 44113531Sjairo.balart@metempsy.com } 44213531Sjairo.balart@metempsy.com break; 44313531Sjairo.balart@metempsy.com } 44413760Sjairo.balart@metempsy.com //Otherwise, report that there was a mistake. 44513531Sjairo.balart@metempsy.com putbyte(GDBBadP); 44613760Sjairo.balart@metempsy.com } while (1); 44713531Sjairo.balart@metempsy.com 44813531Sjairo.balart@metempsy.com DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp); 44913531Sjairo.balart@metempsy.com 45013531Sjairo.balart@metempsy.com return (len); 45113531Sjairo.balart@metempsy.com} 45213531Sjairo.balart@metempsy.com 45313531Sjairo.balart@metempsy.com// Read bytes from kernel address space for debugger. 45413531Sjairo.balart@metempsy.combool 45513531Sjairo.balart@metempsy.comBaseRemoteGDB::read(Addr vaddr, size_t size, char *data) 45613531Sjairo.balart@metempsy.com{ 45713923Sgiacomo.travaglini@arm.com static Addr lastaddr = 0; 45813923Sgiacomo.travaglini@arm.com static size_t lastsize = 0; 45913531Sjairo.balart@metempsy.com 46013531Sjairo.balart@metempsy.com if (vaddr < 10) { 46113531Sjairo.balart@metempsy.com DPRINTF(GDBRead, "read: reading memory location zero!\n"); 46213531Sjairo.balart@metempsy.com vaddr = lastaddr + lastsize; 46313531Sjairo.balart@metempsy.com } 46413531Sjairo.balart@metempsy.com 46513531Sjairo.balart@metempsy.com DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size); 46613531Sjairo.balart@metempsy.com 46713531Sjairo.balart@metempsy.com#if FULL_SYSTEM 46813531Sjairo.balart@metempsy.com FSTranslatingPortProxy *port = context->getVirtProxy(); 46913760Sjairo.balart@metempsy.com#else 47013531Sjairo.balart@metempsy.com SETranslatingPortProxy *port = context->getMemProxy(); 47113531Sjairo.balart@metempsy.com#endif 47213531Sjairo.balart@metempsy.com port->readBlob(vaddr, (uint8_t*)data, size); 47313531Sjairo.balart@metempsy.com 47413531Sjairo.balart@metempsy.com#if TRACING_ON 47513760Sjairo.balart@metempsy.com if (DTRACE(GDBRead)) { 47613531Sjairo.balart@metempsy.com if (DTRACE(GDBExtra)) { 47713531Sjairo.balart@metempsy.com char buf[1024]; 47813760Sjairo.balart@metempsy.com mem2hex(buf, data, size); 47913760Sjairo.balart@metempsy.com DPRINTFNR(": %s\n", buf); 48013531Sjairo.balart@metempsy.com } else 48113531Sjairo.balart@metempsy.com DPRINTFNR("\n"); 48213760Sjairo.balart@metempsy.com } 48313531Sjairo.balart@metempsy.com#endif 48413531Sjairo.balart@metempsy.com 48513531Sjairo.balart@metempsy.com return true; 48613531Sjairo.balart@metempsy.com} 48713531Sjairo.balart@metempsy.com 48813760Sjairo.balart@metempsy.com// Write bytes to kernel address space for debugger. 48913531Sjairo.balart@metempsy.combool 49013760Sjairo.balart@metempsy.comBaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) 49113531Sjairo.balart@metempsy.com{ 49213531Sjairo.balart@metempsy.com static Addr lastaddr = 0; 49313531Sjairo.balart@metempsy.com static size_t lastsize = 0; 49413531Sjairo.balart@metempsy.com 49513531Sjairo.balart@metempsy.com if (vaddr < 10) { 49613531Sjairo.balart@metempsy.com DPRINTF(GDBWrite, "write: writing memory location zero!\n"); 49713531Sjairo.balart@metempsy.com vaddr = lastaddr + lastsize; 49813531Sjairo.balart@metempsy.com } 49913531Sjairo.balart@metempsy.com 50013760Sjairo.balart@metempsy.com if (DTRACE(GDBWrite)) { 50113531Sjairo.balart@metempsy.com DPRINTFN("write: addr=%#x, size=%d", vaddr, size); 50213760Sjairo.balart@metempsy.com if (DTRACE(GDBExtra)) { 50313531Sjairo.balart@metempsy.com char buf[1024]; 50413531Sjairo.balart@metempsy.com mem2hex(buf, data, size); 50513531Sjairo.balart@metempsy.com DPRINTFNR(": %s\n", buf); 50613531Sjairo.balart@metempsy.com } else 50713531Sjairo.balart@metempsy.com DPRINTFNR("\n"); 50813760Sjairo.balart@metempsy.com } 50913760Sjairo.balart@metempsy.com#if FULL_SYSTEM 51013760Sjairo.balart@metempsy.com FSTranslatingPortProxy *port = context->getVirtProxy(); 51113760Sjairo.balart@metempsy.com#else 51213760Sjairo.balart@metempsy.com SETranslatingPortProxy *port = context->getMemProxy(); 51313760Sjairo.balart@metempsy.com#endif 51413760Sjairo.balart@metempsy.com port->writeBlob(vaddr, (uint8_t*)data, size); 51513760Sjairo.balart@metempsy.com#if !FULL_SYSTEM 51613760Sjairo.balart@metempsy.com delete port; 51713760Sjairo.balart@metempsy.com#endif 51813760Sjairo.balart@metempsy.com 51913531Sjairo.balart@metempsy.com return true; 52013531Sjairo.balart@metempsy.com} 52113760Sjairo.balart@metempsy.com 52213531Sjairo.balart@metempsy.comPCEventQueue *BaseRemoteGDB::getPcEventQueue() 52313531Sjairo.balart@metempsy.com{ 52413531Sjairo.balart@metempsy.com return &system->pcEventQueue; 52513531Sjairo.balart@metempsy.com} 52613760Sjairo.balart@metempsy.com 52713760Sjairo.balart@metempsy.comBaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc) 52813760Sjairo.balart@metempsy.com : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc), 52913760Sjairo.balart@metempsy.com gdb(_gdb), refcount(0) 53013760Sjairo.balart@metempsy.com{ 53113760Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc); 53213531Sjairo.balart@metempsy.com} 53313760Sjairo.balart@metempsy.com 53413760Sjairo.balart@metempsy.comvoid 53513760Sjairo.balart@metempsy.comBaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc) 53613760Sjairo.balart@metempsy.com{ 53713760Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc()); 53813760Sjairo.balart@metempsy.com 53913760Sjairo.balart@metempsy.com if (tc == gdb->context) 54013760Sjairo.balart@metempsy.com gdb->trap(SIGTRAP); 54113760Sjairo.balart@metempsy.com} 54213760Sjairo.balart@metempsy.com 54313760Sjairo.balart@metempsy.combool 54413760Sjairo.balart@metempsy.comBaseRemoteGDB::insertSoftBreak(Addr addr, size_t len) 54513760Sjairo.balart@metempsy.com{ 54613760Sjairo.balart@metempsy.com if (len != sizeof(TheISA::MachInst)) 54713760Sjairo.balart@metempsy.com panic("invalid length\n"); 54813760Sjairo.balart@metempsy.com 54913760Sjairo.balart@metempsy.com return insertHardBreak(addr, len); 55013760Sjairo.balart@metempsy.com} 55113760Sjairo.balart@metempsy.com 55213760Sjairo.balart@metempsy.combool 55313760Sjairo.balart@metempsy.comBaseRemoteGDB::removeSoftBreak(Addr addr, size_t len) 55413760Sjairo.balart@metempsy.com{ 55513760Sjairo.balart@metempsy.com if (len != sizeof(MachInst)) 55613760Sjairo.balart@metempsy.com panic("invalid length\n"); 55713531Sjairo.balart@metempsy.com 55813760Sjairo.balart@metempsy.com return removeHardBreak(addr, len); 55913760Sjairo.balart@metempsy.com} 56013531Sjairo.balart@metempsy.com 56113531Sjairo.balart@metempsy.combool 56213531Sjairo.balart@metempsy.comBaseRemoteGDB::insertHardBreak(Addr addr, size_t len) 56314245Sgiacomo.travaglini@arm.com{ 56413760Sjairo.balart@metempsy.com if (len != sizeof(MachInst)) 56513760Sjairo.balart@metempsy.com panic("invalid length\n"); 56613760Sjairo.balart@metempsy.com 56713760Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr); 56813760Sjairo.balart@metempsy.com 56913760Sjairo.balart@metempsy.com HardBreakpoint *&bkpt = hardBreakMap[addr]; 57013531Sjairo.balart@metempsy.com if (bkpt == 0) 57113531Sjairo.balart@metempsy.com bkpt = new HardBreakpoint(this, addr); 57213760Sjairo.balart@metempsy.com 57313760Sjairo.balart@metempsy.com bkpt->refcount++; 57413760Sjairo.balart@metempsy.com 57513760Sjairo.balart@metempsy.com return true; 57613760Sjairo.balart@metempsy.com} 57713760Sjairo.balart@metempsy.com 57813760Sjairo.balart@metempsy.combool 57913760Sjairo.balart@metempsy.comBaseRemoteGDB::removeHardBreak(Addr addr, size_t len) 58013531Sjairo.balart@metempsy.com{ 58113531Sjairo.balart@metempsy.com if (len != sizeof(MachInst)) 58213531Sjairo.balart@metempsy.com panic("invalid length\n"); 58313760Sjairo.balart@metempsy.com 58413531Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr); 58513760Sjairo.balart@metempsy.com 58613760Sjairo.balart@metempsy.com break_iter_t i = hardBreakMap.find(addr); 58713760Sjairo.balart@metempsy.com if (i == hardBreakMap.end()) 58813760Sjairo.balart@metempsy.com return false; 58913760Sjairo.balart@metempsy.com 59013760Sjairo.balart@metempsy.com HardBreakpoint *hbp = (*i).second; 59113760Sjairo.balart@metempsy.com if (--hbp->refcount == 0) { 59213531Sjairo.balart@metempsy.com delete hbp; 59313531Sjairo.balart@metempsy.com hardBreakMap.erase(i); 59413531Sjairo.balart@metempsy.com } 59513760Sjairo.balart@metempsy.com 59613531Sjairo.balart@metempsy.com return true; 59713531Sjairo.balart@metempsy.com} 59813760Sjairo.balart@metempsy.com 59913760Sjairo.balart@metempsy.comvoid 60013760Sjairo.balart@metempsy.comBaseRemoteGDB::setTempBreakpoint(Addr bkpt) 60113760Sjairo.balart@metempsy.com{ 60213760Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt); 60313760Sjairo.balart@metempsy.com insertHardBreak(bkpt, sizeof(TheISA::MachInst)); 60413760Sjairo.balart@metempsy.com} 60513531Sjairo.balart@metempsy.com 60613531Sjairo.balart@metempsy.comvoid 60713760Sjairo.balart@metempsy.comBaseRemoteGDB::clearTempBreakpoint(Addr &bkpt) 60813760Sjairo.balart@metempsy.com{ 60913760Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt); 61013760Sjairo.balart@metempsy.com removeHardBreak(bkpt, sizeof(TheISA::MachInst)); 61113760Sjairo.balart@metempsy.com bkpt = 0; 61213760Sjairo.balart@metempsy.com} 61313760Sjairo.balart@metempsy.com 61413760Sjairo.balart@metempsy.comconst char * 61513760Sjairo.balart@metempsy.comBaseRemoteGDB::break_type(char c) 61613531Sjairo.balart@metempsy.com{ 61713531Sjairo.balart@metempsy.com switch(c) { 61813531Sjairo.balart@metempsy.com case '0': return "software breakpoint"; 61913760Sjairo.balart@metempsy.com case '1': return "hardware breakpoint"; 62013531Sjairo.balart@metempsy.com case '2': return "write watchpoint"; 62113531Sjairo.balart@metempsy.com case '3': return "read watchpoint"; 62213531Sjairo.balart@metempsy.com case '4': return "access watchpoint"; 62313531Sjairo.balart@metempsy.com default: return "unknown breakpoint/watchpoint"; 62413760Sjairo.balart@metempsy.com } 62513531Sjairo.balart@metempsy.com} 62613531Sjairo.balart@metempsy.com 62713531Sjairo.balart@metempsy.com// This function does all command processing for interfacing to a 62813531Sjairo.balart@metempsy.com// remote gdb. Note that the error codes are ignored by gdb at 62914236Sgiacomo.travaglini@arm.com// present, but might eventually become meaningful. (XXX) It might 63014236Sgiacomo.travaglini@arm.com// makes sense to use POSIX errno values, because that is what the 63114236Sgiacomo.travaglini@arm.com// gdb/remote.c functions want to return. 63214236Sgiacomo.travaglini@arm.combool 63314236Sgiacomo.travaglini@arm.comBaseRemoteGDB::trap(int type) 63414236Sgiacomo.travaglini@arm.com{ 63514236Sgiacomo.travaglini@arm.com uint64_t val; 63614236Sgiacomo.travaglini@arm.com size_t datalen, len; 63714236Sgiacomo.travaglini@arm.com char data[GDBPacketBufLen + 1]; 63814236Sgiacomo.travaglini@arm.com char *buffer; 63914236Sgiacomo.travaglini@arm.com size_t bufferSize; 64014236Sgiacomo.travaglini@arm.com const char *p; 64113760Sjairo.balart@metempsy.com char command, subcmd; 64213531Sjairo.balart@metempsy.com string var; 64313531Sjairo.balart@metempsy.com bool ret; 64413531Sjairo.balart@metempsy.com 64513531Sjairo.balart@metempsy.com if (!attached) 64614236Sgiacomo.travaglini@arm.com return false; 64714236Sgiacomo.travaglini@arm.com 64814236Sgiacomo.travaglini@arm.com bufferSize = gdbregs.bytes() * 2 + 256; 64914236Sgiacomo.travaglini@arm.com buffer = (char*)malloc(bufferSize); 65014236Sgiacomo.travaglini@arm.com 65114236Sgiacomo.travaglini@arm.com DPRINTF(GDBMisc, "trap: PC=%s\n", context->pcState()); 65214236Sgiacomo.travaglini@arm.com 65314236Sgiacomo.travaglini@arm.com clearSingleStep(); 65414236Sgiacomo.travaglini@arm.com 65514236Sgiacomo.travaglini@arm.com /* 65614236Sgiacomo.travaglini@arm.com * The first entry to this function is normally through 65714236Sgiacomo.travaglini@arm.com * a breakpoint trap in kgdb_connect(), in which case we 65813760Sjairo.balart@metempsy.com * must advance past the breakpoint because gdb will not. 65913531Sjairo.balart@metempsy.com * 66013760Sjairo.balart@metempsy.com * On the first entry here, we expect that gdb is not yet 66113760Sjairo.balart@metempsy.com * listening to us, so just enter the interaction loop. 66213760Sjairo.balart@metempsy.com * After the debugger is "active" (connected) it will be 66313760Sjairo.balart@metempsy.com * waiting for a "signaled" message from us. 66413760Sjairo.balart@metempsy.com */ 66513760Sjairo.balart@metempsy.com if (!active) 66613760Sjairo.balart@metempsy.com active = true; 66713760Sjairo.balart@metempsy.com else 66813760Sjairo.balart@metempsy.com // Tell remote host that an exception has occurred. 66913760Sjairo.balart@metempsy.com snprintf((char *)buffer, bufferSize, "S%02x", type); 67013760Sjairo.balart@metempsy.com send(buffer); 67113760Sjairo.balart@metempsy.com 67213760Sjairo.balart@metempsy.com // Stick frame regs into our reg cache. 67313760Sjairo.balart@metempsy.com getregs(); 67413760Sjairo.balart@metempsy.com 67513760Sjairo.balart@metempsy.com for (;;) { 67613760Sjairo.balart@metempsy.com datalen = recv(data, sizeof(data)); 67713531Sjairo.balart@metempsy.com data[sizeof(data) - 1] = 0; // Sentinel 67813531Sjairo.balart@metempsy.com command = data[0]; 67913760Sjairo.balart@metempsy.com subcmd = 0; 68013531Sjairo.balart@metempsy.com p = data + 1; 68113531Sjairo.balart@metempsy.com switch (command) { 68213760Sjairo.balart@metempsy.com 68313531Sjairo.balart@metempsy.com case GDBSignal: 68413531Sjairo.balart@metempsy.com // if this command came from a running gdb, answer it -- 68513760Sjairo.balart@metempsy.com // the other guy has no way of knowing if we're in or out 68613531Sjairo.balart@metempsy.com // of this loop when he issues a "remote-signal". 68713531Sjairo.balart@metempsy.com snprintf((char *)buffer, bufferSize, 68813531Sjairo.balart@metempsy.com "S%02x", type); 68913531Sjairo.balart@metempsy.com send(buffer); 69013531Sjairo.balart@metempsy.com continue; 69113760Sjairo.balart@metempsy.com 69213531Sjairo.balart@metempsy.com case GDBRegR: 69313531Sjairo.balart@metempsy.com if (2 * gdbregs.bytes() > bufferSize) 69413760Sjairo.balart@metempsy.com panic("buffer too small"); 69513760Sjairo.balart@metempsy.com 69613531Sjairo.balart@metempsy.com mem2hex(buffer, gdbregs.regs, gdbregs.bytes()); 69713531Sjairo.balart@metempsy.com send(buffer); 69813531Sjairo.balart@metempsy.com continue; 69913531Sjairo.balart@metempsy.com 70013531Sjairo.balart@metempsy.com case GDBRegW: 70113531Sjairo.balart@metempsy.com p = hex2mem(gdbregs.regs, p, gdbregs.bytes()); 70213760Sjairo.balart@metempsy.com if (p == NULL || *p != '\0') 70313531Sjairo.balart@metempsy.com send("E01"); 70413531Sjairo.balart@metempsy.com else { 70513531Sjairo.balart@metempsy.com setregs(); 70613531Sjairo.balart@metempsy.com send("OK"); 70713531Sjairo.balart@metempsy.com } 70813760Sjairo.balart@metempsy.com continue; 70913531Sjairo.balart@metempsy.com 71013531Sjairo.balart@metempsy.com#if 0 71113531Sjairo.balart@metempsy.com case GDBSetReg: 71213531Sjairo.balart@metempsy.com val = hex2i(&p); 71313531Sjairo.balart@metempsy.com if (*p++ != '=') { 71413760Sjairo.balart@metempsy.com send("E01"); 71513531Sjairo.balart@metempsy.com continue; 71613531Sjairo.balart@metempsy.com } 71713531Sjairo.balart@metempsy.com if (val < 0 && val >= KGDB_NUMREGS) { 71813760Sjairo.balart@metempsy.com send("E01"); 71913531Sjairo.balart@metempsy.com continue; 72013531Sjairo.balart@metempsy.com } 72113531Sjairo.balart@metempsy.com 72213531Sjairo.balart@metempsy.com gdbregs.regs[val] = hex2i(&p); 72313531Sjairo.balart@metempsy.com setregs(); 72413760Sjairo.balart@metempsy.com send("OK"); 72513760Sjairo.balart@metempsy.com 72613531Sjairo.balart@metempsy.com continue; 72713531Sjairo.balart@metempsy.com#endif 72813760Sjairo.balart@metempsy.com 72913760Sjairo.balart@metempsy.com case GDBMemR: 73013531Sjairo.balart@metempsy.com val = hex2i(&p); 73113531Sjairo.balart@metempsy.com if (*p++ != ',') { 73213531Sjairo.balart@metempsy.com send("E02"); 73313531Sjairo.balart@metempsy.com continue; 73413580Sgabeblack@google.com } 73513531Sjairo.balart@metempsy.com len = hex2i(&p); 73613531Sjairo.balart@metempsy.com if (*p != '\0') { 73713760Sjairo.balart@metempsy.com send("E03"); 73813760Sjairo.balart@metempsy.com continue; 73913531Sjairo.balart@metempsy.com } 74013531Sjairo.balart@metempsy.com if (len > bufferSize) { 74113531Sjairo.balart@metempsy.com send("E04"); 74213531Sjairo.balart@metempsy.com continue; 74313760Sjairo.balart@metempsy.com } 74413531Sjairo.balart@metempsy.com if (!acc(val, len)) { 74513531Sjairo.balart@metempsy.com send("E05"); 74613531Sjairo.balart@metempsy.com continue; 74713531Sjairo.balart@metempsy.com } 74813531Sjairo.balart@metempsy.com 74913531Sjairo.balart@metempsy.com if (read(val, (size_t)len, (char *)buffer)) { 75014246Sgiacomo.travaglini@arm.com // variable length array would be nice, but C++ doesn't 75114246Sgiacomo.travaglini@arm.com // officially support those... 75213531Sjairo.balart@metempsy.com char *temp = new char[2*len+1]; 75313531Sjairo.balart@metempsy.com mem2hex(temp, buffer, len); 75413531Sjairo.balart@metempsy.com send(temp); 75513531Sjairo.balart@metempsy.com delete [] temp; 75613531Sjairo.balart@metempsy.com } else { 75713531Sjairo.balart@metempsy.com send("E05"); 75813531Sjairo.balart@metempsy.com } 75913531Sjairo.balart@metempsy.com continue; 76013531Sjairo.balart@metempsy.com 76113531Sjairo.balart@metempsy.com case GDBMemW: 76213531Sjairo.balart@metempsy.com val = hex2i(&p); 76313531Sjairo.balart@metempsy.com if (*p++ != ',') { 76413531Sjairo.balart@metempsy.com send("E06"); 76513531Sjairo.balart@metempsy.com continue; 76613760Sjairo.balart@metempsy.com } 76713531Sjairo.balart@metempsy.com len = hex2i(&p); 76813531Sjairo.balart@metempsy.com if (*p++ != ':') { 76913531Sjairo.balart@metempsy.com send("E07"); 77013531Sjairo.balart@metempsy.com continue; 77113531Sjairo.balart@metempsy.com } 77213531Sjairo.balart@metempsy.com if (len > datalen - (p - data)) { 77313531Sjairo.balart@metempsy.com send("E08"); 77413531Sjairo.balart@metempsy.com continue; 77513531Sjairo.balart@metempsy.com } 77613531Sjairo.balart@metempsy.com p = hex2mem(buffer, p, bufferSize); 77713531Sjairo.balart@metempsy.com if (p == NULL) { 77813531Sjairo.balart@metempsy.com send("E09"); 77913531Sjairo.balart@metempsy.com continue; 78013531Sjairo.balart@metempsy.com } 78113531Sjairo.balart@metempsy.com if (!acc(val, len)) { 78213531Sjairo.balart@metempsy.com send("E0A"); 78313531Sjairo.balart@metempsy.com continue; 78413531Sjairo.balart@metempsy.com } 78513531Sjairo.balart@metempsy.com if (write(val, (size_t)len, (char *)buffer)) 78613531Sjairo.balart@metempsy.com send("OK"); 78713531Sjairo.balart@metempsy.com else 78813760Sjairo.balart@metempsy.com send("E0B"); 78913531Sjairo.balart@metempsy.com continue; 79013531Sjairo.balart@metempsy.com 79113531Sjairo.balart@metempsy.com case GDBSetThread: 79213531Sjairo.balart@metempsy.com subcmd = *p++; 79313531Sjairo.balart@metempsy.com val = hex2i(&p); 79413531Sjairo.balart@metempsy.com if (val == 0) 79513531Sjairo.balart@metempsy.com send("OK"); 79613531Sjairo.balart@metempsy.com else 79713531Sjairo.balart@metempsy.com send("E01"); 79813923Sgiacomo.travaglini@arm.com continue; 79913923Sgiacomo.travaglini@arm.com 80013531Sjairo.balart@metempsy.com case GDBDetach: 80113531Sjairo.balart@metempsy.com case GDBKill: 80213531Sjairo.balart@metempsy.com active = false; 80313531Sjairo.balart@metempsy.com clearSingleStep(); 80413531Sjairo.balart@metempsy.com detach(); 80513531Sjairo.balart@metempsy.com goto out; 80613531Sjairo.balart@metempsy.com 80713531Sjairo.balart@metempsy.com case GDBAsyncCont: 80813531Sjairo.balart@metempsy.com subcmd = hex2i(&p); 80913531Sjairo.balart@metempsy.com if (*p++ == ';') { 81013531Sjairo.balart@metempsy.com val = hex2i(&p); 81113531Sjairo.balart@metempsy.com context->pcState(val); 81213531Sjairo.balart@metempsy.com } 81313531Sjairo.balart@metempsy.com clearSingleStep(); 81413531Sjairo.balart@metempsy.com goto out; 81513531Sjairo.balart@metempsy.com 81613531Sjairo.balart@metempsy.com case GDBCont: 81713531Sjairo.balart@metempsy.com if (p - data < (ptrdiff_t)datalen) { 81813760Sjairo.balart@metempsy.com val = hex2i(&p); 81913531Sjairo.balart@metempsy.com context->pcState(val); 82013531Sjairo.balart@metempsy.com } 82113531Sjairo.balart@metempsy.com clearSingleStep(); 82213531Sjairo.balart@metempsy.com goto out; 82313531Sjairo.balart@metempsy.com 82413531Sjairo.balart@metempsy.com case GDBAsyncStep: 82513531Sjairo.balart@metempsy.com subcmd = hex2i(&p); 82613531Sjairo.balart@metempsy.com if (*p++ == ';') { 82713531Sjairo.balart@metempsy.com val = hex2i(&p); 82813531Sjairo.balart@metempsy.com context->pcState(val); 82913531Sjairo.balart@metempsy.com } 83013531Sjairo.balart@metempsy.com setSingleStep(); 83113531Sjairo.balart@metempsy.com goto out; 83213531Sjairo.balart@metempsy.com 83313531Sjairo.balart@metempsy.com case GDBStep: 83413531Sjairo.balart@metempsy.com if (p - data < (ptrdiff_t)datalen) { 83513531Sjairo.balart@metempsy.com val = hex2i(&p); 83613531Sjairo.balart@metempsy.com context->pcState(val); 83713531Sjairo.balart@metempsy.com } 83813531Sjairo.balart@metempsy.com setSingleStep(); 83913531Sjairo.balart@metempsy.com goto out; 84013760Sjairo.balart@metempsy.com 84113531Sjairo.balart@metempsy.com case GDBClrHwBkpt: 84213531Sjairo.balart@metempsy.com subcmd = *p++; 84313760Sjairo.balart@metempsy.com if (*p++ != ',') send("E0D"); 84413760Sjairo.balart@metempsy.com val = hex2i(&p); 84513531Sjairo.balart@metempsy.com if (*p++ != ',') send("E0D"); 84613531Sjairo.balart@metempsy.com len = hex2i(&p); 84713760Sjairo.balart@metempsy.com 84813531Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n", 84913531Sjairo.balart@metempsy.com break_type(subcmd), val, len); 85013531Sjairo.balart@metempsy.com 85113531Sjairo.balart@metempsy.com ret = false; 85213531Sjairo.balart@metempsy.com 85313531Sjairo.balart@metempsy.com switch (subcmd) { 85413531Sjairo.balart@metempsy.com case '0': // software breakpoint 85513531Sjairo.balart@metempsy.com ret = removeSoftBreak(val, len); 85613531Sjairo.balart@metempsy.com break; 85713531Sjairo.balart@metempsy.com 85813760Sjairo.balart@metempsy.com case '1': // hardware breakpoint 85913531Sjairo.balart@metempsy.com ret = removeHardBreak(val, len); 86013760Sjairo.balart@metempsy.com break; 86113531Sjairo.balart@metempsy.com 86213531Sjairo.balart@metempsy.com case '2': // write watchpoint 86313531Sjairo.balart@metempsy.com case '3': // read watchpoint 86413531Sjairo.balart@metempsy.com case '4': // access watchpoint 86513531Sjairo.balart@metempsy.com default: // unknown 86613531Sjairo.balart@metempsy.com send(""); 86713531Sjairo.balart@metempsy.com break; 86813923Sgiacomo.travaglini@arm.com } 86913923Sgiacomo.travaglini@arm.com 87013531Sjairo.balart@metempsy.com send(ret ? "OK" : "E0C"); 87113531Sjairo.balart@metempsy.com continue; 87213531Sjairo.balart@metempsy.com 87313760Sjairo.balart@metempsy.com case GDBSetHwBkpt: 87413531Sjairo.balart@metempsy.com subcmd = *p++; 87513531Sjairo.balart@metempsy.com if (*p++ != ',') send("E0D"); 87613531Sjairo.balart@metempsy.com val = hex2i(&p); 87713531Sjairo.balart@metempsy.com if (*p++ != ',') send("E0D"); 87813531Sjairo.balart@metempsy.com len = hex2i(&p); 87913531Sjairo.balart@metempsy.com 88013531Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n", 88113531Sjairo.balart@metempsy.com break_type(subcmd), val, len); 88213531Sjairo.balart@metempsy.com 88313760Sjairo.balart@metempsy.com ret = false; 88413531Sjairo.balart@metempsy.com 88513531Sjairo.balart@metempsy.com switch (subcmd) { 88613531Sjairo.balart@metempsy.com case '0': // software breakpoint 88713531Sjairo.balart@metempsy.com ret = insertSoftBreak(val, len); 88813531Sjairo.balart@metempsy.com break; 88913531Sjairo.balart@metempsy.com 89013531Sjairo.balart@metempsy.com case '1': // hardware breakpoint 89113531Sjairo.balart@metempsy.com ret = insertHardBreak(val, len); 89213531Sjairo.balart@metempsy.com break; 89313531Sjairo.balart@metempsy.com 89413531Sjairo.balart@metempsy.com case '2': // write watchpoint 89513531Sjairo.balart@metempsy.com case '3': // read watchpoint 89613531Sjairo.balart@metempsy.com case '4': // access watchpoint 89713760Sjairo.balart@metempsy.com default: // unknown 89813531Sjairo.balart@metempsy.com send(""); 89913531Sjairo.balart@metempsy.com break; 90013531Sjairo.balart@metempsy.com } 90113531Sjairo.balart@metempsy.com 90213531Sjairo.balart@metempsy.com send(ret ? "OK" : "E0C"); 90313760Sjairo.balart@metempsy.com continue; 90413531Sjairo.balart@metempsy.com 90513531Sjairo.balart@metempsy.com case GDBQueryVar: 90613531Sjairo.balart@metempsy.com var = string(p, datalen - 1); 90713531Sjairo.balart@metempsy.com if (var == "C") 90813531Sjairo.balart@metempsy.com send("QC0"); 90913531Sjairo.balart@metempsy.com else 91013531Sjairo.balart@metempsy.com send(""); 91113531Sjairo.balart@metempsy.com continue; 91213531Sjairo.balart@metempsy.com 91313531Sjairo.balart@metempsy.com case GDBSetBaud: 91413531Sjairo.balart@metempsy.com case GDBSetBreak: 91513531Sjairo.balart@metempsy.com case GDBDebug: 91613760Sjairo.balart@metempsy.com case GDBCycleStep: 91713531Sjairo.balart@metempsy.com case GDBSigCycleStep: 91813531Sjairo.balart@metempsy.com case GDBReadReg: 91913760Sjairo.balart@metempsy.com case GDBSetVar: 92013531Sjairo.balart@metempsy.com case GDBReset: 92113531Sjairo.balart@metempsy.com case GDBThreadAlive: 92213760Sjairo.balart@metempsy.com case GDBTargetExit: 92313760Sjairo.balart@metempsy.com case GDBBinaryDload: 92413531Sjairo.balart@metempsy.com // Unsupported command 92513531Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "Unsupported command: %s\n", 92613531Sjairo.balart@metempsy.com gdb_command(command)); 92713531Sjairo.balart@metempsy.com DDUMP(GDBMisc, (uint8_t *)data, datalen); 92813531Sjairo.balart@metempsy.com send(""); 92913531Sjairo.balart@metempsy.com continue; 93013531Sjairo.balart@metempsy.com 93113531Sjairo.balart@metempsy.com default: 93213531Sjairo.balart@metempsy.com // Unknown command. 93313531Sjairo.balart@metempsy.com DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n", 93413531Sjairo.balart@metempsy.com command, command); 93513531Sjairo.balart@metempsy.com send(""); 93613760Sjairo.balart@metempsy.com continue; 93713531Sjairo.balart@metempsy.com 93813760Sjairo.balart@metempsy.com 93913531Sjairo.balart@metempsy.com } 94013760Sjairo.balart@metempsy.com } 94113531Sjairo.balart@metempsy.com 94213531Sjairo.balart@metempsy.com out: 94313531Sjairo.balart@metempsy.com free(buffer); 94413531Sjairo.balart@metempsy.com return true; 94513531Sjairo.balart@metempsy.com} 94613760Sjairo.balart@metempsy.com 94713760Sjairo.balart@metempsy.com// Convert a hex digit into an integer. 94813760Sjairo.balart@metempsy.com// This returns -1 if the argument passed is no valid hex digit. 94913760Sjairo.balart@metempsy.comint 95013531Sjairo.balart@metempsy.comBaseRemoteGDB::digit2i(char c) 95113531Sjairo.balart@metempsy.com{ 95213531Sjairo.balart@metempsy.com if (c >= '0' && c <= '9') 95313531Sjairo.balart@metempsy.com return (c - '0'); 95413760Sjairo.balart@metempsy.com else if (c >= 'a' && c <= 'f') 95513531Sjairo.balart@metempsy.com return (c - 'a' + 10); 95613531Sjairo.balart@metempsy.com else if (c >= 'A' && c <= 'F') 95713531Sjairo.balart@metempsy.com 95813531Sjairo.balart@metempsy.com return (c - 'A' + 10); 95913531Sjairo.balart@metempsy.com else 96013531Sjairo.balart@metempsy.com return (-1); 96113531Sjairo.balart@metempsy.com} 96213531Sjairo.balart@metempsy.com 96313531Sjairo.balart@metempsy.com// Convert the low 4 bits of an integer into an hex digit. 96413531Sjairo.balart@metempsy.comchar 96513531Sjairo.balart@metempsy.comBaseRemoteGDB::i2digit(int n) 96613531Sjairo.balart@metempsy.com{ 96713531Sjairo.balart@metempsy.com return ("0123456789abcdef"[n & 0x0f]); 96813531Sjairo.balart@metempsy.com} 96913531Sjairo.balart@metempsy.com 97013531Sjairo.balart@metempsy.com// Convert a byte array into an hex string. 97113531Sjairo.balart@metempsy.comvoid 97213531Sjairo.balart@metempsy.comBaseRemoteGDB::mem2hex(void *vdst, const void *vsrc, int len) 97313531Sjairo.balart@metempsy.com{ 97413531Sjairo.balart@metempsy.com char *dst = (char *)vdst; 97513531Sjairo.balart@metempsy.com const char *src = (const char *)vsrc; 97613531Sjairo.balart@metempsy.com 97713531Sjairo.balart@metempsy.com while (len--) { 97813531Sjairo.balart@metempsy.com *dst++ = i2digit(*src >> 4); 97913531Sjairo.balart@metempsy.com *dst++ = i2digit(*src++); 98013531Sjairo.balart@metempsy.com } 98113531Sjairo.balart@metempsy.com *dst = '\0'; 98213531Sjairo.balart@metempsy.com} 98313531Sjairo.balart@metempsy.com 98413531Sjairo.balart@metempsy.com// Convert an hex string into a byte array. 98513531Sjairo.balart@metempsy.com// This returns a pointer to the character following the last valid 98613531Sjairo.balart@metempsy.com// hex digit. If the string ends in the middle of a byte, NULL is 98713531Sjairo.balart@metempsy.com// returned. 98813531Sjairo.balart@metempsy.comconst char * 98913760Sjairo.balart@metempsy.comBaseRemoteGDB::hex2mem(void *vdst, const char *src, int maxlen) 99013531Sjairo.balart@metempsy.com{ 99113531Sjairo.balart@metempsy.com char *dst = (char *)vdst; 99213531Sjairo.balart@metempsy.com int msb, lsb; 99313531Sjairo.balart@metempsy.com 99413760Sjairo.balart@metempsy.com while (*src && maxlen--) { 99513531Sjairo.balart@metempsy.com msb = digit2i(*src++); 99613531Sjairo.balart@metempsy.com if (msb < 0) 99713531Sjairo.balart@metempsy.com return (src - 1); 99813531Sjairo.balart@metempsy.com lsb = digit2i(*src++); 99913531Sjairo.balart@metempsy.com if (lsb < 0) 100013531Sjairo.balart@metempsy.com return (NULL); 100113531Sjairo.balart@metempsy.com *dst++ = (msb << 4) | lsb; 100213531Sjairo.balart@metempsy.com } 100313760Sjairo.balart@metempsy.com return (src); 100413760Sjairo.balart@metempsy.com} 100513531Sjairo.balart@metempsy.com 100613531Sjairo.balart@metempsy.com// Convert an hex string into an integer. 100713531Sjairo.balart@metempsy.com// This returns a pointer to the character following the last valid 100813531Sjairo.balart@metempsy.com// hex digit. 100913531Sjairo.balart@metempsy.comAddr 101013531Sjairo.balart@metempsy.comBaseRemoteGDB::hex2i(const char **srcp) 101113531Sjairo.balart@metempsy.com{ 101213531Sjairo.balart@metempsy.com const char *src = *srcp; 101313531Sjairo.balart@metempsy.com Addr r = 0; 101413531Sjairo.balart@metempsy.com int nibble; 101513531Sjairo.balart@metempsy.com 101613531Sjairo.balart@metempsy.com while ((nibble = digit2i(*src)) >= 0) { 101713531Sjairo.balart@metempsy.com r *= 16; 101813531Sjairo.balart@metempsy.com r += nibble; 101913760Sjairo.balart@metempsy.com src++; 102013531Sjairo.balart@metempsy.com } 102113531Sjairo.balart@metempsy.com *srcp = src; 102213531Sjairo.balart@metempsy.com return (r); 102313531Sjairo.balart@metempsy.com} 102413531Sjairo.balart@metempsy.com 102513760Sjairo.balart@metempsy.com