remote_gdb.cc revision 2632:1bb2f91485ea
12623SN/A/* 22623SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32623SN/A * All rights reserved. 42623SN/A * 52623SN/A * Redistribution and use in source and binary forms, with or without 62623SN/A * modification, are permitted provided that the following conditions are 72623SN/A * met: redistributions of source code must retain the above copyright 82623SN/A * notice, this list of conditions and the following disclaimer; 92623SN/A * redistributions in binary form must reproduce the above copyright 102623SN/A * notice, this list of conditions and the following disclaimer in the 112623SN/A * documentation and/or other materials provided with the distribution; 122623SN/A * neither the name of the copyright holders nor the names of its 132623SN/A * contributors may be used to endorse or promote products derived from 142623SN/A * this software without specific prior written permission. 152623SN/A * 162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292623SN/A/* 302623SN/A * Copyright (c) 1990, 1993 312623SN/A * The Regents of the University of California. All rights reserved. 322623SN/A * 332623SN/A * This software was developed by the Computer Systems Engineering group 342623SN/A * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 352623SN/A * contributed to Berkeley. 362623SN/A * 372623SN/A * All advertising materials mentioning features or use of this software 382623SN/A * must display the following acknowledgement: 392623SN/A * This product includes software developed by the University of 402623SN/A * California, Lawrence Berkeley Laboratories. 412623SN/A * 422623SN/A * Redistribution and use in source and binary forms, with or without 432623SN/A * modification, are permitted provided that the following conditions 442623SN/A * are met: 452623SN/A * 1. Redistributions of source code must retain the above copyright 462623SN/A * notice, this list of conditions and the following disclaimer. 472623SN/A * 2. Redistributions in binary form must reproduce the above copyright 482623SN/A * notice, this list of conditions and the following disclaimer in the 492623SN/A * documentation and/or other materials provided with the distribution. 502623SN/A * 3. All advertising materials mentioning features or use of this software 512623SN/A * must display the following acknowledgement: 522623SN/A * This product includes software developed by the University of 532623SN/A * California, Berkeley and its contributors. 542623SN/A * 4. Neither the name of the University nor the names of its contributors 552680Sktlim@umich.edu * may be used to endorse or promote products derived from this software 562680Sktlim@umich.edu * without specific prior written permission. 572623SN/A * 582623SN/A * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 592680Sktlim@umich.edu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 602623SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 612623SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 622623SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 632623SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 642623SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 652630SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 662623SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 672623SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 682623SN/A * SUCH DAMAGE. 692623SN/A * 702623SN/A * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 712623SN/A */ 722630SN/A 732623SN/A/*- 742623SN/A * Copyright (c) 2001 The NetBSD Foundation, Inc. 752623SN/A * All rights reserved. 762623SN/A * 772623SN/A * This code is derived from software contributed to The NetBSD Foundation 782623SN/A * by Jason R. Thorpe. 792623SN/A * 802631SN/A * Redistribution and use in source and binary forms, with or without 812631SN/A * modification, are permitted provided that the following conditions 822631SN/A * are met: 832623SN/A * 1. Redistributions of source code must retain the above copyright 842623SN/A * notice, this list of conditions and the following disclaimer. 852623SN/A * 2. Redistributions in binary form must reproduce the above copyright 862623SN/A * notice, this list of conditions and the following disclaimer in the 872623SN/A * documentation and/or other materials provided with the distribution. 882623SN/A * 3. All advertising materials mentioning features or use of this software 892623SN/A * must display the following acknowledgement: 902623SN/A * This product includes software developed by the NetBSD 912623SN/A * Foundation, Inc. and its contributors. 922623SN/A * 4. Neither the name of The NetBSD Foundation nor the names of its 932623SN/A * contributors may be used to endorse or promote products derived 942623SN/A * from this software without specific prior written permission. 952623SN/A * 962623SN/A * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 972623SN/A * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 982623SN/A * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 992623SN/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 1002623SN/A * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1012623SN/A * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1022623SN/A * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1032623SN/A * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1042623SN/A * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1052623SN/A * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1062623SN/A * POSSIBILITY OF SUCH DAMAGE. 1072623SN/A */ 1082623SN/A 1092623SN/A/* 1102623SN/A * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ 1112623SN/A * 1122623SN/A * Taken from NetBSD 1132623SN/A * 1142623SN/A * "Stub" to allow remote cpu to debug over a serial line using gdb. 1152623SN/A */ 1162623SN/A 1172623SN/A#include <sys/signal.h> 1182623SN/A 1192623SN/A#include <string> 1202623SN/A#include <unistd.h> 1212623SN/A 1222623SN/A#include "arch/vtophys.hh" 1232623SN/A#include "base/intmath.hh" 1242623SN/A#include "base/kgdb.h" 1252623SN/A#include "base/remote_gdb.hh" 1262623SN/A#include "base/socket.hh" 1272623SN/A#include "base/trace.hh" 1282680Sktlim@umich.edu#include "config/full_system.hh" 1292623SN/A#include "cpu/exec_context.hh" 1302680Sktlim@umich.edu#include "cpu/static_inst.hh" 1312680Sktlim@umich.edu#include "mem/physical.hh" 1322680Sktlim@umich.edu#include "mem/port.hh" 1332623SN/A#include "sim/system.hh" 1342623SN/A 1352623SN/Ausing namespace std; 1362623SN/Ausing namespace TheISA; 1372623SN/A 1382623SN/A#ifndef NDEBUG 1392623SN/Avector<RemoteGDB *> debuggers; 1402623SN/Aint current_debugger = -1; 1412623SN/A 1422623SN/Avoid 1432623SN/Adebugger() 1442623SN/A{ 1452623SN/A if (current_debugger >= 0 && current_debugger < debuggers.size()) { 1462623SN/A RemoteGDB *gdb = debuggers[current_debugger]; 1472623SN/A if (!gdb->isattached()) 1482623SN/A gdb->listener->accept(); 1492623SN/A if (gdb->isattached()) 1502623SN/A gdb->trap(ALPHA_KENTRY_IF); 1512623SN/A } 1522623SN/A} 1532623SN/A#endif 1542623SN/A 1552623SN/A/////////////////////////////////////////////////////////// 1562623SN/A// 1572623SN/A// 1582623SN/A// 1592623SN/A 1602623SN/AGDBListener::Event::Event(GDBListener *l, int fd, int e) 1612623SN/A : PollEvent(fd, e), listener(l) 1622623SN/A{} 1632644Sstever@eecs.umich.edu 1642623SN/Avoid 1652644Sstever@eecs.umich.eduGDBListener::Event::process(int revent) 1662644Sstever@eecs.umich.edu{ 1672623SN/A listener->accept(); 1682623SN/A} 1692623SN/A 1702623SN/AGDBListener::GDBListener(RemoteGDB *g, int p) 1712623SN/A : event(NULL), gdb(g), port(p) 1722623SN/A{ 1732623SN/A assert(!gdb->listener); 1742623SN/A gdb->listener = this; 1752623SN/A} 1762623SN/A 1772663Sstever@eecs.umich.eduGDBListener::~GDBListener() 1782663Sstever@eecs.umich.edu{ 1792623SN/A if (event) 1802663Sstever@eecs.umich.edu delete event; 1812623SN/A} 1822623SN/A 1832623SN/Astring 1842623SN/AGDBListener::name() 1852623SN/A{ 1862623SN/A return gdb->name() + ".listener"; 1872623SN/A} 1882623SN/A 1892623SN/Avoid 1902623SN/AGDBListener::listen() 1912641Sstever@eecs.umich.edu{ 1922641Sstever@eecs.umich.edu while (!listener.listen(port, true)) { 1932623SN/A DPRINTF(GDBMisc, "Can't bind port %d\n", port); 1942623SN/A port++; 1952630SN/A } 1962623SN/A 1972623SN/A event = new Event(this, listener.getfd(), POLLIN); 1982623SN/A pollQueue.schedule(event); 1992623SN/A 2002623SN/A#ifndef NDEBUG 2012623SN/A gdb->number = debuggers.size(); 2022623SN/A debuggers.push_back(gdb); 2032623SN/A#endif 2042623SN/A 2052623SN/A#ifndef NDEBUG 2062623SN/A ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n", 2072623SN/A curTick, name(), gdb->number, port); 2082623SN/A#else 2092623SN/A ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n", 2102623SN/A curTick, name(), port); 2112623SN/A#endif 2122623SN/A} 2132623SN/A 2142623SN/Avoid 2152623SN/AGDBListener::accept() 2162623SN/A{ 2172623SN/A if (!listener.islistening()) 2182623SN/A panic("GDBListener::accept(): cannot accept if we're not listening!"); 2192623SN/A 2202623SN/A int sfd = listener.accept(true); 2212623SN/A 2222623SN/A if (sfd != -1) { 2232623SN/A if (gdb->isattached()) 2242623SN/A close(sfd); 2252623SN/A else 2262623SN/A gdb->attach(sfd); 2272623SN/A } 2282623SN/A} 2292623SN/A 2302623SN/A/////////////////////////////////////////////////////////// 2312623SN/A// 2322623SN/A// 2332623SN/A// 2342623SN/Aint digit2i(char); 2352623SN/Achar i2digit(int); 2362623SN/Avoid mem2hex(void *, const void *, int); 2372623SN/Aconst char *hex2mem(void *, const char *, int); 2382623SN/AAddr hex2i(const char **); 2392623SN/A 2402623SN/ARemoteGDB::Event::Event(RemoteGDB *g, int fd, int e) 2412623SN/A : PollEvent(fd, e), gdb(g) 2422623SN/A{} 2432623SN/A 2442623SN/Avoid 2452623SN/ARemoteGDB::Event::process(int revent) 2462623SN/A{ 2472623SN/A if (revent & POLLIN) 2482623SN/A gdb->trap(ALPHA_KENTRY_IF); 2492623SN/A else if (revent & POLLNVAL) 2502623SN/A gdb->detach(); 2512623SN/A} 2522623SN/A 2532623SN/ARemoteGDB::RemoteGDB(System *_system, ExecContext *c) 2542623SN/A : event(NULL), listener(NULL), number(-1), fd(-1), 2552623SN/A active(false), attached(false), 2562623SN/A system(_system), pmem(_system->physmem), context(c) 2572623SN/A{ 2582663Sstever@eecs.umich.edu memset(gdbregs, 0, sizeof(gdbregs)); 2592663Sstever@eecs.umich.edu} 2602663Sstever@eecs.umich.edu 2612623SN/ARemoteGDB::~RemoteGDB() 2622623SN/A{ 2632623SN/A if (event) 2642623SN/A delete event; 2652623SN/A} 2662641Sstever@eecs.umich.edu 2672641Sstever@eecs.umich.edustring 2682623SN/ARemoteGDB::name() 2692623SN/A{ 2702623SN/A return system->name() + ".remote_gdb"; 2712630SN/A} 2722623SN/A 2732623SN/Abool 2742623SN/ARemoteGDB::isattached() 2752623SN/A{ return attached; } 2762623SN/A 2772623SN/Avoid 2782623SN/ARemoteGDB::attach(int f) 2792623SN/A{ 2802623SN/A fd = f; 2812623SN/A 2822623SN/A event = new Event(this, fd, POLLIN); 2832623SN/A pollQueue.schedule(event); 2842623SN/A 2852623SN/A attached = true; 2862623SN/A DPRINTFN("remote gdb attached\n"); 2872623SN/A} 2882623SN/A 2892623SN/Avoid 2902623SN/ARemoteGDB::detach() 2912623SN/A{ 2922623SN/A attached = false; 2932623SN/A close(fd); 2942623SN/A fd = -1; 2952623SN/A 2962623SN/A pollQueue.remove(event); 2972623SN/A DPRINTFN("remote gdb detached\n"); 2982623SN/A} 2992623SN/A 3002623SN/Aconst char * 3012623SN/Agdb_command(char cmd) 3022623SN/A{ 3032623SN/A switch (cmd) { 3042623SN/A case KGDB_SIGNAL: return "KGDB_SIGNAL"; 3052623SN/A case KGDB_SET_BAUD: return "KGDB_SET_BAUD"; 3062623SN/A case KGDB_SET_BREAK: return "KGDB_SET_BREAK"; 3072623SN/A case KGDB_CONT: return "KGDB_CONT"; 3082623SN/A case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT"; 3092623SN/A case KGDB_DEBUG: return "KGDB_DEBUG"; 3102623SN/A case KGDB_DETACH: return "KGDB_DETACH"; 3112623SN/A case KGDB_REG_R: return "KGDB_REG_R"; 3122623SN/A case KGDB_REG_W: return "KGDB_REG_W"; 3132623SN/A case KGDB_SET_THREAD: return "KGDB_SET_THREAD"; 3142623SN/A case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP"; 3152623SN/A case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP"; 3162623SN/A case KGDB_KILL: return "KGDB_KILL"; 3172623SN/A case KGDB_MEM_W: return "KGDB_MEM_W"; 3182623SN/A case KGDB_MEM_R: return "KGDB_MEM_R"; 3192623SN/A case KGDB_SET_REG: return "KGDB_SET_REG"; 3202623SN/A case KGDB_READ_REG: return "KGDB_READ_REG"; 3212623SN/A case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR"; 3222623SN/A case KGDB_SET_VAR: return "KGDB_SET_VAR"; 3232623SN/A case KGDB_RESET: return "KGDB_RESET"; 3242623SN/A case KGDB_STEP: return "KGDB_STEP"; 3252623SN/A case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP"; 3262623SN/A case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE"; 3272623SN/A case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT"; 3282623SN/A case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD"; 3292623SN/A case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT"; 3302623SN/A case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT"; 3312623SN/A case KGDB_START: return "KGDB_START"; 3322623SN/A case KGDB_END: return "KGDB_END"; 3332623SN/A case KGDB_GOODP: return "KGDB_GOODP"; 3342623SN/A case KGDB_BADP: return "KGDB_BADP"; 3352623SN/A default: return "KGDB_UNKNOWN"; 3362623SN/A } 3372623SN/A} 3382623SN/A 3392631SN/A/////////////////////////////////////////////////////////// 3402631SN/A// RemoteGDB::acc 3412663Sstever@eecs.umich.edu// 3422663Sstever@eecs.umich.edu// Determine if the mapping at va..(va+len) is valid. 3432662Sstever@eecs.umich.edu// 3442623SN/Abool 3452641Sstever@eecs.umich.eduRemoteGDB::acc(Addr va, size_t len) 3462623SN/A{ 3472623SN/A Addr last_va; 3482623SN/A 3492630SN/A va = TheISA::TruncPage(va); 3502623SN/A last_va = TheISA::RoundPage(va + len); 3512623SN/A 3522623SN/A do { 3532623SN/A if (TheISA::IsK0Seg(va)) { 3542623SN/A if (va < (TheISA::K0SegBase + pmem->size())) { 3552623SN/A DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= " 3562623SN/A "%#x < K0SEG + size\n", va); 3572623SN/A return true; 3582623SN/A } else { 3592644Sstever@eecs.umich.edu DPRINTF(GDBAcc, "acc: Mapping invalid %#x > K0SEG + size\n", 3602644Sstever@eecs.umich.edu va); 3612623SN/A return false; 3622623SN/A } 3632623SN/A } 3642623SN/A 3652623SN/A /** 3662644Sstever@eecs.umich.edu * This code says that all accesses to palcode (instruction and data) 3672623SN/A * are valid since there isn't a va->pa mapping because palcode is 3682623SN/A * accessed physically. At some point this should probably be cleaned up 3692623SN/A * but there is no easy way to do it. 3702631SN/A */ 3712631SN/A 3722631SN/A if (AlphaISA::PcPAL(va) || va < 0x10000) 3732631SN/A return true; 3742631SN/A 3752631SN/A Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20); 3762623SN/A TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va); 3772623SN/A if (!pte.valid()) { 3782623SN/A DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); 3792623SN/A return false; 3802644Sstever@eecs.umich.edu } 3812623SN/A va += TheISA::PageBytes; 3822623SN/A } while (va < last_va); 3832623SN/A 3842644Sstever@eecs.umich.edu DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va); 3852623SN/A return true; 3862623SN/A} 3872644Sstever@eecs.umich.edu 3882644Sstever@eecs.umich.edu/////////////////////////////////////////////////////////// 3892644Sstever@eecs.umich.edu// RemoteGDB::signal 3902644Sstever@eecs.umich.edu// 3912623SN/A// Translate a trap number into a Unix-compatible signal number. 3922644Sstever@eecs.umich.edu// (GDB only understands Unix signal numbers.) 3932623SN/A// 3942623SN/Aint 3952644Sstever@eecs.umich.eduRemoteGDB::signal(int type) 3962644Sstever@eecs.umich.edu{ 3972644Sstever@eecs.umich.edu switch (type) { 3982644Sstever@eecs.umich.edu case ALPHA_KENTRY_INT: 3992644Sstever@eecs.umich.edu return (SIGTRAP); 4002644Sstever@eecs.umich.edu 4012644Sstever@eecs.umich.edu case ALPHA_KENTRY_UNA: 4022644Sstever@eecs.umich.edu return (SIGBUS); 4032644Sstever@eecs.umich.edu 4042623SN/A case ALPHA_KENTRY_ARITH: 4052623SN/A return (SIGFPE); 4062623SN/A 4072644Sstever@eecs.umich.edu case ALPHA_KENTRY_IF: 4082644Sstever@eecs.umich.edu return (SIGILL); 4092623SN/A 4102623SN/A case ALPHA_KENTRY_MM: 4112623SN/A return (SIGSEGV); 4122623SN/A 4132623SN/A default: 4142630SN/A panic("unknown signal type"); 4152623SN/A return 0; 4162644Sstever@eecs.umich.edu } 4172623SN/A} 4182623SN/A 4192623SN/A/////////////////////////////////////////////////////////// 4202657Ssaidi@eecs.umich.edu// RemoteGDB::getregs 4212623SN/A// 4222623SN/A// Translate the kernel debugger register format into 4232623SN/A// the GDB register format. 4242623SN/Avoid 4252623SN/ARemoteGDB::getregs() 4262623SN/A{ 4272623SN/A memset(gdbregs, 0, sizeof(gdbregs)); 4282657Ssaidi@eecs.umich.edu 4292657Ssaidi@eecs.umich.edu gdbregs[KGDB_REG_PC] = context->readPC(); 4302657Ssaidi@eecs.umich.edu 4312657Ssaidi@eecs.umich.edu // @todo: Currently this is very Alpha specific. 4322623SN/A if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) { 4332623SN/A for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { 4342623SN/A gdbregs[i] = context->readIntReg(AlphaISA::reg_redir[i]); 4352623SN/A } 4362623SN/A } else { 4372623SN/A for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { 4382623SN/A gdbregs[i] = context->readIntReg(i); 4392641Sstever@eecs.umich.edu } 4402623SN/A } 4412623SN/A 4422623SN/A#ifdef KGDB_FP_REGS 4432623SN/A for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { 4442623SN/A gdbregs[i + KGDB_REG_F0] = context->readFloatRegBits(i); 4452644Sstever@eecs.umich.edu } 4462644Sstever@eecs.umich.edu#endif 4472644Sstever@eecs.umich.edu} 4482644Sstever@eecs.umich.edu 4492644Sstever@eecs.umich.edu/////////////////////////////////////////////////////////// 4502623SN/A// RemoteGDB::setregs 4512623SN/A// 4522623SN/A// Translate the GDB register format into the kernel 4532623SN/A// debugger register format. 4542623SN/A// 4552630SN/Avoid 4562623SN/ARemoteGDB::setregs() 4572630SN/A{ 4582623SN/A // @todo: Currently this is very Alpha specific. 4592623SN/A if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) { 4602623SN/A for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { 4612657Ssaidi@eecs.umich.edu context->setIntReg(AlphaISA::reg_redir[i], gdbregs[i]); 4622623SN/A } 4632623SN/A } else { 4642623SN/A for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { 4652623SN/A context->setIntReg(i, gdbregs[i]); 4662623SN/A } 4672623SN/A } 4682623SN/A 4692657Ssaidi@eecs.umich.edu#ifdef KGDB_FP_REGS 4702657Ssaidi@eecs.umich.edu for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { 4712657Ssaidi@eecs.umich.edu context->setFloatRegBits(i, gdbregs[i + KGDB_REG_F0]); 4722657Ssaidi@eecs.umich.edu } 4732623SN/A#endif 4742623SN/A context->setPC(gdbregs[KGDB_REG_PC]); 4752623SN/A} 4762623SN/A 4772623SN/Avoid 4782623SN/ARemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr) 4792623SN/A{ 4802623SN/A DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr); 4812623SN/A 4822623SN/A bkpt.address = addr; 4832623SN/A insertHardBreak(addr, 4); 4842623SN/A} 4852623SN/A 4862623SN/Avoid 4872623SN/ARemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt) 4882623SN/A{ 4892623SN/A DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", 4902623SN/A bkpt.address); 4912623SN/A 4922623SN/A 4932623SN/A removeHardBreak(bkpt.address, 4); 4942623SN/A bkpt.address = 0; 4952623SN/A} 4962623SN/A 4972623SN/Avoid 4982623SN/ARemoteGDB::clearSingleStep() 4992623SN/A{ 5002623SN/A DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n", 5012623SN/A takenBkpt.address, notTakenBkpt.address); 5022623SN/A 5032623SN/A if (takenBkpt.address != 0) 5042623SN/A clearTempBreakpoint(takenBkpt); 5052623SN/A 5062623SN/A if (notTakenBkpt.address != 0) 5072623SN/A clearTempBreakpoint(notTakenBkpt); 5082623SN/A} 5092623SN/A 5102623SN/Avoid 5112623SN/ARemoteGDB::setSingleStep() 5122623SN/A{ 5132623SN/A Addr pc = context->readPC(); 5142623SN/A Addr npc, bpc; 5152623SN/A bool set_bt = false; 5162623SN/A 5172623SN/A npc = pc + sizeof(MachInst); 5182623SN/A 5192623SN/A // User was stopped at pc, e.g. the instruction at pc was not 5202623SN/A // executed. 5212623SN/A MachInst inst = read<MachInst>(pc); 5222623SN/A StaticInstPtr si(inst); 5232623SN/A if (si->hasBranchTarget(pc, context, bpc)) { 5242623SN/A // Don't bother setting a breakpoint on the taken branch if it 5252623SN/A // is the same as the next pc 5262623SN/A if (bpc != npc) 5272623SN/A set_bt = true; 5282623SN/A } 5292623SN/A 5302623SN/A DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n", 5312623SN/A takenBkpt.address, notTakenBkpt.address); 5322623SN/A 5332623SN/A setTempBreakpoint(notTakenBkpt, npc); 5342623SN/A 5352623SN/A if (set_bt) 5362623SN/A setTempBreakpoint(takenBkpt, bpc); 5372623SN/A} 5382623SN/A 5392623SN/A///////////////////////// 5402623SN/A// 5412623SN/A// 5422623SN/A 5432623SN/Auint8_t 5442623SN/ARemoteGDB::getbyte() 5452623SN/A{ 5462623SN/A uint8_t b; 5472623SN/A ::read(fd, &b, 1); 5482623SN/A return b; 5492623SN/A} 5502623SN/A 5512623SN/Avoid 5522623SN/ARemoteGDB::putbyte(uint8_t b) 5532623SN/A{ 5542623SN/A ::write(fd, &b, 1); 5552623SN/A} 5562623SN/A 5572623SN/A// Send a packet to gdb 5582623SN/Avoid 5592623SN/ARemoteGDB::send(const char *bp) 5602623SN/A{ 5612623SN/A const char *p; 5622623SN/A uint8_t csum, c; 5632623SN/A 5642623SN/A DPRINTF(GDBSend, "send: %s\n", bp); 5652623SN/A 5662623SN/A do { 5672623SN/A p = bp; 5682623SN/A putbyte(KGDB_START); 5692623SN/A for (csum = 0; (c = *p); p++) { 5702623SN/A putbyte(c); 571 csum += c; 572 } 573 putbyte(KGDB_END); 574 putbyte(i2digit(csum >> 4)); 575 putbyte(i2digit(csum)); 576 } while ((c = getbyte() & 0x7f) == KGDB_BADP); 577} 578 579// Receive a packet from gdb 580int 581RemoteGDB::recv(char *bp, int maxlen) 582{ 583 char *p; 584 int c, csum; 585 int len; 586 587 do { 588 p = bp; 589 csum = len = 0; 590 while ((c = getbyte()) != KGDB_START) 591 ; 592 593 while ((c = getbyte()) != KGDB_END && len < maxlen) { 594 c &= 0x7f; 595 csum += c; 596 *p++ = c; 597 len++; 598 } 599 csum &= 0xff; 600 *p = '\0'; 601 602 if (len >= maxlen) { 603 putbyte(KGDB_BADP); 604 continue; 605 } 606 607 csum -= digit2i(getbyte()) * 16; 608 csum -= digit2i(getbyte()); 609 610 if (csum == 0) { 611 putbyte(KGDB_GOODP); 612 // Sequence present? 613 if (bp[2] == ':') { 614 putbyte(bp[0]); 615 putbyte(bp[1]); 616 len -= 3; 617 bcopy(bp + 3, bp, len); 618 } 619 break; 620 } 621 putbyte(KGDB_BADP); 622 } while (1); 623 624 DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp); 625 626 return (len); 627} 628 629// Read bytes from kernel address space for debugger. 630bool 631RemoteGDB::read(Addr vaddr, size_t size, char *data) 632{ 633 static Addr lastaddr = 0; 634 static size_t lastsize = 0; 635 636 if (vaddr < 10) { 637 DPRINTF(GDBRead, "read: reading memory location zero!\n"); 638 vaddr = lastaddr + lastsize; 639 } 640 641 DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size); 642 643 context->getVirtPort(context)->readBlob(vaddr, (uint8_t*)data, size); 644 645#if TRACING_ON 646 if (DTRACE(GDBRead)) { 647 if (DTRACE(GDBExtra)) { 648 char buf[1024]; 649 mem2hex(buf, data, size); 650 DPRINTFNR(": %s\n", buf); 651 } else 652 DPRINTFNR("\n"); 653 } 654#endif 655 656 return true; 657} 658 659// Write bytes to kernel address space for debugger. 660bool 661RemoteGDB::write(Addr vaddr, size_t size, const char *data) 662{ 663 static Addr lastaddr = 0; 664 static size_t lastsize = 0; 665 666 if (vaddr < 10) { 667 DPRINTF(GDBWrite, "write: writing memory location zero!\n"); 668 vaddr = lastaddr + lastsize; 669 } 670 671 if (DTRACE(GDBWrite)) { 672 DPRINTFN("write: addr=%#x, size=%d", vaddr, size); 673 if (DTRACE(GDBExtra)) { 674 char buf[1024]; 675 mem2hex(buf, data, size); 676 DPRINTFNR(": %s\n", buf); 677 } else 678 DPRINTFNR("\n"); 679 } 680 681 context->getVirtPort(context)->writeBlob(vaddr, (uint8_t*)data, size); 682 683#ifdef IMB 684 alpha_pal_imb(); 685#endif 686 687 return true; 688} 689 690 691PCEventQueue *RemoteGDB::getPcEventQueue() 692{ 693 return &system->pcEventQueue; 694} 695 696 697RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc) 698 : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc), 699 gdb(_gdb), refcount(0) 700{ 701 DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc); 702} 703 704void 705RemoteGDB::HardBreakpoint::process(ExecContext *xc) 706{ 707 DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc()); 708 709 if (xc == gdb->context) 710 gdb->trap(ALPHA_KENTRY_INT); 711} 712 713bool 714RemoteGDB::insertSoftBreak(Addr addr, size_t len) 715{ 716 if (len != sizeof(MachInst)) 717 panic("invalid length\n"); 718 719 return insertHardBreak(addr, len); 720} 721 722bool 723RemoteGDB::removeSoftBreak(Addr addr, size_t len) 724{ 725 if (len != sizeof(MachInst)) 726 panic("invalid length\n"); 727 728 return removeHardBreak(addr, len); 729} 730 731bool 732RemoteGDB::insertHardBreak(Addr addr, size_t len) 733{ 734 if (len != sizeof(MachInst)) 735 panic("invalid length\n"); 736 737 DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr); 738 739 HardBreakpoint *&bkpt = hardBreakMap[addr]; 740 if (bkpt == 0) 741 bkpt = new HardBreakpoint(this, addr); 742 743 bkpt->refcount++; 744 745 return true; 746} 747 748bool 749RemoteGDB::removeHardBreak(Addr addr, size_t len) 750{ 751 if (len != sizeof(MachInst)) 752 panic("invalid length\n"); 753 754 DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr); 755 756 break_iter_t i = hardBreakMap.find(addr); 757 if (i == hardBreakMap.end()) 758 return false; 759 760 HardBreakpoint *hbp = (*i).second; 761 if (--hbp->refcount == 0) { 762 delete hbp; 763 hardBreakMap.erase(i); 764 } 765 766 return true; 767} 768 769const char * 770break_type(char c) 771{ 772 switch(c) { 773 case '0': return "software breakpoint"; 774 case '1': return "hardware breakpoint"; 775 case '2': return "write watchpoint"; 776 case '3': return "read watchpoint"; 777 case '4': return "access watchpoint"; 778 default: return "unknown breakpoint/watchpoint"; 779 } 780} 781 782// This function does all command processing for interfacing to a 783// remote gdb. Note that the error codes are ignored by gdb at 784// present, but might eventually become meaningful. (XXX) It might 785// makes sense to use POSIX errno values, because that is what the 786// gdb/remote.c functions want to return. 787bool 788RemoteGDB::trap(int type) 789{ 790 uint64_t val; 791 size_t datalen, len; 792 char data[KGDB_BUFLEN + 1]; 793 char buffer[sizeof(gdbregs) * 2 + 256]; 794 char temp[KGDB_BUFLEN]; 795 const char *p; 796 char command, subcmd; 797 string var; 798 bool ret; 799 800 if (!attached) 801 return false; 802 803 DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n", 804 context->readPC(), context->readNextPC()); 805 806 clearSingleStep(); 807 808 /* 809 * The first entry to this function is normally through 810 * a breakpoint trap in kgdb_connect(), in which case we 811 * must advance past the breakpoint because gdb will not. 812 * 813 * On the first entry here, we expect that gdb is not yet 814 * listening to us, so just enter the interaction loop. 815 * After the debugger is "active" (connected) it will be 816 * waiting for a "signaled" message from us. 817 */ 818 if (!active) 819 active = true; 820 else 821 // Tell remote host that an exception has occurred. 822 snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type)); 823 send(buffer); 824 825 // Stick frame regs into our reg cache. 826 getregs(); 827 828 for (;;) { 829 datalen = recv(data, sizeof(data)); 830 data[sizeof(data) - 1] = 0; // Sentinel 831 command = data[0]; 832 subcmd = 0; 833 p = data + 1; 834 switch (command) { 835 836 case KGDB_SIGNAL: 837 // if this command came from a running gdb, answer it -- 838 // the other guy has no way of knowing if we're in or out 839 // of this loop when he issues a "remote-signal". 840 snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type)); 841 send(buffer); 842 continue; 843 844 case KGDB_REG_R: 845 if (2 * sizeof(gdbregs) > sizeof(buffer)) 846 panic("buffer too small"); 847 848 mem2hex(buffer, gdbregs, sizeof(gdbregs)); 849 send(buffer); 850 continue; 851 852 case KGDB_REG_W: 853 p = hex2mem(gdbregs, p, sizeof(gdbregs)); 854 if (p == NULL || *p != '\0') 855 send("E01"); 856 else { 857 setregs(); 858 send("OK"); 859 } 860 continue; 861 862#if 0 863 case KGDB_SET_REG: 864 val = hex2i(&p); 865 if (*p++ != '=') { 866 send("E01"); 867 continue; 868 } 869 if (val < 0 && val >= KGDB_NUMREGS) { 870 send("E01"); 871 continue; 872 } 873 874 gdbregs[val] = hex2i(&p); 875 setregs(); 876 send("OK"); 877 878 continue; 879#endif 880 881 case KGDB_MEM_R: 882 val = hex2i(&p); 883 if (*p++ != ',') { 884 send("E02"); 885 continue; 886 } 887 len = hex2i(&p); 888 if (*p != '\0') { 889 send("E03"); 890 continue; 891 } 892 if (len > sizeof(buffer)) { 893 send("E04"); 894 continue; 895 } 896 if (!acc(val, len)) { 897 send("E05"); 898 continue; 899 } 900 901 if (read(val, (size_t)len, (char *)buffer)) { 902 mem2hex(temp, buffer, len); 903 send(temp); 904 } else { 905 send("E05"); 906 } 907 continue; 908 909 case KGDB_MEM_W: 910 val = hex2i(&p); 911 if (*p++ != ',') { 912 send("E06"); 913 continue; 914 } 915 len = hex2i(&p); 916 if (*p++ != ':') { 917 send("E07"); 918 continue; 919 } 920 if (len > datalen - (p - data)) { 921 send("E08"); 922 continue; 923 } 924 p = hex2mem(buffer, p, sizeof(buffer)); 925 if (p == NULL) { 926 send("E09"); 927 continue; 928 } 929 if (!acc(val, len)) { 930 send("E0A"); 931 continue; 932 } 933 if (write(val, (size_t)len, (char *)buffer)) 934 send("OK"); 935 else 936 send("E0B"); 937 continue; 938 939 case KGDB_SET_THREAD: 940 subcmd = *p++; 941 val = hex2i(&p); 942 if (val == 0) 943 send("OK"); 944 else 945 send("E01"); 946 continue; 947 948 case KGDB_DETACH: 949 case KGDB_KILL: 950 active = false; 951 clearSingleStep(); 952 detach(); 953 goto out; 954 955 case KGDB_ASYNC_CONT: 956 subcmd = hex2i(&p); 957 if (*p++ == ';') { 958 val = hex2i(&p); 959 context->setPC(val); 960 context->setNextPC(val + sizeof(MachInst)); 961 } 962 clearSingleStep(); 963 goto out; 964 965 case KGDB_CONT: 966 if (p - data < datalen) { 967 val = hex2i(&p); 968 context->setPC(val); 969 context->setNextPC(val + sizeof(MachInst)); 970 } 971 clearSingleStep(); 972 goto out; 973 974 case KGDB_ASYNC_STEP: 975 subcmd = hex2i(&p); 976 if (*p++ == ';') { 977 val = hex2i(&p); 978 context->setPC(val); 979 context->setNextPC(val + sizeof(MachInst)); 980 } 981 setSingleStep(); 982 goto out; 983 984 case KGDB_STEP: 985 if (p - data < datalen) { 986 val = hex2i(&p); 987 context->setPC(val); 988 context->setNextPC(val + sizeof(MachInst)); 989 } 990 setSingleStep(); 991 goto out; 992 993 case KGDB_CLR_HW_BKPT: 994 subcmd = *p++; 995 if (*p++ != ',') send("E0D"); 996 val = hex2i(&p); 997 if (*p++ != ',') send("E0D"); 998 len = hex2i(&p); 999 1000 DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n", 1001 break_type(subcmd), val, len); 1002 1003 ret = false; 1004 1005 switch (subcmd) { 1006 case '0': // software breakpoint 1007 ret = removeSoftBreak(val, len); 1008 break; 1009 1010 case '1': // hardware breakpoint 1011 ret = removeHardBreak(val, len); 1012 break; 1013 1014 case '2': // write watchpoint 1015 case '3': // read watchpoint 1016 case '4': // access watchpoint 1017 default: // unknown 1018 send(""); 1019 break; 1020 } 1021 1022 send(ret ? "OK" : "E0C"); 1023 continue; 1024 1025 case KGDB_SET_HW_BKPT: 1026 subcmd = *p++; 1027 if (*p++ != ',') send("E0D"); 1028 val = hex2i(&p); 1029 if (*p++ != ',') send("E0D"); 1030 len = hex2i(&p); 1031 1032 DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n", 1033 break_type(subcmd), val, len); 1034 1035 ret = false; 1036 1037 switch (subcmd) { 1038 case '0': // software breakpoint 1039 ret = insertSoftBreak(val, len); 1040 break; 1041 1042 case '1': // hardware breakpoint 1043 ret = insertHardBreak(val, len); 1044 break; 1045 1046 case '2': // write watchpoint 1047 case '3': // read watchpoint 1048 case '4': // access watchpoint 1049 default: // unknown 1050 send(""); 1051 break; 1052 } 1053 1054 send(ret ? "OK" : "E0C"); 1055 continue; 1056 1057 case KGDB_QUERY_VAR: 1058 var = string(p, datalen - 1); 1059 if (var == "C") 1060 send("QC0"); 1061 else 1062 send(""); 1063 continue; 1064 1065 case KGDB_SET_BAUD: 1066 case KGDB_SET_BREAK: 1067 case KGDB_DEBUG: 1068 case KGDB_CYCLE_STEP: 1069 case KGDB_SIG_CYCLE_STEP: 1070 case KGDB_READ_REG: 1071 case KGDB_SET_VAR: 1072 case KGDB_RESET: 1073 case KGDB_THREAD_ALIVE: 1074 case KGDB_TARGET_EXIT: 1075 case KGDB_BINARY_DLOAD: 1076 // Unsupported command 1077 DPRINTF(GDBMisc, "Unsupported command: %s\n", 1078 gdb_command(command)); 1079 DDUMP(GDBMisc, (uint8_t *)data, datalen); 1080 send(""); 1081 continue; 1082 1083 default: 1084 // Unknown command. 1085 DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n", 1086 command, command); 1087 send(""); 1088 continue; 1089 1090 1091 } 1092 } 1093 1094 out: 1095 return true; 1096} 1097 1098// Convert a hex digit into an integer. 1099// This returns -1 if the argument passed is no valid hex digit. 1100int 1101digit2i(char c) 1102{ 1103 if (c >= '0' && c <= '9') 1104 return (c - '0'); 1105 else if (c >= 'a' && c <= 'f') 1106 return (c - 'a' + 10); 1107 else if (c >= 'A' && c <= 'F') 1108 1109 return (c - 'A' + 10); 1110 else 1111 return (-1); 1112} 1113 1114// Convert the low 4 bits of an integer into an hex digit. 1115char 1116i2digit(int n) 1117{ 1118 return ("0123456789abcdef"[n & 0x0f]); 1119} 1120 1121// Convert a byte array into an hex string. 1122void 1123mem2hex(void *vdst, const void *vsrc, int len) 1124{ 1125 char *dst = (char *)vdst; 1126 const char *src = (const char *)vsrc; 1127 1128 while (len--) { 1129 *dst++ = i2digit(*src >> 4); 1130 *dst++ = i2digit(*src++); 1131 } 1132 *dst = '\0'; 1133} 1134 1135// Convert an hex string into a byte array. 1136// This returns a pointer to the character following the last valid 1137// hex digit. If the string ends in the middle of a byte, NULL is 1138// returned. 1139const char * 1140hex2mem(void *vdst, const char *src, int maxlen) 1141{ 1142 char *dst = (char *)vdst; 1143 int msb, lsb; 1144 1145 while (*src && maxlen--) { 1146 msb = digit2i(*src++); 1147 if (msb < 0) 1148 return (src - 1); 1149 lsb = digit2i(*src++); 1150 if (lsb < 0) 1151 return (NULL); 1152 *dst++ = (msb << 4) | lsb; 1153 } 1154 return (src); 1155} 1156 1157// Convert an hex string into an integer. 1158// This returns a pointer to the character following the last valid 1159// hex digit. 1160Addr 1161hex2i(const char **srcp) 1162{ 1163 const char *src = *srcp; 1164 Addr r = 0; 1165 int nibble; 1166 1167 while ((nibble = digit2i(*src)) >= 0) { 1168 r *= 16; 1169 r += nibble; 1170 src++; 1171 } 1172 *srcp = src; 1173 return (r); 1174} 1175 1176