mirror of https://github.com/mgba-emu/mgba.git
Breakpoint clearing
This commit is contained in:
parent
ea6b129509
commit
c30807117f
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue