Breakpoint clearing

This commit is contained in:
Jeffrey Pfau 2014-02-01 15:37:15 -08:00
parent ea6b129509
commit c30807117f
3 changed files with 57 additions and 35 deletions

View File

@ -16,7 +16,7 @@ static void _checkBreakpoints(struct ARMDebugger* debugger) {
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;
}
@ -86,6 +86,17 @@ void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
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) {
if (debugger->cpu->memory != &debugger->memoryShim.d) {
ARMDebuggerInstallMemoryShim(debugger);

View File

@ -12,7 +12,7 @@ enum DebuggerState {
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

View File

@ -115,6 +115,17 @@ static void _int2hex32(uint32_t value, char* out) {
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 _continue(struct GDBStub* stub, const char* message) {
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 _readGPRs(struct GDBStub* stub, const char* message) {
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,19 +276,10 @@ static void _setBreakpoint(struct GDBStub* stub, const char* message) {
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);
@ -306,6 +293,26 @@ static void _setBreakpoint(struct GDBStub* stub, const char* message) {
}
}
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;
}
case '2':
case '3':
// TODO: Watchpoints
default:
break;
}
}
size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
uint8_t checksum = 0;
int parsed = 1;
@ -394,6 +401,9 @@ size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
case 'Z':
_setBreakpoint(stub, message);
break;
case 'z':
_clearBreakpoint(stub, message);
break;
default:
_error(stub, GDB_UNSUPPORTED_COMMAND);
break;