diff --git a/src/arch/alpha/kgdb.h b/src/arch/alpha/kgdb.h deleted file mode 100644 index 0883dc02f..000000000 --- a/src/arch/alpha/kgdb.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 1992, 1993 The Regents of the University of California - * All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratories. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)remote-sl.h 8.1 (Berkeley) 6/11/93 - */ - -/* $NetBSD: kgdb.h,v 1.4 1998/08/13 02:10:59 eeh Exp $ */ - -#ifndef __KGDB_H__ -#define __KGDB_H__ - -/* - * Message types. - */ -#define KGDB_SIGNAL '?' // last sigal -#define KGDB_SET_BAUD 'b' // set baud (deprecated) -#define KGDB_SET_BREAK 'B' // set breakpoint (deprecated) -#define KGDB_CONT 'c' // resume -#define KGDB_ASYNC_CONT 'C' // continue with signal -#define KGDB_DEBUG 'd' // toggle debug flags (deprecated) -#define KGDB_DETACH 'D' // detach remote gdb -#define KGDB_REG_R 'g' // read general registers -#define KGDB_REG_W 'G' // write general registers -#define KGDB_SET_THREAD 'H' // set thread -#define KGDB_CYCLE_STEP 'i' // step a single cycle -#define KGDB_SIG_CYCLE_STEP 'I' // signal then single cycle step -#define KGDB_KILL 'k' // kill program -#define KGDB_MEM_R 'm' // read memory -#define KGDB_MEM_W 'M' // write memory -#define KGDB_READ_REG 'p' // read register -#define KGDB_SET_REG 'P' // write register -#define KGDB_QUERY_VAR 'q' // query variable -#define KGDB_SET_VAR 'Q' // set variable -#define KGDB_RESET 'r' // reset system. (Deprecated) -#define KGDB_STEP 's' // step -#define KGDB_ASYNC_STEP 'S' // signal and step -#define KGDB_THREAD_ALIVE 'T' // find out if the thread is alive. -#define KGDB_TARGET_EXIT 'W' // target exited -#define KGDB_BINARY_DLOAD 'X' // write memory -#define KGDB_CLR_HW_BKPT 'z' // remove breakpoint or watchpoint -#define KGDB_SET_HW_BKPT 'Z' // insert breakpoint or watchpoint - -/* - * start of frame/end of frame - */ -#define KGDB_START '$' -#define KGDB_END '#' -#define KGDB_GOODP '+' -#define KGDB_BADP '-' - -/* - * Stuff for KGDB. - */ -#define KGDB_NUMREGS 66 /* from tm-alpha.h, NUM_REGS */ -#define KGDB_REG_V0 0 -#define KGDB_REG_T0 1 -#define KGDB_REG_T1 2 -#define KGDB_REG_T2 3 -#define KGDB_REG_T3 4 -#define KGDB_REG_T4 5 -#define KGDB_REG_T5 6 -#define KGDB_REG_T6 7 -#define KGDB_REG_T7 8 -#define KGDB_REG_S0 9 -#define KGDB_REG_S1 10 -#define KGDB_REG_S2 11 -#define KGDB_REG_S3 12 -#define KGDB_REG_S4 13 -#define KGDB_REG_S5 14 -#define KGDB_REG_S6 15 /* FP */ -#define KGDB_REG_A0 16 -#define KGDB_REG_A1 17 -#define KGDB_REG_A2 18 -#define KGDB_REG_A3 19 -#define KGDB_REG_A4 20 -#define KGDB_REG_A5 21 -#define KGDB_REG_T8 22 -#define KGDB_REG_T9 23 -#define KGDB_REG_T10 24 -#define KGDB_REG_T11 25 -#define KGDB_REG_RA 26 -#define KGDB_REG_T12 27 -#define KGDB_REG_AT 28 -#define KGDB_REG_GP 29 -#define KGDB_REG_SP 30 -#define KGDB_REG_ZERO 31 -#define KGDB_REG_F0 32 -#define KGDB_REG_F1 33 -#define KGDB_REG_F2 34 -#define KGDB_REG_F3 35 -#define KGDB_REG_F4 36 -#define KGDB_REG_F5 37 -#define KGDB_REG_F6 38 -#define KGDB_REG_F7 39 -#define KGDB_REG_F8 40 -#define KGDB_REG_F9 41 -#define KGDB_REG_F10 42 -#define KGDB_REG_F11 43 -#define KGDB_REG_F12 44 -#define KGDB_REG_F13 45 -#define KGDB_REG_F14 46 -#define KGDB_REG_F15 47 -#define KGDB_REG_F16 48 -#define KGDB_REG_F17 49 -#define KGDB_REG_F18 50 -#define KGDB_REG_F19 51 -#define KGDB_REG_F20 52 -#define KGDB_REG_F21 53 -#define KGDB_REG_F22 54 -#define KGDB_REG_F23 55 -#define KGDB_REG_F24 56 -#define KGDB_REG_F25 57 -#define KGDB_REG_F26 58 -#define KGDB_REG_F27 59 -#define KGDB_REG_F28 60 -#define KGDB_REG_F29 61 -#define KGDB_REG_F30 62 -#define KGDB_REG_F31 63 -#define KGDB_REG_PC 64 -#define KGDB_REG_VFP 65 - -/* Too much? Must be large enough for register transfer. */ -#define KGDB_BUFLEN 1024 - -#endif /* __KGDB_H__ */ diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index a3fcf6136..f32d49e97 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -124,7 +124,6 @@ #include "arch/alpha/decoder.hh" -#include "arch/alpha/kgdb.h" #include "arch/alpha/regredir.hh" #include "arch/alpha/remote_gdb.hh" #include "arch/alpha/utility.hh" @@ -146,9 +145,8 @@ using namespace std; using namespace AlphaISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc) - : BaseRemoteGDB(_system, tc, KGDB_NUMREGS * sizeof(uint64_t)) + : BaseRemoteGDB(_system, tc) { - memset(gdbregs.regs, 0, gdbregs.bytes()); } /* @@ -203,47 +201,41 @@ RemoteGDB::acc(Addr va, size_t len) return true; } -/* - * Translate the kernel debugger register format into the GDB register - * format. - */ void -RemoteGDB::getregs() +RemoteGDB::AlphaGdbRegCache::getRegs(ThreadContext *context) { - memset(gdbregs.regs, 0, gdbregs.bytes()); + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); - gdbregs.regs64[KGDB_REG_PC] = context->pcState().pc(); + r.pc = context->pcState().pc(); - // @todo: Currently this is very Alpha specific. - if (PcPAL(gdbregs.regs64[KGDB_REG_PC])) { - for (int i = 0; i < NumIntArchRegs; ++i) - gdbregs.regs64[i] = context->readIntReg(reg_redir[i]); + if (PcPAL(r.pc)) { + for (int i = 0; i < 32; ++i) + r.gpr[i] = context->readIntReg(reg_redir[i]); } else { - for (int i = 0; i < NumIntArchRegs; ++i) - gdbregs.regs64[i] = context->readIntReg(i); + for (int i = 0; i < 32; ++i) + r.gpr[i] = context->readIntReg(i); } + for (int i = 0; i < 32; ++i) #ifdef KGDB_FP_REGS - for (int i = 0; i < NumFloatArchRegs; ++i) - gdbregs.regs64[i + KGDB_REG_F0] = context->readFloatRegBits(i); + r.fpr[i] = context->readFloatRegBits(i); +#else + r.fpr[i] = 0; #endif } -/* - * Translate the GDB register format into the kernel debugger register - * format. - */ void -RemoteGDB::setregs() +RemoteGDB::AlphaGdbRegCache::setRegs(ThreadContext *context) const { - // @todo: Currently this is very Alpha specific. - if (PcPAL(gdbregs.regs64[KGDB_REG_PC])) { - for (int i = 0; i < NumIntArchRegs; ++i) { - context->setIntReg(reg_redir[i], gdbregs.regs64[i]); + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + + if (PcPAL(r.pc)) { + for (int i = 0; i < 32; ++i) { + context->setIntReg(reg_redir[i], r.gpr[i]); } } else { - for (int i = 0; i < NumIntArchRegs; ++i) { - context->setIntReg(i, gdbregs.regs64[i]); + for (int i = 0; i < 32; ++i) { + context->setIntReg(i, r.gpr[i]); } } @@ -252,7 +244,7 @@ RemoteGDB::setregs() context->setFloatRegBits(i, gdbregs.regs64[i + KGDB_REG_F0]); } #endif - context->pcState(gdbregs.regs64[KGDB_REG_PC]); + context->pcState(r.pc); } // Write bytes to kernel address space for debugger. @@ -277,3 +269,9 @@ RemoteGDB::insertHardBreak(Addr addr, size_t len) " See PCEventQueue::doService() in cpu/pc_event.cc.\n"); return BaseRemoteGDB::insertHardBreak(addr, len); } + +RemoteGDB::BaseGdbRegCache* +RemoteGDB::gdbRegs() { + return new AlphaGdbRegCache(this); +} + diff --git a/src/arch/alpha/remote_gdb.hh b/src/arch/alpha/remote_gdb.hh index 33994653d..4b71fd23a 100644 --- a/src/arch/alpha/remote_gdb.hh +++ b/src/arch/alpha/remote_gdb.hh @@ -1,4 +1,5 @@ /* + * Copyright (c) 2015 LabWare * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -26,6 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert + * Boris Shingarov */ #ifndef __ARCH_ALPHA_REMOTE_GDB_HH__ @@ -33,7 +35,6 @@ #include -#include "arch/alpha/kgdb.h" #include "arch/alpha/types.hh" #include "base/pollevent.hh" #include "base/remote_gdb.hh" @@ -48,17 +49,33 @@ namespace AlphaISA { class RemoteGDB : public BaseRemoteGDB { protected: - void getregs(); - void setregs(); - // Machine memory bool acc(Addr addr, size_t len); bool write(Addr addr, size_t size, const char *data); bool insertHardBreak(Addr addr, size_t len); + class AlphaGdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint64_t gpr[32]; + uint64_t fpr[32]; + uint64_t pc; + uint64_t vfp; + } r; + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".AlphaGdbRegCache"; } + }; + public: RemoteGDB(System *system, ThreadContext *context); + BaseGdbRegCache *gdbRegs(); }; } // namespace AlphaISA diff --git a/src/arch/arm/remote_gdb.cc b/src/arch/arm/remote_gdb.cc index b85b45369..42ca941a8 100644 --- a/src/arch/arm/remote_gdb.cc +++ b/src/arch/arm/remote_gdb.cc @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google Inc. * Copyright (c) 2010, 2013 ARM Limited * All rights reserved @@ -40,6 +41,7 @@ * * Authors: Nathan Binkert * William Wang + * Boris Shingarov */ /* @@ -162,7 +164,7 @@ using namespace std; using namespace ArmISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc) - : BaseRemoteGDB(_system, tc, GDB_REG_BYTES) + : BaseRemoteGDB(_system, tc) { } @@ -192,133 +194,109 @@ RemoteGDB::acc(Addr va, size_t len) } } -/* - * Translate the kernel debugger register format into the GDB register - * format. - */ void -RemoteGDB::getregs() +RemoteGDB::AArch64GdbRegCache::getRegs(ThreadContext *context) { - DPRINTF(GDBAcc, "getregs in remotegdb \n"); + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); - memset(gdbregs.regs, 0, gdbregs.bytes()); + for (int i = 0; i < 31; ++i) + r.x[i] = context->readIntReg(INTREG_X0 + i); + r.spx = context->readIntReg(INTREG_SPX); + r.pc = context->pcState().pc(); + r.cpsr = context->readMiscRegNoEffect(MISCREG_CPSR); - if (inAArch64(context)) { // AArch64 - // x0-x30 - for (int i = 0; i < 31; ++i) - gdbregs.regs64[GDB64_X0 + i] = context->readIntReg(INTREG_X0 + i); - gdbregs.regs64[GDB64_SPX] = context->readIntReg(INTREG_SPX); - // pc - gdbregs.regs64[GDB64_PC] = context->pcState().pc(); - // cpsr - gdbregs.regs64[GDB64_CPSR] = - context->readMiscRegNoEffect(MISCREG_CPSR); - // v0-v31 - for (int i = 0; i < 128; i += 4) { - int gdboff = GDB64_V0_32 + i; - gdbregs.regs32[gdboff + 0] = context->readFloatRegBits(i + 2); - gdbregs.regs32[gdboff + 1] = context->readFloatRegBits(i + 3); - gdbregs.regs32[gdboff + 2] = context->readFloatRegBits(i + 0); - gdbregs.regs32[gdboff + 3] = context->readFloatRegBits(i + 1); - } - } else { // AArch32 - // R0-R15 supervisor mode - gdbregs.regs32[GDB32_R0 + 0] = context->readIntReg(INTREG_R0); - gdbregs.regs32[GDB32_R0 + 1] = context->readIntReg(INTREG_R1); - gdbregs.regs32[GDB32_R0 + 2] = context->readIntReg(INTREG_R2); - gdbregs.regs32[GDB32_R0 + 3] = context->readIntReg(INTREG_R3); - gdbregs.regs32[GDB32_R0 + 4] = context->readIntReg(INTREG_R4); - gdbregs.regs32[GDB32_R0 + 5] = context->readIntReg(INTREG_R5); - gdbregs.regs32[GDB32_R0 + 6] = context->readIntReg(INTREG_R6); - gdbregs.regs32[GDB32_R0 + 7] = context->readIntReg(INTREG_R7); - gdbregs.regs32[GDB32_R0 + 8] = context->readIntReg(INTREG_R8); - gdbregs.regs32[GDB32_R0 + 9] = context->readIntReg(INTREG_R9); - gdbregs.regs32[GDB32_R0 + 10] = context->readIntReg(INTREG_R10); - gdbregs.regs32[GDB32_R0 + 11] = context->readIntReg(INTREG_R11); - gdbregs.regs32[GDB32_R0 + 12] = context->readIntReg(INTREG_R12); - gdbregs.regs32[GDB32_R0 + 13] = context->readIntReg(INTREG_SP); - gdbregs.regs32[GDB32_R0 + 14] = context->readIntReg(INTREG_LR); - gdbregs.regs32[GDB32_R0 + 15] = context->pcState().pc(); - - // CPSR - gdbregs.regs32[GDB32_CPSR] = context->readMiscRegNoEffect(MISCREG_CPSR); - - // vfpv3/neon floating point registers (32 double or 64 float) - for (int i = 0; i < NumFloatV7ArchRegs; ++i) - gdbregs.regs32[GDB32_F0 + i] = context->readFloatRegBits(i); - - // FPSCR - gdbregs.regs32[GDB32_FPSCR] = - context->readMiscRegNoEffect(MISCREG_FPSCR); + for (int i = 0; i < 32*4; i += 4) { + r.v[i + 0] = context->readFloatRegBits(i + 2); + r.v[i + 1] = context->readFloatRegBits(i + 3); + r.v[i + 2] = context->readFloatRegBits(i + 0); + r.v[i + 3] = context->readFloatRegBits(i + 1); } } -/* - * Translate the GDB register format into the kernel debugger register - * format. - */ void -RemoteGDB::setregs() +RemoteGDB::AArch64GdbRegCache::setRegs(ThreadContext *context) const { + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); - DPRINTF(GDBAcc, "setregs in remotegdb \n"); - if (inAArch64(context)) { // AArch64 - // x0-x30 - for (int i = 0; i < 31; ++i) - context->setIntReg(INTREG_X0 + i, gdbregs.regs64[GDB64_X0 + i]); - // pc - context->pcState(gdbregs.regs64[GDB64_PC]); - // cpsr - context->setMiscRegNoEffect(MISCREG_CPSR, gdbregs.regs64[GDB64_CPSR]); - // Update the stack pointer. This should be done after - // updating CPSR/PSTATE since that might affect how SPX gets - // mapped. - context->setIntReg(INTREG_SPX, gdbregs.regs64[GDB64_SPX]); - // v0-v31 - for (int i = 0; i < 128; i += 4) { - int gdboff = GDB64_V0_32 + i; - context->setFloatRegBits(i + 2, gdbregs.regs32[gdboff + 0]); - context->setFloatRegBits(i + 3, gdbregs.regs32[gdboff + 1]); - context->setFloatRegBits(i + 0, gdbregs.regs32[gdboff + 2]); - context->setFloatRegBits(i + 1, gdbregs.regs32[gdboff + 3]); - } - } else { // AArch32 - // R0-R15 supervisor mode - // arm registers are 32 bits wide, gdb registers are 64 bits wide - // two arm registers are packed into one gdb register (little endian) - context->setIntReg(INTREG_R0, gdbregs.regs32[GDB32_R0 + 0]); - context->setIntReg(INTREG_R1, gdbregs.regs32[GDB32_R0 + 1]); - context->setIntReg(INTREG_R2, gdbregs.regs32[GDB32_R0 + 2]); - context->setIntReg(INTREG_R3, gdbregs.regs32[GDB32_R0 + 3]); - context->setIntReg(INTREG_R4, gdbregs.regs32[GDB32_R0 + 4]); - context->setIntReg(INTREG_R5, gdbregs.regs32[GDB32_R0 + 5]); - context->setIntReg(INTREG_R6, gdbregs.regs32[GDB32_R0 + 6]); - context->setIntReg(INTREG_R7, gdbregs.regs32[GDB32_R0 + 7]); - context->setIntReg(INTREG_R8, gdbregs.regs32[GDB32_R0 + 8]); - context->setIntReg(INTREG_R9, gdbregs.regs32[GDB32_R0 + 9]); - context->setIntReg(INTREG_R10, gdbregs.regs32[GDB32_R0 + 10]); - context->setIntReg(INTREG_R11, gdbregs.regs32[GDB32_R0 + 11]); - context->setIntReg(INTREG_R12, gdbregs.regs32[GDB32_R0 + 12]); - context->setIntReg(INTREG_SP, gdbregs.regs32[GDB32_R0 + 13]); - context->setIntReg(INTREG_LR, gdbregs.regs32[GDB32_R0 + 14]); - context->pcState(gdbregs.regs32[GDB32_R0 + 7]); + for (int i = 0; i < 31; ++i) + context->setIntReg(INTREG_X0 + i, r.x[i]); + context->pcState(r.pc); + context->setMiscRegNoEffect(MISCREG_CPSR, r.cpsr); + // Update the stack pointer. This should be done after + // updating CPSR/PSTATE since that might affect how SPX gets + // mapped. + context->setIntReg(INTREG_SPX, r.spx); - //CPSR - context->setMiscRegNoEffect(MISCREG_CPSR, gdbregs.regs32[GDB32_CPSR]); - - //vfpv3/neon floating point registers (32 double or 64 float) - for (int i = 0; i < NumFloatV7ArchRegs; ++i) - context->setFloatRegBits(i, gdbregs.regs32[GDB32_F0 + i]); - - //FPSCR - context->setMiscReg(MISCREG_FPSCR, gdbregs.regs32[GDB32_FPSCR]); + for (int i = 0; i < 32*4; i += 4) { + context->setFloatRegBits(i + 2, r.v[i + 0]); + context->setFloatRegBits(i + 3, r.v[i + 1]); + context->setFloatRegBits(i + 0, r.v[i + 2]); + context->setFloatRegBits(i + 1, r.v[i + 3]); } } -// Write bytes to kernel address space for debugger. -bool -RemoteGDB::write(Addr vaddr, size_t size, const char *data) +void +RemoteGDB::AArch32GdbRegCache::getRegs(ThreadContext *context) { - return BaseRemoteGDB::write(vaddr, size, data); + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + + r.gpr[0] = context->readIntReg(INTREG_R0); + r.gpr[1] = context->readIntReg(INTREG_R1); + r.gpr[2] = context->readIntReg(INTREG_R2); + r.gpr[3] = context->readIntReg(INTREG_R3); + r.gpr[4] = context->readIntReg(INTREG_R4); + r.gpr[5] = context->readIntReg(INTREG_R5); + r.gpr[6] = context->readIntReg(INTREG_R6); + r.gpr[7] = context->readIntReg(INTREG_R7); + r.gpr[8] = context->readIntReg(INTREG_R8); + r.gpr[9] = context->readIntReg(INTREG_R9); + r.gpr[10] = context->readIntReg(INTREG_R10); + r.gpr[11] = context->readIntReg(INTREG_R11); + r.gpr[12] = context->readIntReg(INTREG_R12); + r.gpr[13] = context->readIntReg(INTREG_SP); + r.gpr[14] = context->readIntReg(INTREG_LR); + r.gpr[15] = context->pcState().pc(); + + // One day somebody will implement transfer of FPRs correctly. + for (int i=0; i<8*3; i++) r.fpr[i] = 0; + + r.fpscr = context->readMiscRegNoEffect(MISCREG_FPSCR); + r.cpsr = context->readMiscRegNoEffect(MISCREG_CPSR); } +void +RemoteGDB::AArch32GdbRegCache::setRegs(ThreadContext *context) const +{ + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + + context->setIntReg(INTREG_R0, r.gpr[0]); + context->setIntReg(INTREG_R1, r.gpr[1]); + context->setIntReg(INTREG_R2, r.gpr[2]); + context->setIntReg(INTREG_R3, r.gpr[3]); + context->setIntReg(INTREG_R4, r.gpr[4]); + context->setIntReg(INTREG_R5, r.gpr[5]); + context->setIntReg(INTREG_R6, r.gpr[6]); + context->setIntReg(INTREG_R7, r.gpr[7]); + context->setIntReg(INTREG_R8, r.gpr[8]); + context->setIntReg(INTREG_R9, r.gpr[9]); + context->setIntReg(INTREG_R10, r.gpr[10]); + context->setIntReg(INTREG_R11, r.gpr[11]); + context->setIntReg(INTREG_R12, r.gpr[12]); + context->setIntReg(INTREG_SP, r.gpr[13]); + context->setIntReg(INTREG_LR, r.gpr[14]); + context->pcState(r.gpr[15]); + + // One day somebody will implement transfer of FPRs correctly. + + context->setMiscReg(MISCREG_FPSCR, r.fpscr); + context->setMiscRegNoEffect(MISCREG_CPSR, r.cpsr); +} + +RemoteGDB::BaseGdbRegCache* +RemoteGDB::gdbRegs() +{ + if (inAArch64(context)) + return new AArch64GdbRegCache(this); + else + return new AArch32GdbRegCache(this); +} diff --git a/src/arch/arm/remote_gdb.hh b/src/arch/arm/remote_gdb.hh index ce5c5aa6e..13ceac17f 100644 --- a/src/arch/arm/remote_gdb.hh +++ b/src/arch/arm/remote_gdb.hh @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2013 ARM Limited * All rights reserved @@ -41,6 +42,7 @@ * * Authors: Nathan Binkert * Stephen Hines + * Boris Shingarov */ #ifndef __ARCH_ARM_REMOTE_GDB_HH__ @@ -48,6 +50,7 @@ #include +#include "arch/arm/utility.hh" #include "base/remote_gdb.hh" class System; @@ -56,41 +59,51 @@ class ThreadContext; namespace ArmISA { -// AArch32 registers with vfpv3/neon -enum { - GDB32_R0 = 0, - GDB32_CPSR = 16, - GDB32_F0 = 17, - GDB32_FPSCR = 81, - GDB32_NUMREGS = 82 -}; - -// AArch64 registers -enum { - GDB64_X0 = 0, - GDB64_SPX = 31, - GDB64_PC = 32, - GDB64_CPSR = 33, - GDB64_V0 = 34, - GDB64_V0_32 = 2 * GDB64_V0, - GDB64_NUMREGS = 98 -}; - -const int GDB_REG_BYTES M5_VAR_USED = - std::max(GDB64_NUMREGS * sizeof(uint64_t), - GDB32_NUMREGS * sizeof(uint32_t)); - class RemoteGDB : public BaseRemoteGDB { protected: bool acc(Addr addr, size_t len); - bool write(Addr addr, size_t size, const char *data); - void getregs(); - void setregs(); + class AArch32GdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint32_t gpr[16]; + uint32_t fpr[8*3]; + uint32_t fpscr; + uint32_t cpsr; + } r; + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".AArch32GdbRegCache"; } + }; + + class AArch64GdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint64_t x[31]; + uint64_t spx; + uint64_t pc; + uint64_t cpsr; + uint32_t v[32*4]; + } r; + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".AArch64GdbRegCache"; } + }; public: RemoteGDB(System *_system, ThreadContext *tc); + BaseGdbRegCache *gdbRegs(); }; } // namespace ArmISA diff --git a/src/arch/mips/remote_gdb.cc b/src/arch/mips/remote_gdb.cc index a7bde8ba6..68d8eaa57 100644 --- a/src/arch/mips/remote_gdb.cc +++ b/src/arch/mips/remote_gdb.cc @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2010 ARM Limited * All rights reserved @@ -41,6 +42,7 @@ * Authors: Nathan Binkert * William Wang * Deyuan Guo + * Boris Shingarov */ /* @@ -149,7 +151,7 @@ using namespace std; using namespace MipsISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc) - : BaseRemoteGDB(_system, tc, GdbNumRegs * sizeof(uint32_t)) + : BaseRemoteGDB(_system, tc) { } @@ -168,70 +170,41 @@ RemoteGDB::acc(Addr va, size_t len) return context->getProcessPtr()->pTable->lookup(va, entry); } -/* - * Translate the kernel debugger register format into the GDB register - * format. - */ void -RemoteGDB::getregs() +RemoteGDB::MipsGdbRegCache::getRegs(ThreadContext *context) { DPRINTF(GDBAcc, "getregs in remotegdb \n"); - memset(gdbregs.regs, 0, gdbregs.bytes()); - // MIPS registers are 32 bits wide, gdb registers are 64 bits wide - // two MIPS registers are packed into one gdb register (little endian) - - // INTREG: R0~R31 - for (int i = 0; i < GdbIntArchRegs; i++) - gdbregs.regs32[i] = context->readIntReg(i); - // SR, LO, HI, BADVADDR, CAUSE, PC - gdbregs.regs32[GdbIntArchRegs + 0] = - context->readMiscRegNoEffect(MISCREG_STATUS); - gdbregs.regs32[GdbIntArchRegs + 1] = context->readIntReg(INTREG_LO); - gdbregs.regs32[GdbIntArchRegs + 2] = context->readIntReg(INTREG_HI); - gdbregs.regs32[GdbIntArchRegs + 3] = - context->readMiscRegNoEffect(MISCREG_BADVADDR); - gdbregs.regs32[GdbIntArchRegs + 4] = - context->readMiscRegNoEffect(MISCREG_CAUSE); - gdbregs.regs32[GdbIntArchRegs + 5] = context->pcState().pc(); - // FLOATREG: F0~F31 - for (int i = 0; i < GdbFloatArchRegs; i++) - gdbregs.regs32[GdbIntRegs + i] = context->readFloatRegBits(i); - // FCR, FIR - gdbregs.regs32[GdbIntRegs + GdbFloatArchRegs + 0] = - context->readFloatRegBits(FLOATREG_FCCR); - gdbregs.regs32[GdbIntRegs + GdbFloatArchRegs + 1] = - context->readFloatRegBits(FLOATREG_FIR); + for (int i = 0; i < 32; i++) r.gpr[i] = context->readIntReg(i); + r.sr = context->readMiscRegNoEffect(MISCREG_STATUS); + r.lo = context->readIntReg(INTREG_LO); + r.hi = context->readIntReg(INTREG_HI); + r.badvaddr = context->readMiscRegNoEffect(MISCREG_BADVADDR); + r.cause = context->readMiscRegNoEffect(MISCREG_CAUSE); + r.pc = context->pcState().pc(); + for (int i = 0; i < 32; i++) r.fpr[i] = context->readFloatRegBits(i); + r.fsr = context->readFloatRegBits(FLOATREG_FCCR); + r.fir = context->readFloatRegBits(FLOATREG_FIR); } -/* - * Translate the GDB register format into the kernel debugger register - * format. - */ void -RemoteGDB::setregs() +RemoteGDB::MipsGdbRegCache::setRegs(ThreadContext *context) const { DPRINTF(GDBAcc, "setregs in remotegdb \n"); - // INTREG: R0~R31 - for (int i = 1; i < GdbIntArchRegs; i++) - context->setIntReg(i, gdbregs.regs32[i]); - // SR, LO, HI, BADVADDR, CAUSE, PC - context->setMiscRegNoEffect(MISCREG_STATUS, - gdbregs.regs32[GdbIntArchRegs + 0]); - context->setIntReg(INTREG_LO, gdbregs.regs32[GdbIntArchRegs + 1]); - context->setIntReg(INTREG_HI, gdbregs.regs32[GdbIntArchRegs + 2]); - context->setMiscRegNoEffect(MISCREG_BADVADDR, - gdbregs.regs32[GdbIntArchRegs + 3]); - context->setMiscRegNoEffect(MISCREG_CAUSE, - gdbregs.regs32[GdbIntArchRegs + 4]); - context->pcState(gdbregs.regs32[GdbIntArchRegs + 5]); - // FLOATREG: F0~F31 - for (int i = 0; i < GdbFloatArchRegs; i++) - context->setFloatRegBits(i, gdbregs.regs32[GdbIntRegs + i]); - // FCR, FIR - context->setFloatRegBits(FLOATREG_FCCR, - gdbregs.regs32[GdbIntRegs + GdbFloatArchRegs + 0]); - context->setFloatRegBits(FLOATREG_FIR, - gdbregs.regs32[GdbIntRegs + GdbFloatArchRegs + 1]); + for (int i = 1; i < 32; i++) context->setIntReg(i, r.gpr[i]); + context->setMiscRegNoEffect(MISCREG_STATUS, r.sr); + context->setIntReg(INTREG_LO, r.lo); + context->setIntReg(INTREG_HI, r.hi); + context->setMiscRegNoEffect(MISCREG_BADVADDR, r.badvaddr); + context->setMiscRegNoEffect(MISCREG_CAUSE, r.cause); + context->pcState(r.pc); + for (int i = 0; i < 32; i++) context->setFloatRegBits(i, r.fpr[i]); + context->setFloatRegBits(FLOATREG_FCCR, r.fsr); + context->setFloatRegBits(FLOATREG_FIR, r.fir); +} + +RemoteGDB::BaseGdbRegCache* +RemoteGDB::gdbRegs() { + return new MipsGdbRegCache(this); } diff --git a/src/arch/mips/remote_gdb.hh b/src/arch/mips/remote_gdb.hh index 8d113eb99..fd006e0b6 100644 --- a/src/arch/mips/remote_gdb.hh +++ b/src/arch/mips/remote_gdb.hh @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2007 The Regents of The University of Michigan * All rights reserved. @@ -27,6 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert + * Boris Shingarov */ #ifndef __ARCH_MIPS_REMOTE_GDB_HH__ @@ -42,27 +44,41 @@ class ThreadContext; namespace MipsISA { - // The number of special regs depends on gdb. - const int GdbIntArchRegs = NumIntArchRegs; - const int GdbIntSpecialRegs = 6; - const int GdbFloatArchRegs = NumFloatArchRegs; - const int GdbFloatSpecialRegs = 2; +class RemoteGDB : public BaseRemoteGDB +{ + protected: + bool acc(Addr addr, size_t len); - const int GdbIntRegs = GdbIntArchRegs + GdbIntSpecialRegs; - const int GdbFloatRegs = GdbFloatArchRegs + GdbFloatSpecialRegs; - const int GdbNumRegs = GdbIntRegs + GdbFloatRegs; - - class RemoteGDB : public BaseRemoteGDB + class MipsGdbRegCache : public BaseGdbRegCache { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint32_t gpr[32]; + uint32_t sr; + uint32_t lo; + uint32_t hi; + uint32_t badvaddr; + uint32_t cause; + uint32_t pc; + uint32_t fpr[32]; + uint32_t fsr; + uint32_t fir; + } r; public: - RemoteGDB(System *_system, ThreadContext *tc); - - protected: - bool acc(Addr addr, size_t len); - - void getregs(); - void setregs(); + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".MipsGdbRegCache"; } }; -} + + + public: + RemoteGDB(System *_system, ThreadContext *tc); + BaseGdbRegCache *gdbRegs(); +}; + +} // namespace MipsISA #endif /* __ARCH_MIPS_REMOTE_GDB_H__ */ diff --git a/src/arch/power/remote_gdb.cc b/src/arch/power/remote_gdb.cc index b8a1592b6..ef10efc18 100644 --- a/src/arch/power/remote_gdb.cc +++ b/src/arch/power/remote_gdb.cc @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2010 ARM Limited * All rights reserved @@ -149,7 +150,7 @@ using namespace std; using namespace PowerISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc) - : BaseRemoteGDB(_system, tc, GDB_REG_BYTES) + : BaseRemoteGDB(_system, tc) { } @@ -171,67 +172,50 @@ RemoteGDB::acc(Addr va, size_t len) return context->getProcessPtr()->pTable->lookup(va, entry); } -/* - * Translate the kernel debugger register format into the GDB register - * format. - * - * The PowerPC ISA is quite flexible in what register sets may be present - * depending on the features implemented by the particular CPU; - * GDB addresses this by describing the format of how register contents - * are transferred on the wire, in XML files such as 'power-core.xml'. - * Ideally, we should be reading these files instead of hardcoding this - * information, but for now the following implementation is enough to - * serve as the RSP backend for the out-of-the-box, default GDB. - */ void -RemoteGDB::getregs() +RemoteGDB::PowerGdbRegCache::getRegs(ThreadContext *context) { - DPRINTF(GDBAcc, "getregs in remotegdb \n"); - memset(gdbregs.regs, 0, gdbregs.bytes()); + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); // Default order on 32-bit PowerPC: // R0-R31 (32-bit each), F0-F31 (64-bit IEEE754 double), // PC, MSR, CR, LR, CTR, XER (32-bit each) - // INTREG: R0~R31 for (int i = 0; i < NumIntArchRegs; i++) - gdbregs.regs32[GdbFirstGPRIndex + i] = htobe((uint32_t)context->readIntReg(i)); + r.gpr[i] = htobe((uint32_t)context->readIntReg(i)); - // FLOATREG: F0~F31 for (int i = 0; i < NumFloatArchRegs; i++) - gdbregs.regs32[GdbFirstFPRIndex + i] = context->readFloatRegBits(i); + r.fpr[i] = context->readFloatRegBits(i); - // PC, MSR, CR, LR, CTR, XER - gdbregs.regs32[GdbPCIndex] = htobe((uint32_t)context->pcState().pc()); - gdbregs.regs32[GdbMSRIndex] = 0; // Is MSR modeled? - gdbregs.regs32[GdbCRIndex] = htobe((uint32_t)context->readIntReg(INTREG_CR)); - gdbregs.regs32[GdbLRIndex] = htobe((uint32_t)context->readIntReg(INTREG_LR)); - gdbregs.regs32[GdbCTRIndex] = htobe((uint32_t)context->readIntReg(INTREG_CTR)); - gdbregs.regs32[GdbXERIndex] = htobe((uint32_t)context->readIntReg(INTREG_XER)); + r.pc = htobe((uint32_t)context->pcState().pc()); + r.msr = 0; // Is MSR modeled? + r.cr = htobe((uint32_t)context->readIntReg(INTREG_CR)); + r.lr = htobe((uint32_t)context->readIntReg(INTREG_LR)); + r.ctr = htobe((uint32_t)context->readIntReg(INTREG_CTR)); + r.xer = htobe((uint32_t)context->readIntReg(INTREG_XER)); } -/* - * Translate the GDB register format into the kernel debugger register - * format. - */ void -RemoteGDB::setregs() +RemoteGDB::PowerGdbRegCache::setRegs(ThreadContext *context) const { - DPRINTF(GDBAcc, "setregs in remotegdb \n"); + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); - // INTREG: R0~R31 for (int i = 0; i < NumIntArchRegs; i++) - context->setIntReg(i, betoh(gdbregs.regs32[GdbFirstGPRIndex + i])); + context->setIntReg(i, betoh(r.gpr[i])); - // FLOATREG: F0~F31 for (int i = 0; i < NumFloatArchRegs; i++) - context->setFloatRegBits(i, gdbregs.regs64[GdbFirstFPRIndex + i]); + context->setFloatRegBits(i, r.fpr[i]); - // PC, MSR, CR, LR, CTR, XER - context->pcState(betoh(gdbregs.regs32[GdbPCIndex])); + context->pcState(betoh(r.pc)); // Is MSR modeled? - context->setIntReg(INTREG_CR, betoh(gdbregs.regs32[GdbCRIndex])); - context->setIntReg(INTREG_LR, betoh(gdbregs.regs32[GdbLRIndex])); - context->setIntReg(INTREG_CTR, betoh(gdbregs.regs32[GdbCTRIndex])); - context->setIntReg(INTREG_XER, betoh(gdbregs.regs32[GdbXERIndex])); + context->setIntReg(INTREG_CR, betoh(r.cr)); + context->setIntReg(INTREG_LR, betoh(r.lr)); + context->setIntReg(INTREG_CTR, betoh(r.ctr)); + context->setIntReg(INTREG_XER, betoh(r.xer)); } + +RemoteGDB::BaseGdbRegCache* +RemoteGDB::gdbRegs() { + return new PowerGdbRegCache(this); +} + diff --git a/src/arch/power/remote_gdb.hh b/src/arch/power/remote_gdb.hh index aea75528e..e1c396266 100644 --- a/src/arch/power/remote_gdb.hh +++ b/src/arch/power/remote_gdb.hh @@ -1,4 +1,5 @@ /* + * Copyright (c) 2015 LabWare * Copyright (c) 2002-2005 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * Copyright (c) 2009 The University of Edinburgh @@ -30,6 +31,7 @@ * Authors: Nathan Binkert * Stephen Hines * Timothy M. Jones + * Boris Shingarov */ #ifndef __ARCH_POWER_REMOTE_GDB_HH__ @@ -42,32 +44,38 @@ namespace PowerISA { -const int GDB_REG_BYTES = - NumIntArchRegs * 4 + - NumFloatArchRegs * 8 + - 4 + /* PC */ - 4 + /* MSR */ - 4 + /* CR */ - 4 + /* LR */ - 4 + /* CTR */ - 4; /* XER */ -const int GdbFirstGPRIndex = 0; -const int GdbFirstFPRIndex = 16; -const int GdbPCIndex = 96; -const int GdbMSRIndex = 97; -const int GdbCRIndex = 98; -const int GdbLRIndex = 99; -const int GdbCTRIndex = 100; -const int GdbXERIndex = 101; class RemoteGDB : public BaseRemoteGDB { - public: - RemoteGDB(System *_system, ThreadContext *tc); protected: bool acc(Addr addr, size_t len); - void getregs(); - void setregs(); + + class PowerGdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint32_t gpr[NumIntArchRegs]; + uint64_t fpr[NumFloatArchRegs]; + uint32_t pc; + uint32_t msr; + uint32_t cr; + uint32_t lr; + uint32_t ctr; + uint32_t xer; + } r; + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".PowerGdbRegCache"; } + }; + + + public: + RemoteGDB(System *_system, ThreadContext *tc); + BaseGdbRegCache *gdbRegs(); }; } // namespace PowerISA diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc index e654741b6..46788af17 100644 --- a/src/arch/sparc/remote_gdb.cc +++ b/src/arch/sparc/remote_gdb.cc @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. @@ -27,6 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert + * Boris Shingarov */ /* @@ -131,6 +133,7 @@ #include "base/trace.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" +#include "debug/GDBAcc.hh" #include "debug/GDBRead.hh" #include "mem/page_table.hh" #include "mem/physical.hh" @@ -144,7 +147,7 @@ using namespace std; using namespace SparcISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) - : BaseRemoteGDB(_system, c, NumGDBRegs * sizeof(uint64_t)) + : BaseRemoteGDB(_system, c) {} /////////////////////////////////////////////////////////// @@ -172,72 +175,82 @@ RemoteGDB::acc(Addr va, size_t len) } } -/////////////////////////////////////////////////////////// -// RemoteGDB::getregs -// -// Translate the kernel debugger register format into -// the GDB register format. void -RemoteGDB::getregs() +RemoteGDB::SPARCGdbRegCache::getRegs(ThreadContext *context) { - memset(gdbregs.regs, 0, gdbregs.size); - + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + for (int i = 0; i < 32; i++) r.gpr[i] = htobe((uint32_t)context->readIntReg(i)); PCState pc = context->pcState(); + r.pc = htobe((uint32_t)pc.pc()); + r.npc = htobe((uint32_t)pc.npc()); + r.y = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1)); PSTATE pstate = context->readMiscReg(MISCREG_PSTATE); + r.psr = htobe((uint32_t)pstate); + r.fsr = htobe((uint32_t)context->readMiscReg(MISCREG_FSR)); + r.csr = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2)); +} - if (pstate.am) { - gdbregs.regs32[Reg32Pc] = htobe((uint32_t)pc.pc()); - gdbregs.regs32[Reg32Npc] = htobe((uint32_t)pc.npc()); - for (int x = RegG0; x <= RegI0 + 7; x++) - gdbregs.regs32[x] = htobe((uint32_t)context->readIntReg(x - RegG0)); - - gdbregs.regs32[Reg32Y] = - htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1)); - gdbregs.regs32[Reg32Psr] = htobe((uint32_t)pstate); - gdbregs.regs32[Reg32Fsr] = - htobe((uint32_t)context->readMiscReg(MISCREG_FSR)); - gdbregs.regs32[Reg32Csr] = - htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2)); - } else { - gdbregs.regs64[RegPc] = htobe(pc.pc()); - gdbregs.regs64[RegNpc] = htobe(pc.npc()); - for (int x = RegG0; x <= RegI0 + 7; x++) - gdbregs.regs64[x] = htobe(context->readIntReg(x - RegG0)); - - gdbregs.regs64[RegFsr] = htobe(context->readMiscReg(MISCREG_FSR)); - gdbregs.regs64[RegFprs] = htobe(context->readMiscReg(MISCREG_FPRS)); - gdbregs.regs64[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1)); - gdbregs.regs64[RegState] = htobe( - context->readMiscReg(MISCREG_CWP) | - pstate << 8 | - context->readMiscReg(MISCREG_ASI) << 24 | - context->readIntReg(NumIntArchRegs + 2) << 32); - } - - DPRINTF(GDBRead, "PC=%#x\n", gdbregs.regs64[RegPc]); +void +RemoteGDB::SPARC64GdbRegCache::getRegs(ThreadContext *context) +{ + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + for (int i = 0; i < 32; i++) r.gpr[i] = htobe(context->readIntReg(i)); + for (int i = 0; i < 32; i++) r.fpr[i] = 0; + PCState pc = context->pcState(); + r.pc = htobe(pc.pc()); + r.npc = htobe(pc.npc()); + r.fsr = htobe(context->readMiscReg(MISCREG_FSR)); + r.fprs = htobe(context->readMiscReg(MISCREG_FPRS)); + r.y = htobe(context->readIntReg(NumIntArchRegs + 1)); + PSTATE pstate = context->readMiscReg(MISCREG_PSTATE); + r.state = htobe( + context->readMiscReg(MISCREG_CWP) | + pstate << 8 | + context->readMiscReg(MISCREG_ASI) << 24 | + context->readIntReg(NumIntArchRegs + 2) << 32); +} +void +RemoteGDB::SPARCGdbRegCache::setRegs(ThreadContext *context) const +{ + for (int i = 0; i < 32; i++) context->setIntReg(i, r.gpr[i]); + PCState pc; + pc.pc(r.pc); + pc.npc(r.npc); + pc.nnpc(pc.npc() + sizeof(MachInst)); + pc.upc(0); + pc.nupc(1); + context->pcState(pc); // Floating point registers are left at 0 in netbsd // All registers other than the pc, npc and int regs // are ignored as well. } -/////////////////////////////////////////////////////////// -// RemoteGDB::setregs -// -// Translate the GDB register format into the kernel -// debugger register format. -// void -RemoteGDB::setregs() +RemoteGDB::SPARC64GdbRegCache::setRegs(ThreadContext *context) const { + for (int i = 0; i < 32; i++) context->setIntReg(i, r.gpr[i]); PCState pc; - pc.pc(gdbregs.regs64[RegPc]); - pc.npc(gdbregs.regs64[RegNpc]); + pc.pc(r.pc); + pc.npc(r.npc); pc.nnpc(pc.npc() + sizeof(MachInst)); pc.upc(0); pc.nupc(1); context->pcState(pc); - for (int x = RegG0; x <= RegI0 + 7; x++) - context->setIntReg(x - RegG0, gdbregs.regs64[x]); - // Only the integer registers, pc and npc are set in netbsd + // Floating point registers are left at 0 in netbsd + // All registers other than the pc, npc and int regs + // are ignored as well. +} + + +RemoteGDB::BaseGdbRegCache* +RemoteGDB::gdbRegs() +{ + PSTATE pstate = context->readMiscReg(MISCREG_PSTATE); + if (pstate.am) + {DPRINTF(GDBRead, "Creating 32-bit GDB\n"); + return new SPARCGdbRegCache(this);} + else + {DPRINTF(GDBRead, "Creating 64-bit GDB\n"); + return new SPARC64GdbRegCache(this);} } diff --git a/src/arch/sparc/remote_gdb.hh b/src/arch/sparc/remote_gdb.hh index 6531e0f61..543683ee8 100644 --- a/src/arch/sparc/remote_gdb.hh +++ b/src/arch/sparc/remote_gdb.hh @@ -1,4 +1,5 @@ /* + * Copyright (c) 2015 LabWare * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -26,6 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert + * Boris Shingarov */ #ifndef __ARCH_SPARC_REMOTE_GDB_HH__ @@ -33,10 +35,7 @@ #include -#include "arch/sparc/types.hh" -#include "base/pollevent.hh" #include "base/remote_gdb.hh" -#include "cpu/pc_event.hh" class System; class ThreadContext; @@ -47,26 +46,58 @@ namespace SparcISA class RemoteGDB : public BaseRemoteGDB { protected: - enum RegisterConstants + bool acc(Addr addr, size_t len); + + class SPARCGdbRegCache : public BaseGdbRegCache { - RegG0 = 0, RegO0 = 8, RegL0 = 16, RegI0 = 24, - RegF0 = 32, - RegPc = 64, RegNpc, RegState, RegFsr, RegFprs, RegY, - /*RegState contains data in same format as tstate */ - Reg32Y = 64, Reg32Psr, Reg32Pc, Reg32Npc, Reg32Fsr, Reg32Csr, - NumGDBRegs + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint32_t gpr[32]; + uint32_t hole[32]; + uint32_t y; + uint32_t psr; + uint32_t wim; + uint32_t tbr; + uint32_t pc; + uint32_t npc; + uint32_t fsr; + uint32_t csr; + } r; + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".SPARCGdbRegCache"; } + }; + + class SPARC64GdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint64_t gpr[32]; + uint64_t fpr[32]; + uint64_t pc; + uint64_t npc; + uint64_t state; + uint64_t fsr; + uint64_t fprs; + uint64_t y; + } r; + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".SPARC64GdbRegCache"; } }; public: - RemoteGDB(System *system, ThreadContext *context); - - bool acc(Addr addr, size_t len); - - protected: - void getregs(); - void setregs(); + RemoteGDB(System *_system, ThreadContext *tc); + BaseGdbRegCache *gdbRegs(); }; - -} +} // namespace SparcISA #endif /* __ARCH_SPARC_REMOTE_GDB_H__ */ diff --git a/src/arch/x86/remote_gdb.cc b/src/arch/x86/remote_gdb.cc index dd96037e0..99800385a 100644 --- a/src/arch/x86/remote_gdb.cc +++ b/src/arch/x86/remote_gdb.cc @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2007 The Hewlett-Packard Development Company * All rights reserved. @@ -36,6 +37,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Gabe Black + * Boris Shingarov */ #include @@ -54,6 +56,7 @@ #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" +#include "debug/GDBAcc.hh" #include "mem/page_table.hh" #include "sim/full_system.hh" @@ -61,7 +64,7 @@ using namespace std; using namespace X86ISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) : - BaseRemoteGDB(_system, c, GDB_REG_BYTES) + BaseRemoteGDB(_system, c) {} bool @@ -88,138 +91,130 @@ RemoteGDB::acc(Addr va, size_t len) } } -void -RemoteGDB::getregs() +RemoteGDB::BaseGdbRegCache* +RemoteGDB::gdbRegs() { HandyM5Reg m5reg = context->readMiscRegNoEffect(MISCREG_M5_REG); - if (m5reg.submode == SixtyFourBitMode) { - gdbregs.regs64[GDB64_RAX] = context->readIntReg(INTREG_RAX); - gdbregs.regs64[GDB64_RBX] = context->readIntReg(INTREG_RBX); - gdbregs.regs64[GDB64_RCX] = context->readIntReg(INTREG_RCX); - gdbregs.regs64[GDB64_RDX] = context->readIntReg(INTREG_RDX); - gdbregs.regs64[GDB64_RSI] = context->readIntReg(INTREG_RSI); - gdbregs.regs64[GDB64_RDI] = context->readIntReg(INTREG_RDI); - gdbregs.regs64[GDB64_RBP] = context->readIntReg(INTREG_RBP); - gdbregs.regs64[GDB64_RSP] = context->readIntReg(INTREG_RSP); - gdbregs.regs64[GDB64_R8] = context->readIntReg(INTREG_R8); - gdbregs.regs64[GDB64_R9] = context->readIntReg(INTREG_R9); - gdbregs.regs64[GDB64_R10] = context->readIntReg(INTREG_R10); - gdbregs.regs64[GDB64_R11] = context->readIntReg(INTREG_R11); - gdbregs.regs64[GDB64_R12] = context->readIntReg(INTREG_R12); - gdbregs.regs64[GDB64_R13] = context->readIntReg(INTREG_R13); - gdbregs.regs64[GDB64_R14] = context->readIntReg(INTREG_R14); - gdbregs.regs64[GDB64_R15] = context->readIntReg(INTREG_R15); - gdbregs.regs64[GDB64_RIP] = context->pcState().pc(); - gdbregs.regs32[GDB64_RFLAGS_32] = - context->readMiscRegNoEffect(MISCREG_RFLAGS); - gdbregs.regs32[GDB64_CS_32] = context->readMiscRegNoEffect(MISCREG_CS); - gdbregs.regs32[GDB64_SS_32] = context->readMiscRegNoEffect(MISCREG_SS); - gdbregs.regs32[GDB64_DS_32] = context->readMiscRegNoEffect(MISCREG_DS); - gdbregs.regs32[GDB64_ES_32] = context->readMiscRegNoEffect(MISCREG_ES); - gdbregs.regs32[GDB64_FS_32] = context->readMiscRegNoEffect(MISCREG_FS); - gdbregs.regs32[GDB64_GS_32] = context->readMiscRegNoEffect(MISCREG_GS); - } else { - gdbregs.regs32[GDB32_EAX] = context->readIntReg(INTREG_RAX); - gdbregs.regs32[GDB32_ECX] = context->readIntReg(INTREG_RCX); - gdbregs.regs32[GDB32_EDX] = context->readIntReg(INTREG_RDX); - gdbregs.regs32[GDB32_EBX] = context->readIntReg(INTREG_RBX); - gdbregs.regs32[GDB32_ESP] = context->readIntReg(INTREG_RSP); - gdbregs.regs32[GDB32_EBP] = context->readIntReg(INTREG_RBP); - gdbregs.regs32[GDB32_ESI] = context->readIntReg(INTREG_RSI); - gdbregs.regs32[GDB32_EDI] = context->readIntReg(INTREG_RDI); - gdbregs.regs32[GDB32_EIP] = context->pcState().pc(); - gdbregs.regs32[GDB32_EFLAGS] = - context->readMiscRegNoEffect(MISCREG_RFLAGS); - gdbregs.regs32[GDB32_CS] = context->readMiscRegNoEffect(MISCREG_CS); - gdbregs.regs32[GDB32_CS] = context->readMiscRegNoEffect(MISCREG_SS); - gdbregs.regs32[GDB32_CS] = context->readMiscRegNoEffect(MISCREG_DS); - gdbregs.regs32[GDB32_CS] = context->readMiscRegNoEffect(MISCREG_ES); - gdbregs.regs32[GDB32_CS] = context->readMiscRegNoEffect(MISCREG_FS); - gdbregs.regs32[GDB32_CS] = context->readMiscRegNoEffect(MISCREG_GS); - } + if (m5reg.submode == SixtyFourBitMode) + return new AMD64GdbRegCache(this); + else + return new X86GdbRegCache(this); +} + + + +void +RemoteGDB::AMD64GdbRegCache::getRegs(ThreadContext *context) +{ + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + r.rax = context->readIntReg(INTREG_RAX); + r.rbx = context->readIntReg(INTREG_RBX); + r.rcx = context->readIntReg(INTREG_RCX); + r.rdx = context->readIntReg(INTREG_RDX); + r.rsi = context->readIntReg(INTREG_RSI); + r.rdi = context->readIntReg(INTREG_RDI); + r.rbp = context->readIntReg(INTREG_RBP); + r.rsp = context->readIntReg(INTREG_RSP); + r.r8 = context->readIntReg(INTREG_R8); + r.r9 = context->readIntReg(INTREG_R9); + r.r10 = context->readIntReg(INTREG_R10); + r.r11 = context->readIntReg(INTREG_R11); + r.r12 = context->readIntReg(INTREG_R12); + r.r13 = context->readIntReg(INTREG_R13); + r.r14 = context->readIntReg(INTREG_R14); + r.r15 = context->readIntReg(INTREG_R15); + r.rip = context->pcState().pc(); + r.eflags = context->readMiscRegNoEffect(MISCREG_RFLAGS); + r.cs = context->readMiscRegNoEffect(MISCREG_CS); + r.ss = context->readMiscRegNoEffect(MISCREG_SS); + r.ds = context->readMiscRegNoEffect(MISCREG_DS); + r.es = context->readMiscRegNoEffect(MISCREG_ES); + r.fs = context->readMiscRegNoEffect(MISCREG_FS); + r.gs = context->readMiscRegNoEffect(MISCREG_GS); } void -RemoteGDB::setregs() +RemoteGDB::X86GdbRegCache::getRegs(ThreadContext *context) { - HandyM5Reg m5reg = context->readMiscRegNoEffect(MISCREG_M5_REG); - if (m5reg.submode == SixtyFourBitMode) { - context->setIntReg(INTREG_RAX, gdbregs.regs64[GDB64_RAX]); - context->setIntReg(INTREG_RBX, gdbregs.regs64[GDB64_RBX]); - context->setIntReg(INTREG_RCX, gdbregs.regs64[GDB64_RCX]); - context->setIntReg(INTREG_RDX, gdbregs.regs64[GDB64_RDX]); - context->setIntReg(INTREG_RSI, gdbregs.regs64[GDB64_RSI]); - context->setIntReg(INTREG_RDI, gdbregs.regs64[GDB64_RDI]); - context->setIntReg(INTREG_RBP, gdbregs.regs64[GDB64_RBP]); - context->setIntReg(INTREG_RSP, gdbregs.regs64[GDB64_RSP]); - context->setIntReg(INTREG_R8, gdbregs.regs64[GDB64_R8]); - context->setIntReg(INTREG_R9, gdbregs.regs64[GDB64_R9]); - context->setIntReg(INTREG_R10, gdbregs.regs64[GDB64_R10]); - context->setIntReg(INTREG_R11, gdbregs.regs64[GDB64_R11]); - context->setIntReg(INTREG_R12, gdbregs.regs64[GDB64_R12]); - context->setIntReg(INTREG_R13, gdbregs.regs64[GDB64_R13]); - context->setIntReg(INTREG_R14, gdbregs.regs64[GDB64_R14]); - context->setIntReg(INTREG_R15, gdbregs.regs64[GDB64_R15]); - context->pcState(gdbregs.regs64[GDB64_RIP]); - context->setMiscReg(MISCREG_RFLAGS, gdbregs.regs32[GDB64_RFLAGS_32]); - if (gdbregs.regs32[GDB64_CS_32] != - context->readMiscRegNoEffect(MISCREG_CS)) { - warn("Remote gdb: Ignoring update to CS.\n"); - } - if (gdbregs.regs32[GDB64_SS_32] != - context->readMiscRegNoEffect(MISCREG_SS)) { - warn("Remote gdb: Ignoring update to SS.\n"); - } - if (gdbregs.regs32[GDB64_DS_32] != - context->readMiscRegNoEffect(MISCREG_DS)) { - warn("Remote gdb: Ignoring update to DS.\n"); - } - if (gdbregs.regs32[GDB64_ES_32] != - context->readMiscRegNoEffect(MISCREG_ES)) { - warn("Remote gdb: Ignoring update to ES.\n"); - } - if (gdbregs.regs32[GDB64_FS_32] != - context->readMiscRegNoEffect(MISCREG_FS)) { - warn("Remote gdb: Ignoring update to FS.\n"); - } - if (gdbregs.regs32[GDB64_GS_32] != - context->readMiscRegNoEffect(MISCREG_GS)) { - warn("Remote gdb: Ignoring update to GS.\n"); - } - } else { - context->setIntReg(INTREG_RAX, gdbregs.regs32[GDB32_EAX]); - context->setIntReg(INTREG_RCX, gdbregs.regs32[GDB32_ECX]); - context->setIntReg(INTREG_RDX, gdbregs.regs32[GDB32_EDX]); - context->setIntReg(INTREG_RBX, gdbregs.regs32[GDB32_EBX]); - context->setIntReg(INTREG_RSP, gdbregs.regs32[GDB32_ESP]); - context->setIntReg(INTREG_RBP, gdbregs.regs32[GDB32_EBP]); - context->setIntReg(INTREG_RSI, gdbregs.regs32[GDB32_ESI]); - context->setIntReg(INTREG_RDI, gdbregs.regs32[GDB32_EDI]); - context->pcState(gdbregs.regs32[GDB32_EIP]); - context->setMiscReg(MISCREG_RFLAGS, gdbregs.regs32[GDB32_EFLAGS]); - if (gdbregs.regs32[GDB64_CS_32] != - context->readMiscRegNoEffect(MISCREG_CS)) { - warn("Remote gdb: Ignoring update to CS.\n"); - } - if (gdbregs.regs32[GDB32_SS] != - context->readMiscRegNoEffect(MISCREG_SS)) { - warn("Remote gdb: Ignoring update to SS.\n"); - } - if (gdbregs.regs32[GDB32_DS] != - context->readMiscRegNoEffect(MISCREG_DS)) { - warn("Remote gdb: Ignoring update to DS.\n"); - } - if (gdbregs.regs32[GDB32_ES] != - context->readMiscRegNoEffect(MISCREG_ES)) { - warn("Remote gdb: Ignoring update to ES.\n"); - } - if (gdbregs.regs32[GDB32_FS] != - context->readMiscRegNoEffect(MISCREG_FS)) { - warn("Remote gdb: Ignoring update to FS.\n"); - } - if (gdbregs.regs32[GDB32_GS] != - context->readMiscRegNoEffect(MISCREG_GS)) { - warn("Remote gdb: Ignoring update to GS.\n"); - } - } + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + r.eax = context->readIntReg(INTREG_RAX); + r.ecx = context->readIntReg(INTREG_RCX); + r.edx = context->readIntReg(INTREG_RDX); + r.ebx = context->readIntReg(INTREG_RBX); + r.esp = context->readIntReg(INTREG_RSP); + r.ebp = context->readIntReg(INTREG_RBP); + r.esi = context->readIntReg(INTREG_RSI); + r.edi = context->readIntReg(INTREG_RDI); + r.eip = context->pcState().pc(); + r.eflags = context->readMiscRegNoEffect(MISCREG_RFLAGS); + r.cs = context->readMiscRegNoEffect(MISCREG_CS); + r.ss = context->readMiscRegNoEffect(MISCREG_SS); + r.ds = context->readMiscRegNoEffect(MISCREG_DS); + r.es = context->readMiscRegNoEffect(MISCREG_ES); + r.fs = context->readMiscRegNoEffect(MISCREG_FS); + r.gs = context->readMiscRegNoEffect(MISCREG_GS); +} + +void +RemoteGDB::AMD64GdbRegCache::setRegs(ThreadContext *context) const +{ + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + context->setIntReg(INTREG_RAX, r.rax); + context->setIntReg(INTREG_RBX, r.rbx); + context->setIntReg(INTREG_RCX, r.rcx); + context->setIntReg(INTREG_RDX, r.rdx); + context->setIntReg(INTREG_RSI, r.rsi); + context->setIntReg(INTREG_RDI, r.rdi); + context->setIntReg(INTREG_RBP, r.rbp); + context->setIntReg(INTREG_RSP, r.rsp); + context->setIntReg(INTREG_R8, r.r8); + context->setIntReg(INTREG_R9, r.r9); + context->setIntReg(INTREG_R10, r.r10); + context->setIntReg(INTREG_R11, r.r11); + context->setIntReg(INTREG_R12, r.r12); + context->setIntReg(INTREG_R13, r.r13); + context->setIntReg(INTREG_R14, r.r14); + context->setIntReg(INTREG_R15, r.r15); + context->pcState(r.rip); + context->setMiscReg(MISCREG_RFLAGS, r.eflags); + if (r.cs != context->readMiscRegNoEffect(MISCREG_CS)) + warn("Remote gdb: Ignoring update to CS.\n"); + if (r.ss != context->readMiscRegNoEffect(MISCREG_SS)) + warn("Remote gdb: Ignoring update to SS.\n"); + if (r.ds != context->readMiscRegNoEffect(MISCREG_DS)) + warn("Remote gdb: Ignoring update to DS.\n"); + if (r.es != context->readMiscRegNoEffect(MISCREG_ES)) + warn("Remote gdb: Ignoring update to ES.\n"); + if (r.fs != context->readMiscRegNoEffect(MISCREG_FS)) + warn("Remote gdb: Ignoring update to FS.\n"); + if (r.gs != context->readMiscRegNoEffect(MISCREG_GS)) + warn("Remote gdb: Ignoring update to GS.\n"); +} + +void +RemoteGDB::X86GdbRegCache::setRegs(ThreadContext *context) const +{ + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + context->setIntReg(INTREG_RAX, r.eax); + context->setIntReg(INTREG_RCX, r.ecx); + context->setIntReg(INTREG_RDX, r.edx); + context->setIntReg(INTREG_RBX, r.ebx); + context->setIntReg(INTREG_RSP, r.esp); + context->setIntReg(INTREG_RBP, r.ebp); + context->setIntReg(INTREG_RSI, r.esi); + context->setIntReg(INTREG_RDI, r.edi); + context->pcState(r.eip); + context->setMiscReg(MISCREG_RFLAGS, r.eflags); + if (r.cs != context->readMiscRegNoEffect(MISCREG_CS)) + warn("Remote gdb: Ignoring update to CS.\n"); + if (r.ss != context->readMiscRegNoEffect(MISCREG_SS)) + warn("Remote gdb: Ignoring update to SS.\n"); + if (r.ds != context->readMiscRegNoEffect(MISCREG_DS)) + warn("Remote gdb: Ignoring update to DS.\n"); + if (r.es != context->readMiscRegNoEffect(MISCREG_ES)) + warn("Remote gdb: Ignoring update to ES.\n"); + if (r.fs != context->readMiscRegNoEffect(MISCREG_FS)) + warn("Remote gdb: Ignoring update to FS.\n"); + if (r.gs != context->readMiscRegNoEffect(MISCREG_GS)) + warn("Remote gdb: Ignoring update to GS.\n"); } diff --git a/src/arch/x86/remote_gdb.hh b/src/arch/x86/remote_gdb.hh index 991452f74..5696e3dc7 100644 --- a/src/arch/x86/remote_gdb.hh +++ b/src/arch/x86/remote_gdb.hh @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2007 The Hewlett-Packard Development Company * All rights reserved. @@ -36,6 +37,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Gabe Black + * Boris Shingarov */ #ifndef __ARCH_X86_REMOTEGDB_HH__ @@ -53,79 +55,86 @@ namespace X86ISA { class RemoteGDB : public BaseRemoteGDB { - public: - enum - { - GDB32_EAX, - GDB32_ECX, - GDB32_EDX, - GDB32_EBX, - GDB32_ESP, - GDB32_EBP, - GDB32_ESI, - GDB32_EDI, - GDB32_EIP, - GDB32_EFLAGS, - GDB32_CS, - GDB32_SS, - GDB32_DS, - GDB32_ES, - GDB32_FS, - GDB32_GS, - - GDB32_NUMREGS - }; - - enum - { - GDB64_RAX, - GDB64_RBX, - GDB64_RCX, - GDB64_RDX, - GDB64_RSI, - GDB64_RDI, - GDB64_RBP, - GDB64_RSP, - GDB64_R8, - GDB64_R9, - GDB64_R10, - GDB64_R11, - GDB64_R12, - GDB64_R13, - GDB64_R14, - GDB64_R15, - GDB64_RIP, - // These indices index into the reg cache treated as an array of 32 - // bit integers. The next index is one beyond the previous, and then - // scaled up from an index into an array of 64 bit integers. - GDB64_RFLAGS_32 = (GDB64_RIP + 1) * 2, - GDB64_CS_32, - GDB64_SS_32, - GDB64_DS_32, - GDB64_ES_32, - GDB64_FS_32, - GDB64_GS_32, - - // Scale the end index count back down (rounded up) to be for an - // array of 64 bit integers. - GDB64_NUMREGS = (GDB64_GS_32 + 1) / 2 + 1 - }; - - RemoteGDB(System *system, ThreadContext *context); - - bool acc(Addr addr, size_t len); - protected: - void getregs(); - void setregs(); - + bool acc(Addr addr, size_t len); bool checkBpLen(size_t len) { return len == 1; } + class X86GdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t eip; + uint32_t eflags; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + } r; + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".X86GdbRegCache"; } + }; + + class AMD64GdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct { + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rsi; + uint64_t rdi; + uint64_t rbp; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rip; + uint32_t eflags; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + /* + * We do not model st[], FPU status regs, xmm[] etc. + * While it's not ok to have G-packets larger than what gdb + * knows about, it is ok to have smaller ones. + */ + } r; + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string name() const { return gdb->name() + ".AMD64GdbRegCache"; } + }; + + public: + RemoteGDB(System *system, ThreadContext *context); + BaseGdbRegCache *gdbRegs(); }; - -const int GDB_REG_BYTES M5_VAR_USED = - std::max(RemoteGDB::GDB32_NUMREGS * sizeof(uint32_t), - RemoteGDB::GDB64_NUMREGS * sizeof(uint64_t)); - -} +} // namespace X86ISA #endif // __ARCH_X86_REMOTEGDB_HH__ diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index e603fb90f..e033bea9c 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. @@ -27,6 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert + * Boris Shingarov */ /* @@ -270,12 +272,11 @@ BaseRemoteGDB::SingleStepEvent::process() gdb->trap(SIGTRAP); } -BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, - size_t cacheSize) : inputEvent(NULL), trapEvent(this), listener(NULL), +BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c) : + inputEvent(NULL), trapEvent(this), listener(NULL), number(-1), fd(-1), active(false), attached(false), system(_system), - context(c), gdbregs(cacheSize), singleStepEvent(this) + context(c), singleStepEvent(this) { - memset(gdbregs.regs, 0, gdbregs.bytes()); } BaseRemoteGDB::~BaseRemoteGDB() @@ -700,7 +701,9 @@ BaseRemoteGDB::trap(int type) if (!attached) return false; - bufferSize = gdbregs.bytes() * 2 + 256; + unique_ptr regCache(gdbRegs()); + + bufferSize = regCache->size() * 2 + 256; buffer = (char*)malloc(bufferSize); DPRINTF(GDBMisc, "trap: PC=%s\n", context->pcState()); @@ -721,12 +724,12 @@ BaseRemoteGDB::trap(int type) active = true; } else { // Tell remote host that an exception has occurred. - snprintf((char *)buffer, bufferSize, "S%02x", type); + snprintf(buffer, bufferSize, "S%02x", type); send(buffer); } // Stick frame regs into our reg cache. - getregs(); + regCache->getRegs(context); for (;;) { datalen = recv(data, sizeof(data)); @@ -740,48 +743,29 @@ BaseRemoteGDB::trap(int type) // if this command came from a running gdb, answer it -- // the other guy has no way of knowing if we're in or out // of this loop when he issues a "remote-signal". - snprintf((char *)buffer, bufferSize, + snprintf(buffer, bufferSize, "S%02x", type); send(buffer); continue; case GDBRegR: - if (2 * gdbregs.bytes() > bufferSize) + if (2 * regCache->size() > bufferSize) panic("buffer too small"); - mem2hex(buffer, gdbregs.regs, gdbregs.bytes()); + mem2hex(buffer, regCache->data(), regCache->size()); send(buffer); continue; case GDBRegW: - p = hex2mem(gdbregs.regs, p, gdbregs.bytes()); + p = hex2mem(regCache->data(), p, regCache->size()); if (p == NULL || *p != '\0') send("E01"); else { - setregs(); + regCache->setRegs(context); send("OK"); } continue; -#if 0 - case GDBSetReg: - val = hex2i(&p); - if (*p++ != '=') { - send("E01"); - continue; - } - if (val < 0 && val >= KGDB_NUMREGS) { - send("E01"); - continue; - } - - gdbregs.regs[val] = hex2i(&p); - setregs(); - send("OK"); - - continue; -#endif - case GDBMemR: val = hex2i(&p); if (*p++ != ',') { @@ -802,7 +786,7 @@ BaseRemoteGDB::trap(int type) continue; } - if (read(val, (size_t)len, (char *)buffer)) { + if (read(val, (size_t)len, buffer)) { // variable length array would be nice, but C++ doesn't // officially support those... char *temp = new char[2*len+1]; @@ -838,7 +822,7 @@ BaseRemoteGDB::trap(int type) send("E0A"); continue; } - if (write(val, (size_t)len, (char *)buffer)) + if (write(val, (size_t)len, buffer)) send("OK"); else send("E0B"); @@ -1025,10 +1009,10 @@ BaseRemoteGDB::i2digit(int n) // Convert a byte array into an hex string. void -BaseRemoteGDB::mem2hex(void *vdst, const void *vsrc, int len) +BaseRemoteGDB::mem2hex(char *vdst, const char *vsrc, int len) { - char *dst = (char *)vdst; - const char *src = (const char *)vsrc; + char *dst = vdst; + const char *src = vsrc; while (len--) { *dst++ = i2digit(*src >> 4); @@ -1042,9 +1026,9 @@ BaseRemoteGDB::mem2hex(void *vdst, const void *vsrc, int len) // hex digit. If the string ends in the middle of a byte, NULL is // returned. const char * -BaseRemoteGDB::hex2mem(void *vdst, const char *src, int maxlen) +BaseRemoteGDB::hex2mem(char *vdst, const char *src, int maxlen) { - char *dst = (char *)vdst; + char *dst = vdst; int msb, lsb; while (*src && maxlen--) { diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh index 6cca485e3..2ab7a84dd 100644 --- a/src/base/remote_gdb.hh +++ b/src/base/remote_gdb.hh @@ -1,4 +1,5 @@ /* + * Copyright 2015 LabWare * Copyright 2014 Google, Inc. * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. @@ -27,6 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert + * Boris Shingarov */ #ifndef __REMOTE_GDB_HH__ @@ -99,8 +101,8 @@ class BaseRemoteGDB //Address formats, break types, and gdb commands may change //between architectures, so they're defined as virtual //functions. - virtual void mem2hex(void *, const void *, int); - virtual const char * hex2mem(void *, const char *, int); + virtual void mem2hex(char *, const char *, int); + virtual const char * hex2mem(char *, const char *, int); virtual const char * break_type(char c); virtual const char * gdb_command(char cmd); @@ -150,32 +152,56 @@ class BaseRemoteGDB ThreadContext *context; protected: - class GdbRegCache + /** + * Concrete subclasses of this abstract class represent how the + * register values are transmitted on the wire. Usually each + * architecture should define one subclass, but there can be more + * if there is more than one possible wire format. For example, + * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache. + */ + class BaseGdbRegCache { public: - GdbRegCache(size_t newSize) : - regs64(new uint64_t[divCeil(newSize, sizeof(uint64_t))]), - size(newSize) + + /** + * Return the pointer to the raw bytes buffer containing the + * register values. Each byte of this buffer is literally + * encoded as two hex digits in the g or G RSP packet. + */ + virtual char *data() const = 0; + + /** + * Return the size of the raw buffer, in bytes + * (i.e., half of the number of digits in the g/G packet). + */ + virtual size_t size() const = 0; + + /** + * Fill the raw buffer from the registers in the ThreadContext. + */ + virtual void getRegs(ThreadContext*) = 0; + + /** + * Set the ThreadContext's registers from the values + * in the raw buffer. + */ + virtual void setRegs(ThreadContext*) const = 0; + + /** + * Return the name to use in places like DPRINTF. + * Having each concrete superclass redefine this member + * is useful in situations where the class of the regCache + * can change on the fly. + */ + virtual const std::string name() const = 0; + + BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g) {} - ~GdbRegCache() - { - delete [] regs64; - } - union { - uint64_t *regs64; - uint32_t *regs32; - uint16_t *regs16; - uint8_t *regs8; - void *regs; - }; - // Size of cache in bytes. - size_t size; - size_t bytes() { return size; } + protected: + BaseRemoteGDB *gdb; }; - GdbRegCache gdbregs; - protected: uint8_t getbyte(); void putbyte(uint8_t b); @@ -192,8 +218,9 @@ class BaseRemoteGDB template void write(Addr addr, T data); public: - BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize); + BaseRemoteGDB(System *system, ThreadContext *context); virtual ~BaseRemoteGDB(); + virtual BaseGdbRegCache *gdbRegs() = 0; void replaceThreadContext(ThreadContext *tc) { context = tc; } @@ -223,9 +250,6 @@ class BaseRemoteGDB SingleStepEvent singleStepEvent; - virtual void getregs() = 0; - virtual void setregs() = 0; - void clearSingleStep(); void setSingleStep();