mirror of https://github.com/mgba-emu/mgba.git
Debugger: Begin refactoring ARMDebugger into Debugger
This commit is contained in:
parent
fbfbbbf279
commit
d86440e04f
|
@ -499,7 +499,7 @@ static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector*
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t address = dv->intValue;
|
uint32_t address = dv->intValue;
|
||||||
ARMDebuggerSetBreakpoint(&debugger->d, address);
|
DebuggerSetBreakpoint(&debugger->d, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||||
|
@ -508,7 +508,7 @@ static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVecto
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t address = dv->intValue;
|
uint32_t address = dv->intValue;
|
||||||
ARMDebuggerSetSoftwareBreakpoint(&debugger->d, address, MODE_ARM);
|
DebuggerSetSoftwareBreakpoint(&debugger->d, address, MODE_ARM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||||
|
@ -517,7 +517,7 @@ static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVec
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t address = dv->intValue;
|
uint32_t address = dv->intValue;
|
||||||
ARMDebuggerSetSoftwareBreakpoint(&debugger->d, address, MODE_THUMB);
|
DebuggerSetSoftwareBreakpoint(&debugger->d, address, MODE_THUMB);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||||
|
@ -526,8 +526,8 @@ static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t address = dv->intValue;
|
uint32_t address = dv->intValue;
|
||||||
ARMDebuggerClearBreakpoint(&debugger->d, address);
|
DebuggerClearBreakpoint(&debugger->d, address);
|
||||||
ARMDebuggerClearWatchpoint(&debugger->d, address);
|
DebuggerClearWatchpoint(&debugger->d, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||||
|
@ -536,12 +536,12 @@ static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector*
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t address = dv->intValue;
|
uint32_t address = dv->intValue;
|
||||||
ARMDebuggerSetWatchpoint(&debugger->d, address, WATCHPOINT_RW); // TODO: ro/wo
|
DebuggerSetWatchpoint(&debugger->d, address, WATCHPOINT_RW); // TODO: ro/wo
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _breakIntoDefault(int signal) {
|
static void _breakIntoDefault(int signal) {
|
||||||
UNUSED(signal);
|
UNUSED(signal);
|
||||||
ARMDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0);
|
DebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t _performOperation(enum Operation operation, uint32_t current, uint32_t next, struct CLIDebugVector* dv) {
|
static uint32_t _performOperation(enum Operation operation, uint32_t current, uint32_t next, struct CLIDebugVector* dv) {
|
||||||
|
@ -570,7 +570,7 @@ static uint32_t _performOperation(enum Operation operation, uint32_t current, ui
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t _lookupIdentifier(struct ARMDebugger* debugger, const char* name, struct CLIDebugVector* dv) {
|
static uint32_t _lookupIdentifier(struct Debugger* debugger, const char* name, struct CLIDebugVector* dv) {
|
||||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||||
if (strcmp(name, "sp") == 0) {
|
if (strcmp(name, "sp") == 0) {
|
||||||
return debugger->cpu->gprs[ARM_SP];
|
return debugger->cpu->gprs[ARM_SP];
|
||||||
|
@ -605,7 +605,7 @@ static uint32_t _lookupIdentifier(struct ARMDebugger* debugger, const char* name
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t _evaluateParseTree(struct ARMDebugger* debugger, struct ParseTree* tree, struct CLIDebugVector* dv) {
|
static uint32_t _evaluateParseTree(struct Debugger* debugger, struct ParseTree* tree, struct CLIDebugVector* dv) {
|
||||||
switch (tree->token.type) {
|
switch (tree->token.type) {
|
||||||
case TOKEN_UINT_TYPE:
|
case TOKEN_UINT_TYPE:
|
||||||
return tree->token.uintValue;
|
return tree->token.uintValue;
|
||||||
|
@ -765,7 +765,7 @@ static char* _prompt(EditLine* el) {
|
||||||
return "> ";
|
return "> ";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _commandLine(struct ARMDebugger* debugger) {
|
static void _commandLine(struct Debugger* debugger) {
|
||||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||||
const char* line;
|
const char* line;
|
||||||
_printStatus(cliDebugger, 0);
|
_printStatus(cliDebugger, 0);
|
||||||
|
@ -787,7 +787,7 @@ static void _commandLine(struct ARMDebugger* debugger) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _reportEntry(struct ARMDebugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) {
|
static void _reportEntry(struct Debugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) {
|
||||||
UNUSED(debugger);
|
UNUSED(debugger);
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case DEBUGGER_ENTER_MANUAL:
|
case DEBUGGER_ENTER_MANUAL:
|
||||||
|
@ -874,7 +874,7 @@ static unsigned char _tabComplete(EditLine* elstate, int ch) {
|
||||||
return CC_REDISPLAY;
|
return CC_REDISPLAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _cliDebuggerInit(struct ARMDebugger* debugger) {
|
static void _cliDebuggerInit(struct Debugger* debugger) {
|
||||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||||
// TODO: get argv[0]
|
// TODO: get argv[0]
|
||||||
cliDebugger->elstate = el_init(binaryName, stdin, stdout, stderr);
|
cliDebugger->elstate = el_init(binaryName, stdin, stdout, stderr);
|
||||||
|
@ -892,7 +892,7 @@ static void _cliDebuggerInit(struct ARMDebugger* debugger) {
|
||||||
signal(SIGINT, _breakIntoDefault);
|
signal(SIGINT, _breakIntoDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _cliDebuggerDeinit(struct ARMDebugger* debugger) {
|
static void _cliDebuggerDeinit(struct Debugger* debugger) {
|
||||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||||
history_end(cliDebugger->histate);
|
history_end(cliDebugger->histate);
|
||||||
el_end(cliDebugger->elstate);
|
el_end(cliDebugger->elstate);
|
||||||
|
@ -904,7 +904,7 @@ static void _cliDebuggerDeinit(struct ARMDebugger* debugger) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _cliDebuggerCustom(struct ARMDebugger* debugger) {
|
static void _cliDebuggerCustom(struct Debugger* debugger) {
|
||||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||||
bool retain = false;
|
bool retain = false;
|
||||||
if (cliDebugger->system) {
|
if (cliDebugger->system) {
|
||||||
|
@ -916,7 +916,7 @@ static void _cliDebuggerCustom(struct ARMDebugger* debugger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLIDebuggerCreate(struct CLIDebugger* debugger) {
|
void CLIDebuggerCreate(struct CLIDebugger* debugger) {
|
||||||
ARMDebuggerCreate(&debugger->d);
|
DebuggerCreate(&debugger->d);
|
||||||
debugger->d.init = _cliDebuggerInit;
|
debugger->d.init = _cliDebuggerInit;
|
||||||
debugger->d.deinit = _cliDebuggerDeinit;
|
debugger->d.deinit = _cliDebuggerDeinit;
|
||||||
debugger->d.custom = _cliDebuggerCustom;
|
debugger->d.custom = _cliDebuggerCustom;
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct CLIDebuggerSystem {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CLIDebugger {
|
struct CLIDebugger {
|
||||||
struct ARMDebugger d;
|
struct Debugger d;
|
||||||
|
|
||||||
struct CLIDebuggerSystem* system;
|
struct CLIDebuggerSystem* system;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#include "memory-debugger.h"
|
#include "memory-debugger.h"
|
||||||
|
|
||||||
const uint32_t ARM_DEBUGGER_ID = 0xDEADBEEF;
|
const uint32_t DEBUGGER_ID = 0xDEADBEEF;
|
||||||
|
|
||||||
DEFINE_VECTOR(DebugBreakpointList, struct DebugBreakpoint);
|
DEFINE_VECTOR(DebugBreakpointList, struct DebugBreakpoint);
|
||||||
DEFINE_VECTOR(DebugWatchpointList, struct DebugWatchpoint);
|
DEFINE_VECTOR(DebugWatchpointList, struct DebugWatchpoint);
|
||||||
|
@ -25,7 +25,7 @@ static struct DebugBreakpoint* _lookupBreakpoint(struct DebugBreakpointList* bre
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _checkBreakpoints(struct ARMDebugger* debugger) {
|
static void _checkBreakpoints(struct Debugger* debugger) {
|
||||||
int instructionLength;
|
int instructionLength;
|
||||||
enum ExecutionMode mode = debugger->cpu->cpsr.t;
|
enum ExecutionMode mode = debugger->cpu->cpsr.t;
|
||||||
if (mode == MODE_ARM) {
|
if (mode == MODE_ARM) {
|
||||||
|
@ -40,20 +40,20 @@ static void _checkBreakpoints(struct ARMDebugger* debugger) {
|
||||||
struct DebuggerEntryInfo info = {
|
struct DebuggerEntryInfo info = {
|
||||||
.address = breakpoint->address
|
.address = breakpoint->address
|
||||||
};
|
};
|
||||||
ARMDebuggerEnter(debugger, DEBUGGER_ENTER_BREAKPOINT, &info);
|
DebuggerEnter(debugger, DEBUGGER_ENTER_BREAKPOINT, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ARMDebuggerInit(void* cpu, struct mCPUComponent*);
|
static void DebuggerInit(void* cpu, struct mCPUComponent*);
|
||||||
static void ARMDebuggerDeinit(struct mCPUComponent*);
|
static void DebuggerDeinit(struct mCPUComponent*);
|
||||||
|
|
||||||
void ARMDebuggerCreate(struct ARMDebugger* debugger) {
|
void DebuggerCreate(struct Debugger* debugger) {
|
||||||
debugger->d.id = ARM_DEBUGGER_ID;
|
debugger->d.id = DEBUGGER_ID;
|
||||||
debugger->d.init = ARMDebuggerInit;
|
debugger->d.init = DebuggerInit;
|
||||||
debugger->d.deinit = ARMDebuggerDeinit;
|
debugger->d.deinit = DebuggerDeinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerInit(void* cpu, struct mCPUComponent* component) {
|
void DebuggerInit(void* cpu, struct mCPUComponent* component) {
|
||||||
struct ARMDebugger* debugger = (struct ARMDebugger*) component;
|
struct Debugger* debugger = (struct Debugger*) component;
|
||||||
debugger->cpu = cpu;
|
debugger->cpu = cpu;
|
||||||
debugger->state = DEBUGGER_RUNNING;
|
debugger->state = DEBUGGER_RUNNING;
|
||||||
debugger->originalMemory = debugger->cpu->memory;
|
debugger->originalMemory = debugger->cpu->memory;
|
||||||
|
@ -66,15 +66,15 @@ void ARMDebuggerInit(void* cpu, struct mCPUComponent* component) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerDeinit(struct mCPUComponent* component) {
|
void DebuggerDeinit(struct mCPUComponent* component) {
|
||||||
struct ARMDebugger* debugger = (struct ARMDebugger*) component;
|
struct Debugger* debugger = (struct Debugger*) component;
|
||||||
debugger->deinit(debugger);
|
debugger->deinit(debugger);
|
||||||
DebugBreakpointListDeinit(&debugger->breakpoints);
|
DebugBreakpointListDeinit(&debugger->breakpoints);
|
||||||
DebugBreakpointListDeinit(&debugger->swBreakpoints);
|
DebugBreakpointListDeinit(&debugger->swBreakpoints);
|
||||||
DebugWatchpointListDeinit(&debugger->watchpoints);
|
DebugWatchpointListDeinit(&debugger->watchpoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerRun(struct ARMDebugger* debugger) {
|
void DebuggerRun(struct Debugger* debugger) {
|
||||||
switch (debugger->state) {
|
switch (debugger->state) {
|
||||||
case DEBUGGER_RUNNING:
|
case DEBUGGER_RUNNING:
|
||||||
if (!DebugBreakpointListSize(&debugger->breakpoints) && !DebugWatchpointListSize(&debugger->watchpoints)) {
|
if (!DebugBreakpointListSize(&debugger->breakpoints) && !DebugWatchpointListSize(&debugger->watchpoints)) {
|
||||||
|
@ -107,7 +107,7 @@ void ARMDebuggerRun(struct ARMDebugger* debugger) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) {
|
void DebuggerEnter(struct Debugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) {
|
||||||
debugger->state = DEBUGGER_PAUSED;
|
debugger->state = DEBUGGER_PAUSED;
|
||||||
struct ARMCore* cpu = debugger->cpu;
|
struct ARMCore* cpu = debugger->cpu;
|
||||||
cpu->nextEvent = cpu->cycles;
|
cpu->nextEvent = cpu->cycles;
|
||||||
|
@ -128,13 +128,13 @@ void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason rea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
|
void DebuggerSetBreakpoint(struct Debugger* debugger, uint32_t address) {
|
||||||
struct DebugBreakpoint* breakpoint = DebugBreakpointListAppend(&debugger->breakpoints);
|
struct DebugBreakpoint* breakpoint = DebugBreakpointListAppend(&debugger->breakpoints);
|
||||||
breakpoint->address = address;
|
breakpoint->address = address;
|
||||||
breakpoint->isSw = false;
|
breakpoint->isSw = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
|
bool DebuggerSetSoftwareBreakpoint(struct Debugger* debugger, uint32_t address, enum ExecutionMode mode) {
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
if (!debugger->setSoftwareBreakpoint || !debugger->setSoftwareBreakpoint(debugger, address, mode, &opcode)) {
|
if (!debugger->setSoftwareBreakpoint || !debugger->setSoftwareBreakpoint(debugger, address, mode, &opcode)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -149,7 +149,7 @@ bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t add
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
|
void DebuggerClearBreakpoint(struct Debugger* debugger, uint32_t address) {
|
||||||
struct DebugBreakpointList* breakpoints = &debugger->breakpoints;
|
struct DebugBreakpointList* breakpoints = &debugger->breakpoints;
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < DebugBreakpointListSize(breakpoints); ++i) {
|
for (i = 0; i < DebugBreakpointListSize(breakpoints); ++i) {
|
||||||
|
@ -160,16 +160,16 @@ void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type) {
|
void DebuggerSetWatchpoint(struct Debugger* debugger, uint32_t address, enum WatchpointType type) {
|
||||||
if (!DebugWatchpointListSize(&debugger->watchpoints)) {
|
if (!DebugWatchpointListSize(&debugger->watchpoints)) {
|
||||||
ARMDebuggerInstallMemoryShim(debugger);
|
DebuggerInstallMemoryShim(debugger);
|
||||||
}
|
}
|
||||||
struct DebugWatchpoint* watchpoint = DebugWatchpointListAppend(&debugger->watchpoints);
|
struct DebugWatchpoint* watchpoint = DebugWatchpointListAppend(&debugger->watchpoints);
|
||||||
watchpoint->address = address;
|
watchpoint->address = address;
|
||||||
watchpoint->type = type;
|
watchpoint->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
|
void DebuggerClearWatchpoint(struct Debugger* debugger, uint32_t address) {
|
||||||
struct DebugWatchpointList* watchpoints = &debugger->watchpoints;
|
struct DebugWatchpointList* watchpoints = &debugger->watchpoints;
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < DebugWatchpointListSize(watchpoints); ++i) {
|
for (i = 0; i < DebugWatchpointListSize(watchpoints); ++i) {
|
||||||
|
@ -178,6 +178,6 @@ void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!DebugWatchpointListSize(&debugger->watchpoints)) {
|
if (!DebugWatchpointListSize(&debugger->watchpoints)) {
|
||||||
ARMDebuggerRemoveMemoryShim(debugger);
|
DebuggerRemoveMemoryShim(debugger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,18 @@
|
||||||
#include "arm/arm.h"
|
#include "arm/arm.h"
|
||||||
#include "util/vector.h"
|
#include "util/vector.h"
|
||||||
|
|
||||||
extern const uint32_t ARM_DEBUGGER_ID;
|
extern const uint32_t DEBUGGER_ID;
|
||||||
|
|
||||||
|
enum DebuggerType {
|
||||||
|
DEBUGGER_NONE = 0,
|
||||||
|
#ifdef USE_CLI_DEBUGGER
|
||||||
|
DEBUGGER_CLI,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_GDB_STUB
|
||||||
|
DEBUGGER_GDB,
|
||||||
|
#endif
|
||||||
|
DEBUGGER_MAX
|
||||||
|
};
|
||||||
|
|
||||||
enum DebuggerState {
|
enum DebuggerState {
|
||||||
DEBUGGER_PAUSED,
|
DEBUGGER_PAUSED,
|
||||||
|
@ -74,7 +85,7 @@ enum DebuggerLogLevel {
|
||||||
DEBUGGER_LOG_ERROR = 0x08
|
DEBUGGER_LOG_ERROR = 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ARMDebugger {
|
struct Debugger {
|
||||||
struct mCPUComponent d;
|
struct mCPUComponent d;
|
||||||
enum DebuggerState state;
|
enum DebuggerState state;
|
||||||
struct ARMCore* cpu;
|
struct ARMCore* cpu;
|
||||||
|
@ -86,26 +97,26 @@ struct ARMDebugger {
|
||||||
|
|
||||||
struct DebugBreakpoint* currentBreakpoint;
|
struct DebugBreakpoint* currentBreakpoint;
|
||||||
|
|
||||||
void (*init)(struct ARMDebugger*);
|
void (*init)(struct Debugger*);
|
||||||
void (*deinit)(struct ARMDebugger*);
|
void (*deinit)(struct Debugger*);
|
||||||
void (*paused)(struct ARMDebugger*);
|
void (*paused)(struct Debugger*);
|
||||||
void (*entered)(struct ARMDebugger*, enum DebuggerEntryReason, struct DebuggerEntryInfo*);
|
void (*entered)(struct Debugger*, enum DebuggerEntryReason, struct DebuggerEntryInfo*);
|
||||||
void (*custom)(struct ARMDebugger*);
|
void (*custom)(struct Debugger*);
|
||||||
|
|
||||||
bool (*setSoftwareBreakpoint)(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
|
bool (*setSoftwareBreakpoint)(struct Debugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
|
||||||
bool (*clearSoftwareBreakpoint)(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
|
bool (*clearSoftwareBreakpoint)(struct Debugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
|
||||||
|
|
||||||
ATTRIBUTE_FORMAT(printf, 3, 4)
|
ATTRIBUTE_FORMAT(printf, 3, 4)
|
||||||
void (*log)(struct ARMDebugger*, enum DebuggerLogLevel, const char* format, ...);
|
void (*log)(struct Debugger*, enum DebuggerLogLevel, const char* format, ...);
|
||||||
};
|
};
|
||||||
|
|
||||||
void ARMDebuggerCreate(struct ARMDebugger*);
|
void DebuggerCreate(struct Debugger*);
|
||||||
void ARMDebuggerRun(struct ARMDebugger*);
|
void DebuggerRun(struct Debugger*);
|
||||||
void ARMDebuggerEnter(struct ARMDebugger*, enum DebuggerEntryReason, struct DebuggerEntryInfo*);
|
void DebuggerEnter(struct Debugger*, enum DebuggerEntryReason, struct DebuggerEntryInfo*);
|
||||||
void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address);
|
void DebuggerSetBreakpoint(struct Debugger* debugger, uint32_t address);
|
||||||
bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode);
|
bool DebuggerSetSoftwareBreakpoint(struct Debugger* debugger, uint32_t address, enum ExecutionMode mode);
|
||||||
void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address);
|
void DebuggerClearBreakpoint(struct Debugger* debugger, uint32_t address);
|
||||||
void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type);
|
void DebuggerSetWatchpoint(struct Debugger* debugger, uint32_t address, enum WatchpointType type);
|
||||||
void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address);
|
void DebuggerClearWatchpoint(struct Debugger* debugger, uint32_t address);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,14 +26,14 @@ enum {
|
||||||
|
|
||||||
static void _sendMessage(struct GDBStub* stub);
|
static void _sendMessage(struct GDBStub* stub);
|
||||||
|
|
||||||
static void _gdbStubDeinit(struct ARMDebugger* debugger) {
|
static void _gdbStubDeinit(struct Debugger* debugger) {
|
||||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||||
if (!SOCKET_FAILED(stub->socket)) {
|
if (!SOCKET_FAILED(stub->socket)) {
|
||||||
GDBStubShutdown(stub);
|
GDBStubShutdown(stub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) {
|
static void _gdbStubEntered(struct Debugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) {
|
||||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case DEBUGGER_ENTER_MANUAL:
|
case DEBUGGER_ENTER_MANUAL:
|
||||||
|
@ -76,7 +76,7 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas
|
||||||
_sendMessage(stub);
|
_sendMessage(stub);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _gdbStubPoll(struct ARMDebugger* debugger) {
|
static void _gdbStubPoll(struct Debugger* debugger) {
|
||||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||||
--stub->untilPoll;
|
--stub->untilPoll;
|
||||||
if (stub->untilPoll > 0) {
|
if (stub->untilPoll > 0) {
|
||||||
|
@ -87,7 +87,7 @@ static void _gdbStubPoll(struct ARMDebugger* debugger) {
|
||||||
GDBStubUpdate(stub);
|
GDBStubUpdate(stub);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _gdbStubWait(struct ARMDebugger* debugger) {
|
static void _gdbStubWait(struct Debugger* debugger) {
|
||||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||||
stub->shouldBlock = true;
|
stub->shouldBlock = true;
|
||||||
GDBStubUpdate(stub);
|
GDBStubUpdate(stub);
|
||||||
|
@ -302,7 +302,7 @@ static void _processVReadCommand(struct GDBStub* stub, const char* message) {
|
||||||
stub->outgoing[0] = '\0';
|
stub->outgoing[0] = '\0';
|
||||||
if (!strncmp("Attach", message, 6)) {
|
if (!strncmp("Attach", message, 6)) {
|
||||||
strncpy(stub->outgoing, "1", GDB_STUB_MAX_LINE - 4);
|
strncpy(stub->outgoing, "1", GDB_STUB_MAX_LINE - 4);
|
||||||
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0);
|
DebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0);
|
||||||
}
|
}
|
||||||
_sendMessage(stub);
|
_sendMessage(stub);
|
||||||
}
|
}
|
||||||
|
@ -318,22 +318,22 @@ static void _setBreakpoint(struct GDBStub* stub, const char* message) {
|
||||||
switch (message[0]) {
|
switch (message[0]) {
|
||||||
case '0': // Memory breakpoints are not currently supported
|
case '0': // Memory breakpoints are not currently supported
|
||||||
case '1':
|
case '1':
|
||||||
ARMDebuggerSetBreakpoint(&stub->d, address);
|
DebuggerSetBreakpoint(&stub->d, address);
|
||||||
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
|
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
|
||||||
_sendMessage(stub);
|
_sendMessage(stub);
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_WRITE);
|
DebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_WRITE);
|
||||||
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
|
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
|
||||||
_sendMessage(stub);
|
_sendMessage(stub);
|
||||||
break;
|
break;
|
||||||
case '3':
|
case '3':
|
||||||
ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_READ);
|
DebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_READ);
|
||||||
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
|
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
|
||||||
_sendMessage(stub);
|
_sendMessage(stub);
|
||||||
break;
|
break;
|
||||||
case '4':
|
case '4':
|
||||||
ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_RW);
|
DebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_RW);
|
||||||
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
|
strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);
|
||||||
_sendMessage(stub);
|
_sendMessage(stub);
|
||||||
break;
|
break;
|
||||||
|
@ -351,12 +351,12 @@ static void _clearBreakpoint(struct GDBStub* stub, const char* message) {
|
||||||
switch (message[0]) {
|
switch (message[0]) {
|
||||||
case '0': // Memory breakpoints are not currently supported
|
case '0': // Memory breakpoints are not currently supported
|
||||||
case '1':
|
case '1':
|
||||||
ARMDebuggerClearBreakpoint(&stub->d, address);
|
DebuggerClearBreakpoint(&stub->d, address);
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
case '3':
|
case '3':
|
||||||
case '4':
|
case '4':
|
||||||
ARMDebuggerClearWatchpoint(&stub->d, address);
|
DebuggerClearWatchpoint(&stub->d, address);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -379,7 +379,7 @@ size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
|
||||||
++message;
|
++message;
|
||||||
break;
|
break;
|
||||||
case '\x03':
|
case '\x03':
|
||||||
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0);
|
DebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0);
|
||||||
return parsed;
|
return parsed;
|
||||||
default:
|
default:
|
||||||
_nak(stub);
|
_nak(stub);
|
||||||
|
@ -468,7 +468,7 @@ size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDBStubCreate(struct GDBStub* stub) {
|
void GDBStubCreate(struct GDBStub* stub) {
|
||||||
ARMDebuggerCreate(&stub->d);
|
DebuggerCreate(&stub->d);
|
||||||
stub->socket = INVALID_SOCKET;
|
stub->socket = INVALID_SOCKET;
|
||||||
stub->connection = INVALID_SOCKET;
|
stub->connection = INVALID_SOCKET;
|
||||||
stub->d.init = 0;
|
stub->d.init = 0;
|
||||||
|
@ -547,7 +547,7 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
||||||
if (!SocketSetBlocking(stub->connection, false)) {
|
if (!SocketSetBlocking(stub->connection, false)) {
|
||||||
goto connectionLost;
|
goto connectionLost;
|
||||||
}
|
}
|
||||||
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED, 0);
|
DebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED, 0);
|
||||||
} else if (SocketWouldBlock()) {
|
} else if (SocketWouldBlock()) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -23,7 +23,7 @@ enum GDBStubAckState {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GDBStub {
|
struct GDBStub {
|
||||||
struct ARMDebugger d;
|
struct Debugger d;
|
||||||
|
|
||||||
char line[GDB_STUB_MAX_LINE];
|
char line[GDB_STUB_MAX_LINE];
|
||||||
char outgoing[GDB_STUB_MAX_LINE];
|
char outgoing[GDB_STUB_MAX_LINE];
|
||||||
|
|
|
@ -11,52 +11,52 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, uint32_t newValue, int width);
|
static bool _checkWatchpoints(struct Debugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, uint32_t newValue, int width);
|
||||||
|
|
||||||
#define FIND_DEBUGGER(DEBUGGER, CPU) \
|
#define FIND_DEBUGGER(DEBUGGER, CPU) \
|
||||||
{ \
|
{ \
|
||||||
DEBUGGER = 0; \
|
DEBUGGER = 0; \
|
||||||
size_t i; \
|
size_t i; \
|
||||||
for (i = 0; i < CPU->numComponents; ++i) { \
|
for (i = 0; i < CPU->numComponents; ++i) { \
|
||||||
if (CPU->components[i]->id == ARM_DEBUGGER_ID) { \
|
if (CPU->components[i]->id == DEBUGGER_ID) { \
|
||||||
DEBUGGER = (struct ARMDebugger*) cpu->components[i]; \
|
DEBUGGER = (struct Debugger*) cpu->components[i]; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CREATE_SHIM(NAME, RETURN, TYPES, ...) \
|
#define CREATE_SHIM(NAME, RETURN, TYPES, ...) \
|
||||||
static RETURN ARMDebuggerShim_ ## NAME TYPES { \
|
static RETURN DebuggerShim_ ## NAME TYPES { \
|
||||||
struct ARMDebugger* debugger; \
|
struct Debugger* debugger; \
|
||||||
FIND_DEBUGGER(debugger, cpu); \
|
FIND_DEBUGGER(debugger, cpu); \
|
||||||
return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \
|
return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CREATE_WATCHPOINT_READ_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \
|
#define CREATE_WATCHPOINT_READ_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \
|
||||||
static RETURN ARMDebuggerShim_ ## NAME TYPES { \
|
static RETURN DebuggerShim_ ## NAME TYPES { \
|
||||||
struct ARMDebugger* debugger; \
|
struct Debugger* debugger; \
|
||||||
FIND_DEBUGGER(debugger, cpu); \
|
FIND_DEBUGGER(debugger, cpu); \
|
||||||
struct DebuggerEntryInfo info; \
|
struct DebuggerEntryInfo info; \
|
||||||
if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_READ, 0, WIDTH)) { \
|
if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_READ, 0, WIDTH)) { \
|
||||||
ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \
|
DebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \
|
||||||
} \
|
} \
|
||||||
return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \
|
return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CREATE_WATCHPOINT_WRITE_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \
|
#define CREATE_WATCHPOINT_WRITE_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \
|
||||||
static RETURN ARMDebuggerShim_ ## NAME TYPES { \
|
static RETURN DebuggerShim_ ## NAME TYPES { \
|
||||||
struct ARMDebugger* debugger; \
|
struct Debugger* debugger; \
|
||||||
FIND_DEBUGGER(debugger, cpu); \
|
FIND_DEBUGGER(debugger, cpu); \
|
||||||
struct DebuggerEntryInfo info; \
|
struct DebuggerEntryInfo info; \
|
||||||
if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_WRITE, value, WIDTH)) { \
|
if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_WRITE, value, WIDTH)) { \
|
||||||
ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \
|
DebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \
|
||||||
} \
|
} \
|
||||||
return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \
|
return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CREATE_MULTIPLE_WATCHPOINT_SHIM(NAME, ACCESS_TYPE) \
|
#define CREATE_MULTIPLE_WATCHPOINT_SHIM(NAME, ACCESS_TYPE) \
|
||||||
static uint32_t ARMDebuggerShim_ ## NAME (struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) { \
|
static uint32_t DebuggerShim_ ## NAME (struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) { \
|
||||||
struct ARMDebugger* debugger; \
|
struct Debugger* debugger; \
|
||||||
FIND_DEBUGGER(debugger, cpu); \
|
FIND_DEBUGGER(debugger, cpu); \
|
||||||
uint32_t popcount = popcount32(mask); \
|
uint32_t popcount = popcount32(mask); \
|
||||||
int offset = 4; \
|
int offset = 4; \
|
||||||
|
@ -72,7 +72,7 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st
|
||||||
for (i = 0; i < popcount; ++i) { \
|
for (i = 0; i < popcount; ++i) { \
|
||||||
struct DebuggerEntryInfo info; \
|
struct DebuggerEntryInfo info; \
|
||||||
if (_checkWatchpoints(debugger, base + 4 * i, &info, ACCESS_TYPE, 0, 4)) { \
|
if (_checkWatchpoints(debugger, base + 4 * i, &info, ACCESS_TYPE, 0, 4)) { \
|
||||||
ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \
|
DebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
return debugger->originalMemory.NAME(cpu, address, mask, direction, cycleCounter); \
|
return debugger->originalMemory.NAME(cpu, address, mask, direction, cycleCounter); \
|
||||||
|
@ -88,7 +88,7 @@ CREATE_MULTIPLE_WATCHPOINT_SHIM(loadMultiple, WATCHPOINT_READ)
|
||||||
CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple, WATCHPOINT_WRITE)
|
CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple, WATCHPOINT_WRITE)
|
||||||
CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address)
|
CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address)
|
||||||
|
|
||||||
static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, uint32_t newValue, int width) {
|
static bool _checkWatchpoints(struct Debugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, uint32_t newValue, int width) {
|
||||||
--width;
|
--width;
|
||||||
struct DebugWatchpoint* watchpoint;
|
struct DebugWatchpoint* watchpoint;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -116,20 +116,20 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) {
|
void DebuggerInstallMemoryShim(struct Debugger* debugger) {
|
||||||
debugger->originalMemory = debugger->cpu->memory;
|
debugger->originalMemory = debugger->cpu->memory;
|
||||||
debugger->cpu->memory.store32 = ARMDebuggerShim_store32;
|
debugger->cpu->memory.store32 = DebuggerShim_store32;
|
||||||
debugger->cpu->memory.store16 = ARMDebuggerShim_store16;
|
debugger->cpu->memory.store16 = DebuggerShim_store16;
|
||||||
debugger->cpu->memory.store8 = ARMDebuggerShim_store8;
|
debugger->cpu->memory.store8 = DebuggerShim_store8;
|
||||||
debugger->cpu->memory.load32 = ARMDebuggerShim_load32;
|
debugger->cpu->memory.load32 = DebuggerShim_load32;
|
||||||
debugger->cpu->memory.load16 = ARMDebuggerShim_load16;
|
debugger->cpu->memory.load16 = DebuggerShim_load16;
|
||||||
debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
|
debugger->cpu->memory.load8 = DebuggerShim_load8;
|
||||||
debugger->cpu->memory.storeMultiple = ARMDebuggerShim_storeMultiple;
|
debugger->cpu->memory.storeMultiple = DebuggerShim_storeMultiple;
|
||||||
debugger->cpu->memory.loadMultiple = ARMDebuggerShim_loadMultiple;
|
debugger->cpu->memory.loadMultiple = DebuggerShim_loadMultiple;
|
||||||
debugger->cpu->memory.setActiveRegion = ARMDebuggerShim_setActiveRegion;
|
debugger->cpu->memory.setActiveRegion = DebuggerShim_setActiveRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger) {
|
void DebuggerRemoveMemoryShim(struct Debugger* debugger) {
|
||||||
debugger->cpu->memory.store32 = debugger->originalMemory.store32;
|
debugger->cpu->memory.store32 = debugger->originalMemory.store32;
|
||||||
debugger->cpu->memory.store16 = debugger->originalMemory.store16;
|
debugger->cpu->memory.store16 = debugger->originalMemory.store16;
|
||||||
debugger->cpu->memory.store8 = debugger->originalMemory.store8;
|
debugger->cpu->memory.store8 = debugger->originalMemory.store8;
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
|
||||||
struct ARMDebugger;
|
struct Debugger;
|
||||||
|
|
||||||
void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger);
|
void DebuggerInstallMemoryShim(struct Debugger* debugger);
|
||||||
void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger);
|
void DebuggerRemoveMemoryShim(struct Debugger* debugger);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,8 +40,8 @@ static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode);
|
||||||
static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode);
|
static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode);
|
||||||
static void GBABreakpoint(struct ARMCore* cpu, int immediate);
|
static void GBABreakpoint(struct ARMCore* cpu, int immediate);
|
||||||
|
|
||||||
static bool _setSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
|
static bool _setSoftwareBreakpoint(struct Debugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode);
|
||||||
static bool _clearSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
|
static bool _clearSoftwareBreakpoint(struct Debugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
|
||||||
|
|
||||||
|
|
||||||
#ifdef _3DS
|
#ifdef _3DS
|
||||||
|
@ -402,7 +402,7 @@ static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) {
|
||||||
return nextEvent;
|
return nextEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) {
|
void GBAAttachDebugger(struct GBA* gba, struct Debugger* debugger) {
|
||||||
debugger->setSoftwareBreakpoint = _setSoftwareBreakpoint;
|
debugger->setSoftwareBreakpoint = _setSoftwareBreakpoint;
|
||||||
debugger->clearSoftwareBreakpoint = _clearSoftwareBreakpoint;
|
debugger->clearSoftwareBreakpoint = _clearSoftwareBreakpoint;
|
||||||
gba->debugger = debugger;
|
gba->debugger = debugger;
|
||||||
|
@ -698,7 +698,7 @@ void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...) {
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...) {
|
void GBADebuggerLogShim(struct Debugger* debugger, enum DebuggerLogLevel level, const char* format, ...) {
|
||||||
struct GBA* gba = 0;
|
struct GBA* gba = 0;
|
||||||
if (debugger->cpu) {
|
if (debugger->cpu) {
|
||||||
gba = (struct GBA*) debugger->cpu->master;
|
gba = (struct GBA*) debugger->cpu->master;
|
||||||
|
@ -819,7 +819,7 @@ void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) {
|
||||||
.address = _ARMPCAddress(cpu),
|
.address = _ARMPCAddress(cpu),
|
||||||
.opcode = opcode
|
.opcode = opcode
|
||||||
};
|
};
|
||||||
ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info);
|
DebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info);
|
||||||
}
|
}
|
||||||
GBALog(gba, level, "Stub opcode: %08x", opcode);
|
GBALog(gba, level, "Stub opcode: %08x", opcode);
|
||||||
}
|
}
|
||||||
|
@ -834,7 +834,7 @@ void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) {
|
||||||
.address = _ARMPCAddress(cpu),
|
.address = _ARMPCAddress(cpu),
|
||||||
.opcode = opcode
|
.opcode = opcode
|
||||||
};
|
};
|
||||||
ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info);
|
DebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info);
|
||||||
} else {
|
} else {
|
||||||
ARMRaiseUndefined(cpu);
|
ARMRaiseUndefined(cpu);
|
||||||
}
|
}
|
||||||
|
@ -851,7 +851,7 @@ void GBABreakpoint(struct ARMCore* cpu, int immediate) {
|
||||||
struct DebuggerEntryInfo info = {
|
struct DebuggerEntryInfo info = {
|
||||||
.address = _ARMPCAddress(cpu)
|
.address = _ARMPCAddress(cpu)
|
||||||
};
|
};
|
||||||
ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_BREAKPOINT, &info);
|
DebuggerEnter(gba->debugger, DEBUGGER_ENTER_BREAKPOINT, &info);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GBA_COMPONENT_CHEAT_DEVICE:
|
case GBA_COMPONENT_CHEAT_DEVICE:
|
||||||
|
@ -978,12 +978,12 @@ struct GBAThread* GBAThreadGetContext(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool _setSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {
|
static bool _setSoftwareBreakpoint(struct Debugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {
|
||||||
GBASetBreakpoint((struct GBA*) debugger->cpu->master, &debugger->d, address, mode, opcode);
|
GBASetBreakpoint((struct GBA*) debugger->cpu->master, &debugger->d, address, mode, opcode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _clearSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t opcode) {
|
static bool _clearSoftwareBreakpoint(struct Debugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t opcode) {
|
||||||
GBAClearBreakpoint((struct GBA*) debugger->cpu->master, address, mode, opcode);
|
GBAClearBreakpoint((struct GBA*) debugger->cpu->master, address, mode, opcode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ struct GBA {
|
||||||
|
|
||||||
struct mCoreSync* sync;
|
struct mCoreSync* sync;
|
||||||
|
|
||||||
struct ARMDebugger* debugger;
|
struct Debugger* debugger;
|
||||||
|
|
||||||
uint32_t bus;
|
uint32_t bus;
|
||||||
int performingDMA;
|
int performingDMA;
|
||||||
|
@ -166,7 +166,7 @@ void GBATestIRQ(struct ARMCore* cpu);
|
||||||
void GBAHalt(struct GBA* gba);
|
void GBAHalt(struct GBA* gba);
|
||||||
void GBAStop(struct GBA* gba);
|
void GBAStop(struct GBA* gba);
|
||||||
|
|
||||||
void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger);
|
void GBAAttachDebugger(struct GBA* gba, struct Debugger* debugger);
|
||||||
void GBADetachDebugger(struct GBA* gba);
|
void GBADetachDebugger(struct GBA* gba);
|
||||||
|
|
||||||
void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode,
|
void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode,
|
||||||
|
@ -196,6 +196,6 @@ ATTRIBUTE_FORMAT(printf, 3, 4)
|
||||||
void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...);
|
void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...);
|
||||||
|
|
||||||
ATTRIBUTE_FORMAT(printf, 3, 4)
|
ATTRIBUTE_FORMAT(printf, 3, 4)
|
||||||
void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel level, const char* format, ...);
|
void GBADebuggerLogShim(struct Debugger* debugger, enum DebuggerLogLevel level, const char* format, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,7 +61,7 @@ static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
|
||||||
|
|
||||||
if (gbaDebugger->frameAdvance) {
|
if (gbaDebugger->frameAdvance) {
|
||||||
if (!gbaDebugger->inVblank && GBARegisterDISPSTATIsInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1])) {
|
if (!gbaDebugger->inVblank && GBARegisterDISPSTATIsInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1])) {
|
||||||
ARMDebuggerEnter(&gbaDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0);
|
DebuggerEnter(&gbaDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0);
|
||||||
gbaDebugger->frameAdvance = false;
|
gbaDebugger->frameAdvance = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,7 +275,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
if (threadContext->debugger) {
|
if (threadContext->debugger) {
|
||||||
threadContext->debugger->log = GBADebuggerLogShim;
|
threadContext->debugger->log = GBADebuggerLogShim;
|
||||||
GBAAttachDebugger(&gba, threadContext->debugger);
|
GBAAttachDebugger(&gba, threadContext->debugger);
|
||||||
ARMDebuggerEnter(threadContext->debugger, DEBUGGER_ENTER_ATTACHED, 0);
|
DebuggerEnter(threadContext->debugger, DEBUGGER_ENTER_ATTACHED, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GBASIOSetDriverSet(&gba.sio, &threadContext->sioDrivers);
|
GBASIOSetDriverSet(&gba.sio, &threadContext->sioDrivers);
|
||||||
|
@ -299,8 +299,8 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
|
|
||||||
while (threadContext->state < THREAD_EXITING) {
|
while (threadContext->state < THREAD_EXITING) {
|
||||||
if (threadContext->debugger) {
|
if (threadContext->debugger) {
|
||||||
struct ARMDebugger* debugger = threadContext->debugger;
|
struct Debugger* debugger = threadContext->debugger;
|
||||||
ARMDebuggerRun(debugger);
|
DebuggerRun(debugger);
|
||||||
if (debugger->state == DEBUGGER_SHUTDOWN) {
|
if (debugger->state == DEBUGGER_SHUTDOWN) {
|
||||||
_changeState(threadContext, THREAD_EXITING, false);
|
_changeState(threadContext, THREAD_EXITING, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct GBAThread {
|
||||||
// Input
|
// Input
|
||||||
struct GBAVideoRenderer* renderer;
|
struct GBAVideoRenderer* renderer;
|
||||||
struct GBASIODriverSet sioDrivers;
|
struct GBASIODriverSet sioDrivers;
|
||||||
struct ARMDebugger* debugger;
|
struct Debugger* debugger;
|
||||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||||
struct mDirectorySet dirs;
|
struct mDirectorySet dirs;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -199,12 +199,12 @@ void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config) {
|
||||||
mCoreConfigSetOverrideIntValue(config, "fullscreen", graphicsOpts->fullscreen);
|
mCoreConfigSetOverrideIntValue(config, "fullscreen", graphicsOpts->fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ARMDebugger* createDebugger(struct mArguments* opts, struct mCore* core) {
|
struct Debugger* createDebugger(struct mArguments* opts, struct mCore* core) {
|
||||||
#ifndef USE_CLI_DEBUGGER
|
#ifndef USE_CLI_DEBUGGER
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
#endif
|
#endif
|
||||||
union DebugUnion {
|
union DebugUnion {
|
||||||
struct ARMDebugger d;
|
struct Debugger d;
|
||||||
#ifdef USE_CLI_DEBUGGER
|
#ifdef USE_CLI_DEBUGGER
|
||||||
struct CLIDebugger cli;
|
struct CLIDebugger cli;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,16 +8,7 @@
|
||||||
|
|
||||||
#include "util/common.h"
|
#include "util/common.h"
|
||||||
|
|
||||||
enum DebuggerType {
|
#include "debugger/debugger.h"
|
||||||
DEBUGGER_NONE = 0,
|
|
||||||
#ifdef USE_CLI_DEBUGGER
|
|
||||||
DEBUGGER_CLI,
|
|
||||||
#endif
|
|
||||||
#ifdef USE_GDB_STUB
|
|
||||||
DEBUGGER_GDB,
|
|
||||||
#endif
|
|
||||||
DEBUGGER_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mArguments {
|
struct mArguments {
|
||||||
char* fname;
|
char* fname;
|
||||||
|
@ -48,8 +39,6 @@ struct mGraphicsOpts {
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GBAThread;
|
|
||||||
|
|
||||||
bool parseArguments(struct mArguments* args, int argc, char* const* argv,
|
bool parseArguments(struct mArguments* args, int argc, char* const* argv,
|
||||||
struct mSubParser* subparser);
|
struct mSubParser* subparser);
|
||||||
void applyArguments(struct mArguments* args, struct mSubParser* subparser, struct mCoreConfig* config);
|
void applyArguments(struct mArguments* args, struct mSubParser* subparser, struct mCoreConfig* config);
|
||||||
|
@ -60,6 +49,6 @@ void version(const char* arg0);
|
||||||
|
|
||||||
void initParserForGraphics(struct mSubParser* parser, struct mGraphicsOpts* opts);
|
void initParserForGraphics(struct mSubParser* parser, struct mGraphicsOpts* opts);
|
||||||
struct mCore;
|
struct mCore;
|
||||||
struct ARMDebugger* createDebugger(struct mArguments* opts, struct mCore* core);
|
struct Debugger* createDebugger(struct mArguments* opts, struct mCore* core);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,12 +41,12 @@ void GDBController::attach() {
|
||||||
}
|
}
|
||||||
m_gameController->setDebugger(&m_gdbStub.d);
|
m_gameController->setDebugger(&m_gdbStub.d);
|
||||||
if (m_gameController->isLoaded()) {
|
if (m_gameController->isLoaded()) {
|
||||||
ARMDebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_ATTACHED, 0);
|
DebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_ATTACHED, 0);
|
||||||
} else {
|
} else {
|
||||||
QObject::disconnect(m_autoattach);
|
QObject::disconnect(m_autoattach);
|
||||||
m_autoattach = connect(m_gameController, &GameController::gameStarted, [this]() {
|
m_autoattach = connect(m_gameController, &GameController::gameStarted, [this]() {
|
||||||
QObject::disconnect(m_autoattach);
|
QObject::disconnect(m_autoattach);
|
||||||
ARMDebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_ATTACHED, 0);
|
DebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_ATTACHED, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,6 @@ void GDBController::breakInto() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_gameController->threadInterrupt();
|
m_gameController->threadInterrupt();
|
||||||
ARMDebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_MANUAL, 0);
|
DebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_MANUAL, 0);
|
||||||
m_gameController->threadContinue();
|
m_gameController->threadContinue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,11 +262,11 @@ void GameController::setOptions(const mCoreOptions* opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_GDB_STUB
|
#ifdef USE_GDB_STUB
|
||||||
ARMDebugger* GameController::debugger() {
|
Debugger* GameController::debugger() {
|
||||||
return m_threadContext.debugger;
|
return m_threadContext.debugger;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::setDebugger(ARMDebugger* debugger) {
|
void GameController::setDebugger(Debugger* debugger) {
|
||||||
threadInterrupt();
|
threadInterrupt();
|
||||||
if (m_threadContext.debugger && GBAThreadIsActive(&m_threadContext)) {
|
if (m_threadContext.debugger && GBAThreadIsActive(&m_threadContext)) {
|
||||||
GBADetachDebugger(m_threadContext.gba);
|
GBADetachDebugger(m_threadContext.gba);
|
||||||
|
|
|
@ -75,8 +75,8 @@ public:
|
||||||
int stateSlot() const { return m_stateSlot; }
|
int stateSlot() const { return m_stateSlot; }
|
||||||
|
|
||||||
#ifdef USE_GDB_STUB
|
#ifdef USE_GDB_STUB
|
||||||
ARMDebugger* debugger();
|
Debugger* debugger();
|
||||||
void setDebugger(ARMDebugger*);
|
void setDebugger(Debugger*);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -405,7 +405,7 @@ static void _mSDLHandleKeypressGBA(struct GBAThread* context, struct mSDLPlayer*
|
||||||
switch (event->keysym.sym) {
|
switch (event->keysym.sym) {
|
||||||
case SDLK_F11:
|
case SDLK_F11:
|
||||||
if (context->debugger) {
|
if (context->debugger) {
|
||||||
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL, 0);
|
DebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
#ifdef USE_PNG
|
#ifdef USE_PNG
|
||||||
|
|
Loading…
Reference in New Issue