summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/alpha/kgdb.h163
-rw-r--r--src/arch/alpha/remote_gdb.cc58
-rw-r--r--src/arch/alpha/remote_gdb.hh25
-rw-r--r--src/arch/arm/remote_gdb.cc200
-rw-r--r--src/arch/arm/remote_gdb.hh67
-rw-r--r--src/arch/mips/remote_gdb.cc87
-rw-r--r--src/arch/mips/remote_gdb.hh50
-rw-r--r--src/arch/power/remote_gdb.cc72
-rw-r--r--src/arch/power/remote_gdb.hh50
-rw-r--r--src/arch/sparc/remote_gdb.cc115
-rw-r--r--src/arch/sparc/remote_gdb.hh69
-rw-r--r--src/arch/x86/remote_gdb.cc253
-rw-r--r--src/arch/x86/remote_gdb.hh141
-rw-r--r--src/base/remote_gdb.cc60
-rw-r--r--src/base/remote_gdb.hh78
15 files changed, 684 insertions, 804 deletions
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 <map>
-#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();
+ 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);
+ }
+}
- // CPSR
- gdbregs.regs32[GDB32_CPSR] = context->readMiscRegNoEffect(MISCREG_CPSR);
+void
+RemoteGDB::AArch64GdbRegCache::setRegs(ThreadContext *context) const
+{
+ DPRINTF(GDBAcc, "setRegs in remotegdb \n");
- // 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);
+ 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);
- // FPSCR
- gdbregs.regs32[GDB32_FPSCR] =
- context->readMiscRegNoEffect(MISCREG_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]);
}
}
-/*
- * Translate the GDB register format into the kernel debugger register
- * format.
- */
void
-RemoteGDB::setregs()
+RemoteGDB::AArch32GdbRegCache::getRegs(ThreadContext *context)
{
+ DPRINTF(GDBAcc, "getRegs 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]);
+ 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();
- //CPSR
- context->setMiscRegNoEffect(MISCREG_CPSR, gdbregs.regs32[GDB32_CPSR]);
+ // One day somebody will implement transfer of FPRs correctly.
+ for (int i=0; i<8*3; i++) r.fpr[i] = 0;
- //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]);
- }
+ r.fpscr = context->readMiscRegNoEffect(MISCREG_FPSCR);
+ r.cpsr = context->readMiscRegNoEffect(MISCREG_CPSR);
}
-// Write bytes to kernel address space for debugger.
-bool
-RemoteGDB::write(Addr vaddr, size_t size, const char *data)
+void
+RemoteGDB::AArch32GdbRegCache::setRegs(ThreadContext *context) const
{
- return BaseRemoteGDB::write(vaddr, size, data);
+ 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 <algorithm>
+#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;
-
- const int GdbIntRegs = GdbIntArchRegs + GdbIntSpecialRegs;
- const int GdbFloatRegs = GdbFloatArchRegs + GdbFloatSpecialRegs;
- const int GdbNumRegs = GdbIntRegs + GdbFloatRegs;
+class RemoteGDB : public BaseRemoteGDB
+{
+ protected:
+ bool acc(Addr addr, size_t len);
- 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);
+ 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"; }
+ };
- protected:
- bool acc(Addr addr, size_t len);
- void getregs();
- void setregs();
- };
-}
+ 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);
-
- // 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.fpr[i] = context->readFloatRegBits(i);
+
+ 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 <map>
-#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"; }
};
- public:
- RemoteGDB(System *system, ThreadContext *context);
-
- bool acc(Addr addr, size_t len);
+ 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"; }
+ };
- protected:
- void getregs();
- void setregs();
+ public:
+ 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 <sys/signal.h>
@@ -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::setregs()
+RemoteGDB::AMD64GdbRegCache::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.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::X86GdbRegCache::getRegs(ThreadContext *context)
+{
+ 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
+ protected:
+ bool acc(Addr addr, size_t len);
+ bool checkBpLen(size_t len) { return len == 1; }
+ class X86GdbRegCache : public BaseGdbRegCache
{
- 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
+ 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"; }
};
- enum
+ class AMD64GdbRegCache : public BaseGdbRegCache
{
- 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
+ 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);
-
- bool acc(Addr addr, size_t len);
-
- protected:
- void getregs();
- void setregs();
-
- bool checkBpLen(size_t len) { return len == 1; }
+ 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<BaseRemoteGDB::BaseGdbRegCache> 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,31 +152,55 @@ 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; }
- };
- GdbRegCache gdbregs;
+ protected:
+ BaseRemoteGDB *gdb;
+ };
protected:
uint8_t getbyte();
@@ -192,8 +218,9 @@ class BaseRemoteGDB
template <class T> 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();