diff options
-rw-r--r-- | src/arch/x86/remote_gdb.cc | 188 | ||||
-rw-r--r-- | src/arch/x86/remote_gdb.hh | 102 |
2 files changed, 263 insertions, 27 deletions
diff --git a/src/arch/x86/remote_gdb.cc b/src/arch/x86/remote_gdb.cc index c7bce59bf..b30bf5739 100644 --- a/src/arch/x86/remote_gdb.cc +++ b/src/arch/x86/remote_gdb.cc @@ -1,4 +1,5 @@ /* + * Copyright 2014 Google, Inc. * Copyright (c) 2007 The Hewlett-Packard Development Company * All rights reserved. * @@ -42,41 +43,204 @@ #include <string> +#include "arch/x86/regs/int.hh" +#include "arch/x86/regs/misc.hh" +#include "arch/x86/pagetable_walker.hh" +#include "arch/x86/process.hh" #include "arch/x86/remote_gdb.hh" #include "arch/vtophys.hh" #include "base/remote_gdb.hh" #include "base/socket.hh" #include "base/trace.hh" +#include "cpu/base.hh" #include "cpu/thread_context.hh" +#include "mem/page_table.hh" +#include "sim/full_system.hh" using namespace std; using namespace X86ISA; -RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) - : BaseRemoteGDB(_system, c, NumGDBRegs) +RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) : + BaseRemoteGDB(_system, c, GDB_REG_BYTES), singleStepEvent(this) {} -bool RemoteGDB::acc(Addr va, size_t len) +bool +RemoteGDB::acc(Addr va, size_t len) { - panic("Remote gdb acc not implemented in x86!\n"); + if (FullSystem) { + Walker *walker = context->getDTBPtr()->getWalker(); + unsigned logBytes; + Fault fault = walker->startFunctional(context, va, logBytes, + BaseTLB::Read); + if (fault != NoFault) + return false; + + Addr endVa = va + len - 1; + if ((va & ~mask(logBytes)) == (endVa & ~mask(logBytes))) + return true; + + fault = walker->startFunctional(context, endVa, logBytes, + BaseTLB::Read); + return fault == NoFault; + } else { + TlbEntry entry; + return context->getProcessPtr()->pTable->lookup(va, entry); + } +} + +void +RemoteGDB::SingleStepEvent::process() +{ + if (!gdb->singleStepEvent.scheduled()) + gdb->scheduleInstCommitEvent(&gdb->singleStepEvent, 1); + gdb->trap(SIGTRAP); } -void RemoteGDB::getregs() +void +RemoteGDB::getregs() { - panic("Remote gdb getregs not implemented in x86!\n"); + 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); + } } -void RemoteGDB::setregs() +void +RemoteGDB::setregs() { - panic("Remote gdb setregs not implemented in x86!\n"); + 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"); + } + } } -void RemoteGDB::clearSingleStep() +void +RemoteGDB::clearSingleStep() { - panic("Remote gdb clearSingleStep not implemented in x86!\n"); + descheduleInstCommitEvent(&singleStepEvent); } -void RemoteGDB::setSingleStep() +void +RemoteGDB::setSingleStep() { - panic("Remoge gdb setSingleStep not implemented in x86!\n"); + if (!singleStepEvent.scheduled()) + scheduleInstCommitEvent(&singleStepEvent, 1); } diff --git a/src/arch/x86/remote_gdb.hh b/src/arch/x86/remote_gdb.hh index f8b15a818..b654fc2f8 100644 --- a/src/arch/x86/remote_gdb.hh +++ b/src/arch/x86/remote_gdb.hh @@ -1,4 +1,5 @@ /* + * Copyright 2014 Google, Inc. * Copyright (c) 2007 The Hewlett-Packard Development Company * All rights reserved. * @@ -40,6 +41,8 @@ #ifndef __ARCH_X86_REMOTEGDB_HH__ #define __ARCH_X86_REMOTEGDB_HH__ +#include <algorithm> + #include "arch/x86/types.hh" #include "base/remote_gdb.hh" @@ -48,29 +51,98 @@ class ThreadContext; namespace X86ISA { - class RemoteGDB : public BaseRemoteGDB +class RemoteGDB : public BaseRemoteGDB +{ + public: + enum { - protected: - enum RegisterContants - { - NumGDBRegs - //XXX fill this in - }; + 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, - public: - RemoteGDB(System *system, ThreadContext *context); + 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 + }; - bool acc(Addr addr, size_t len); + RemoteGDB(System *system, ThreadContext *context); + bool acc(Addr addr, size_t len); + + protected: + class SingleStepEvent : public Event + { protected: - void getregs(); - void setregs(); + RemoteGDB *gdb; - void clearSingleStep(); - void setSingleStep(); + public: + SingleStepEvent(RemoteGDB *g) : gdb(g) + {} - Addr nextBkpt; + void process(); }; + + SingleStepEvent singleStepEvent; + + void getregs(); + void setregs(); + + void clearSingleStep(); + void setSingleStep(); + + bool checkBpLen(size_t len) { return len == 1; } +}; + +const int GDB_REG_BYTES = + std::max(RemoteGDB::GDB32_NUMREGS * sizeof(uint32_t), + RemoteGDB::GDB64_NUMREGS * sizeof(uint64_t)); + } #endif // __ARCH_X86_REMOTEGDB_HH__ |