Breakpoint clearing
Jeffrey Pfau jeffrey@endrift.com
Sat, 01 Feb 2014 15:37:15 -0800
3 files changed,
57 insertions(+),
35 deletions(-)
M
src/debugger/debugger.c
→
src/debugger/debugger.c
@@ -16,7 +16,7 @@ } else {
instructionLength = WORD_SIZE_THUMB; } for (breakpoint = debugger->breakpoints; breakpoint; breakpoint = breakpoint->next) { - if (breakpoint->address + instructionLength == debugger->cpu->gprs[ARM_PC]) { + if (breakpoint->address + instructionLength == (uint32_t) debugger->cpu->gprs[ARM_PC]) { ARMDebuggerEnter(debugger, DEBUGGER_ENTER_BREAKPOINT); break; }@@ -84,6 +84,17 @@ struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
breakpoint->address = address; breakpoint->next = debugger->breakpoints; debugger->breakpoints = breakpoint; +} + +void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) { + struct DebugBreakpoint** previous = &debugger->breakpoints; + struct DebugBreakpoint* breakpoint; + for (; (breakpoint = *previous); previous = &breakpoint->next) { + if (breakpoint->address == address) { + *previous = breakpoint->next; + free(breakpoint); + } + } } void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
M
src/debugger/debugger.h
→
src/debugger/debugger.h
@@ -12,7 +12,7 @@ };
struct DebugBreakpoint { struct DebugBreakpoint* next; - int32_t address; + uint32_t address; }; struct DebugMemoryShim {@@ -49,6 +49,7 @@ void ARMDebuggerDeinit(struct ARMDebugger*);
void ARMDebuggerRun(struct ARMDebugger*); void ARMDebuggerEnter(struct ARMDebugger*, enum DebuggerEntryReason); void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address); +void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address); void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address); #endif
M
src/debugger/gdb-stub.c
→
src/debugger/gdb-stub.c
@@ -115,6 +115,17 @@ out[0] = language[(value >> 4) & 0xF];
out[1] = language[value & 0xF]; } +static uint32_t _readHex(const char* in, unsigned* out) { + unsigned i; + for (i = 0; i < 8; ++i) { + if (in[i] == ',') { + break; + } + } + *out += i; + return _hex2int(in, i); +} + static void _sendMessage(struct GDBStub* stub) { if (stub->lineAck != GDB_ACK_OFF) { stub->lineAck = GDB_ACK_PENDING;@@ -168,20 +179,10 @@ }
static void _readMemory(struct GDBStub* stub, const char* message) { const char* readAddress = message; - unsigned i; - for (i = 0; i < 8; ++i) { - if (readAddress[i] == ',') { - break; - } - } - uint32_t address = _hex2int(readAddress, i); + unsigned i = 0; + uint32_t address = _readHex(readAddress, &i); readAddress += i + 1; - for (i = 0; i < 8; ++i) { - if (readAddress[i] == '#') { - break; - } - } - uint32_t size = _hex2int(readAddress, i); + uint32_t size = _readHex(readAddress, &i); if (size > 512) { _error(stub, GDB_BAD_ARGUMENTS); return;@@ -210,13 +211,8 @@ }
static void _readRegister(struct GDBStub* stub, const char* message) { const char* readAddress = message; - unsigned i; - for (i = 0; i < 8; ++i) { - if (readAddress[i] == '#') { - break; - } - } - uint32_t reg = _hex2int(readAddress, i); + unsigned i = 0; + uint32_t reg = _readHex(readAddress, &i); uint32_t value; if (reg < 0x10) { value = stub->d.cpu->gprs[reg];@@ -280,20 +276,31 @@ switch (message[0]) {
case '0': // Memory breakpoints are not currently supported case '1': { const char* readAddress = &message[2]; - unsigned i; - for (i = 0; i < 8; ++i) { - if (readAddress[i] == ',') { - break; - } - } - uint32_t address = _hex2int(readAddress, i); - for (i = 0; i < 8; ++i) { - if (readAddress[i] == '#') { - break; - } - } - uint32_t kind = _hex2int(readAddress, i); // We don't use this in hardware watchpoints + 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 ARMDebuggerSetBreakpoint(&stub->d, address); + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); + break; + } + case '2': + case '3': + // TODO: Watchpoints + default: + break; + } +} + +static void _clearBreakpoint(struct GDBStub* stub, const char* message) { + switch (message[0]) { + case '0': // Memory breakpoints are not currently supported + case '1': { + const char* readAddress = &message[2]; + unsigned i = 0; + uint32_t address = _readHex(readAddress, &i); + ARMDebuggerClearBreakpoint(&stub->d, address); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break;@@ -393,6 +400,9 @@ _processVReadCommand(stub, message);
break; case 'Z': _setBreakpoint(stub, message); + break; + case 'z': + _clearBreakpoint(stub, message); break; default: _error(stub, GDB_UNSUPPORTED_COMMAND);