summaryrefslogtreecommitdiff
path: root/src/arch/x86/remote_gdb.cc
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2014-12-05 22:36:16 -0800
committerGabe Black <gabeblack@google.com>2014-12-05 22:36:16 -0800
commitfb07d43b1a4a903fb2e51b41685eb5814d9f9e11 (patch)
tree0e44d7e5bc796da39ce7cb4ecb908e787adba978 /src/arch/x86/remote_gdb.cc
parent16c9b41616312bfef0b5859f7cebe24e8c17d9da (diff)
downloadgem5-fb07d43b1a4a903fb2e51b41685eb5814d9f9e11.tar.xz
x86: Implement a remote GDB stub.
This stub should allow remote debugging of 32 bit and 64 bit targets. Single stepping seems to work, as do breakpoints. If both breakpoints and single stepping affect an instruction, gdb will stop at the instruction twice before continuing. That's a little surprising, but is generally harmless.
Diffstat (limited to 'src/arch/x86/remote_gdb.cc')
-rw-r--r--src/arch/x86/remote_gdb.cc188
1 files changed, 176 insertions, 12 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);
}