static void _setBreakpoint(struct GDBStub* stub, const char* message) { const char* readAddress = &message[2]; unsigned i = 0; uint32_t address = _readHex(readAddress, &i); readAddress += i + 1; uint32_t kind = _readHex(readAddress, &i); switch (message[0]) { case '0': ARMDebuggerSetSoftwareBreakpoint(stub->d.platform, address, kind == 2 ? MODE_THUMB : MODE_ARM); break; case '1': stub->d.platform->setBreakpoint(stub->d.platform, address); break; case '2': stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_WRITE); break; case '3': stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_READ); break; case '4': stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_RW); break; default: stub->outgoing[0] = '\0'; _sendMessage(stub); return; } strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); }
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 _readMemory(struct GDBStub* stub, const char* message) { const char* readAddress = message; unsigned i = 0; uint32_t address = _readHex(readAddress, &i); readAddress += i + 1; uint32_t size = _readHex(readAddress, &i); if (size > 512) { _error(stub, GDB_BAD_ARGUMENTS); return; } struct ARMCore* cpu = stub->d.core->cpu; int writeAddress = 0; for (i = 0; i < size; ++i, writeAddress += 2) { uint8_t byte = cpu->memory.load8(cpu, address + i, 0); _int2hex8(byte, &stub->outgoing[writeAddress]); } stub->outgoing[writeAddress] = 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 <= ARM_PC) { cpu->gprs[reg] = value; if (reg == ARM_PC) { int32_t currentCycles = 0; if (cpu->executionMode == MODE_ARM) { ARM_WRITE_PC; } else { THUMB_WRITE_PC; } } } 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 _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 _setBreakpoint(struct GDBStub* stub, const char* message) { const char* readAddress = &message[2]; unsigned i = 0; uint32_t address = _readHex(readAddress, &i); readAddress += i + 1; uint32_t kind = _readHex(readAddress, &i); // We don't use this in hardware watchpoints UNUSED(kind); switch (message[0]) { case '0': // Memory breakpoints are not currently supported case '1': stub->d.platform->setBreakpoint(stub->d.platform, address); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; case '2': stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_WRITE); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; case '3': stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_READ); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; case '4': stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_RW); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; default: stub->outgoing[0] = '\0'; _sendMessage(stub); break; } }
static void _readRegister(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); uint32_t value; if (reg < 0x10) { value = cpu->gprs[reg]; } else if (reg == 0x19) { value = cpu->cpsr.packed; } else { stub->outgoing[0] = '\0'; _sendMessage(stub); return; } _int2hex32(value, stub->outgoing); stub->outgoing[8] = '\0'; _sendMessage(stub); }
static void _clearBreakpoint(struct GDBStub* stub, const char* message) { const char* readAddress = &message[2]; unsigned i = 0; uint32_t address = _readHex(readAddress, &i); switch (message[0]) { case '0': // Memory breakpoints are not currently supported case '1': stub->d.platform->clearBreakpoint(stub->d.platform, address); break; case '2': case '3': case '4': stub->d.platform->clearWatchpoint(stub->d.platform, address); break; default: break; } strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); }