Merge remote-tracking branch 'github/pr/297'
Jeffrey Pfau jeffrey@endrift.com
Thu, 21 Jul 2016 22:09:15 -0700
2 files changed,
119 insertions(+),
2 deletions(-)
M
src/debugger/gdb-stub.c
→
src/debugger/gdb-stub.c
@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gdb-stub.h" #include "core/core.h" +#include "gba/memory.h" #include <signal.h>@@ -149,7 +150,7 @@
static uint32_t _readHex(const char* in, unsigned* out) { unsigned i; for (i = 0; i < 8; ++i) { - if (in[i] == ',') { + if (in[i] == ',' || in[i] == ':' || in[i] == '=') { break; } }@@ -210,6 +211,65 @@ // TODO: parse message
UNUSED(message); } +static void _writeMemoryBinary(struct GDBStub* stub, const char* message) { + const char* readAddress = message; + unsigned i = 0; + uint32_t address = _readHex(readAddress, &i); + readAddress += i + 1; + + i = 0; + uint32_t size = _readHex(readAddress, &i); + readAddress += i + 1; + + if (size > 512) { + _error(stub, GDB_BAD_ARGUMENTS); + return; + } + + struct ARMCore* cpu = stub->d.core->cpu; + for (i = 0; i < size; i++) { + uint8_t byte = *readAddress; + ++readAddress; + + // Parse escape char + if (byte == 0x7D) { + byte = *readAddress ^ 0x20; + ++readAddress; + } + + GBAPatch8(cpu, address + i, byte, 0); + } + + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); +} + + +static void _writeMemory(struct GDBStub* stub, const char* message) { + const char* readAddress = message; + unsigned i = 0; + uint32_t address = _readHex(readAddress, &i); + readAddress += i + 1; + + i = 0; + uint32_t size = _readHex(readAddress, &i); + readAddress += i + 1; + + if (size > 512) { + _error(stub, GDB_BAD_ARGUMENTS); + return; + } + + struct ARMCore* cpu = stub->d.core->cpu; + for (i = 0; i < size; ++i, readAddress += 2) { + uint8_t byte = _hex2int(readAddress, 2); + GBAPatch8(cpu, address + i, byte, 0); + } + + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); +} + static void _readMemory(struct GDBStub* stub, const char* message) { const char* readAddress = message; unsigned i = 0;@@ -230,6 +290,20 @@ stub->outgoing[writeAddress] = 0;
_sendMessage(stub); } +static void _writeGPRs(struct GDBStub* stub, const char* message) { + struct ARMCore* cpu = stub->d.core->cpu; + const char* readAddress = message; + + int r; + for (r = 0; r < 16; ++r) { + cpu->gprs[r] = _hex2int(readAddress, 8); + readAddress += 8; + } + + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); +} + static void _readGPRs(struct GDBStub* stub, const char* message) { struct ARMCore* cpu = stub->d.core->cpu; UNUSED(message);@@ -243,6 +317,36 @@ stub->outgoing[i] = 0;
_sendMessage(stub); } +static void _writeRegister(struct GDBStub* stub, const char* message) { + struct ARMCore* cpu = stub->d.core->cpu; + const char* readAddress = message; + + unsigned i = 0; + uint32_t reg = _readHex(readAddress, &i); + readAddress += i + 1; + + uint32_t value = _readHex(readAddress, &i); + +#ifdef _MSC_VER + value = _byteswap_ulong(value); +#else + value = __builtin_bswap32(value); +#endif + + if (reg < 0x10) { + cpu->gprs[reg] = value; + } else if (reg == 0x19) { + cpu->cpsr.packed = value; + } else { + stub->outgoing[0] = '\0'; + _sendMessage(stub); + return; + } + + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); +} + static void _readRegister(struct GDBStub* stub, const char* message) { struct ARMCore* cpu = stub->d.core->cpu; const char* readAddress = message;@@ -388,7 +492,7 @@ }
int i; char messageType = message[0]; - for (i = 0; message[i] && message[i] != '#'; ++i, ++parsed) { + for (i = 0; message[i] != '#'; ++i, ++parsed) { checksum += message[i]; } if (!message[i]) {@@ -423,6 +527,9 @@ break;
case 'c': _continue(stub, message); break; + case 'G': + _writeGPRs(stub, message); + break; case 'g': _readGPRs(stub, message); break;@@ -431,8 +538,14 @@ // This is faked because we only have one thread
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; + case 'M': + _writeMemory(stub, message); + break; case 'm': _readMemory(stub, message); + break; + case 'P': + _writeRegister(stub, message); break; case 'p': _readRegister(stub, message);@@ -452,6 +565,9 @@ break;
case 'v': _processVReadCommand(stub, message); break; + case 'X': + _writeMemoryBinary(stub, message); + break; case 'Z': _setBreakpoint(stub, message); break;