diff -r 021524c21cbc -r d0adbd5e6eba src/arch/arm/remote_gdb.cc --- a/src/arch/arm/remote_gdb.cc Sun Nov 22 05:10:21 2015 -0500 +++ b/src/arch/arm/remote_gdb.cc Mon Nov 23 15:57:43 2015 -0500 @@ -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 ArmISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc) - : BaseRemoteGDB(_system, tc, GDB_REG_BYTES) + : BaseRemoteGDB(_system, tc) { } @@ -192,127 +194,103 @@ } } -/* - * 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"); + 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); - memset(gdbregs.regs, 0, gdbregs.bytes()); - - 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) { + 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); - 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 < 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]); + } +} - //CPSR - context->setMiscRegNoEffect(MISCREG_CPSR, gdbregs.regs32[GDB32_CPSR]); +void +RemoteGDB::AArch32GdbRegCache::getRegs(ThreadContext *context) +{ + 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(); - //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]); + // One day somebody will implement transfer of FPRs correctly. + for (int i=0; i<8*3; i++) r.fpr[i] = 0; - //FPSCR - context->setMiscReg(MISCREG_FPSCR, gdbregs.regs32[GDB32_FPSCR]); - } + r.fpscr = context->readMiscRegNoEffect(MISCREG_FPSCR); + r.cpsr = context->readMiscRegNoEffect(MISCREG_CPSR); +} + +void +RemoteGDB::AArch32GdbRegCache::setRegs(ThreadContext *context) +{ + 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(); + else + return new AArch32GdbRegCache(); } // Write bytes to kernel address space for debugger. diff -r 021524c21cbc -r d0adbd5e6eba src/base/remote_gdb.hh --- a/src/base/remote_gdb.hh Sun Nov 22 05:10:21 2015 -0500 +++ b/src/base/remote_gdb.hh Mon Nov 23 15:57:43 2015 -0500 @@ -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__ @@ -150,32 +152,42 @@ 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) - {} - ~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; } + /** + * 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 void *data() = 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 bytes() = 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*) = 0; }; - GdbRegCache gdbregs; - protected: uint8_t getbyte(); void putbyte(uint8_t b); @@ -192,8 +204,9 @@ 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,8 +236,8 @@ SingleStepEvent singleStepEvent; - virtual void getregs() = 0; - virtual void setregs() = 0; + void getRegs(); + void setRegs(); void clearSingleStep(); void setSingleStep(); diff -r 021524c21cbc -r d0adbd5e6eba src/base/remote_gdb.cc --- a/src/base/remote_gdb.cc Sun Nov 22 05:10:21 2015 -0500 +++ b/src/base/remote_gdb.cc Mon Nov 23 15:57:43 2015 -0500 @@ -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 @@ 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() @@ -500,6 +501,30 @@ return true; } +/* + * Translate the GDB register format into the kernel debugger register + * format. + */ +void +BaseRemoteGDB::setRegs() +{ + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + unique_ptr cache(gdbRegs()); + cache->setRegs(context); +} + +/* + * Translate the kernel debugger register format into the GDB register + * format. + */ +void +BaseRemoteGDB::getRegs() +{ + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + unique_ptr cache(gdbRegs()); + cache->getRegs(context); +} + // Write bytes to kernel address space for debugger. bool BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) @@ -700,7 +725,7 @@ if (!attached) return false; - bufferSize = gdbregs.bytes() * 2 + 256; + bufferSize = gdbRegs()->bytes() * 2 + 256; buffer = (char*)malloc(bufferSize); DPRINTF(GDBMisc, "trap: PC=%s\n", context->pcState()); @@ -726,7 +751,7 @@ } // Stick frame regs into our reg cache. - getregs(); + getRegs(); for (;;) { datalen = recv(data, sizeof(data)); @@ -746,42 +771,23 @@ continue; case GDBRegR: - if (2 * gdbregs.bytes() > bufferSize) + if (2 * gdbRegs()->bytes() > bufferSize) panic("buffer too small"); - mem2hex(buffer, gdbregs.regs, gdbregs.bytes()); + mem2hex(buffer, gdbRegs()->data(), gdbRegs()->bytes()); send(buffer); continue; case GDBRegW: - p = hex2mem(gdbregs.regs, p, gdbregs.bytes()); + p = hex2mem(gdbRegs()->data(), p, gdbRegs()->bytes()); if (p == NULL || *p != '\0') send("E01"); else { - setregs(); + setRegs(); 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++ != ',') { diff -r 021524c21cbc -r d0adbd5e6eba src/arch/arm/remote_gdb.hh --- a/src/arch/arm/remote_gdb.hh Sun Nov 22 05:10:21 2015 -0500 +++ b/src/arch/arm/remote_gdb.hh Mon Nov 23 15:57:43 2015 -0500 @@ -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,48 @@ 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 + { + private: + struct { + uint32_t gpr[16]; + uint32_t fpr[8*3]; + uint32_t fpscr; + uint32_t cpsr; + } r; + public: + void *data() { return (void*)&r; } + size_t bytes() { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*); + }; + + class AArch64GdbRegCache : public BaseGdbRegCache + { + private: + struct { + uint64_t x[31]; + uint64_t spx; + uint64_t pc; + uint64_t cpsr; + uint32_t v[32*4]; + } r; + public: + void *data() { return (void*)&r; } + size_t bytes() { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*); + }; public: RemoteGDB(System *_system, ThreadContext *tc); + BaseGdbRegCache *gdbRegs(); }; } // namespace ArmISA