changeset e60c7758cf69 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=e60c7758cf69
description:
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:
src/arch/x86/remote_gdb.cc | 188 ++++++++++++++++++++++++++++++++++++++++++--
src/arch/x86/remote_gdb.hh | 102 ++++++++++++++++++++---
2 files changed, 263 insertions(+), 27 deletions(-)
diffs (truncated from 358 to 300 lines):
diff -r 910fc5624d68 -r e60c7758cf69 src/arch/x86/remote_gdb.cc
--- a/src/arch/x86/remote_gdb.cc Fri Dec 05 22:35:47 2014 -0800
+++ b/src/arch/x86/remote_gdb.cc Fri Dec 05 22:36:16 2014 -0800
@@ -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::getregs()
+void
+RemoteGDB::SingleStepEvent::process()
{
- panic("Remote gdb getregs not implemented in x86!\n");
+ if (!gdb->singleStepEvent.scheduled())
+ gdb->scheduleInstCommitEvent(&gdb->singleStepEvent, 1);
+ gdb->trap(SIGTRAP);
}
-void RemoteGDB::setregs()
+void
+RemoteGDB::getregs()
{
- panic("Remote gdb setregs 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::clearSingleStep()
+void
+RemoteGDB::setregs()
{
- panic("Remote gdb clearSingleStep 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::setSingleStep()
+void
+RemoteGDB::clearSingleStep()
{
- panic("Remoge gdb setSingleStep not implemented in x86!\n");
+ descheduleInstCommitEvent(&singleStepEvent);
}
+
+void
+RemoteGDB::setSingleStep()
+{
+ if (!singleStepEvent.scheduled())
+ scheduleInstCommitEvent(&singleStepEvent, 1);
+}
diff -r 910fc5624d68 -r e60c7758cf69 src/arch/x86/remote_gdb.hh
--- a/src/arch/x86/remote_gdb.hh Fri Dec 05 22:35:47 2014 -0800
+++ b/src/arch/x86/remote_gdb.hh Fri Dec 05 22:36:16 2014 -0800
@@ -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 @@
namespace X86ISA
{
- class RemoteGDB : public BaseRemoteGDB
+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,
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev