summaryrefslogtreecommitdiff
path: root/src/base
diff options
context:
space:
mode:
Diffstat (limited to 'src/base')
-rw-r--r--src/base/remote_gdb.cc60
-rw-r--r--src/base/remote_gdb.hh78
2 files changed, 73 insertions, 65 deletions
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();