diff options
Diffstat (limited to 'src/base')
-rw-r--r-- | src/base/remote_gdb.cc | 60 | ||||
-rw-r--r-- | src/base/remote_gdb.hh | 78 |
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(); |