Debugger: Add get/set register functions

This commit is contained in:
Vicki Pfau 2017-10-13 00:29:38 -07:00
parent a2447d09e3
commit d484c98eba
7 changed files with 246 additions and 119 deletions

View File

@ -84,6 +84,9 @@ struct mDebuggerPlatform {
void (*clearWatchpoint)(struct mDebuggerPlatform*, uint32_t address, int segment);
void (*checkBreakpoints)(struct mDebuggerPlatform*);
void (*trace)(struct mDebuggerPlatform*, char* out, size_t* length);
bool (*getRegister)(struct mDebuggerPlatform*, const char* name, int32_t* value);
bool (*setRegister)(struct mDebuggerPlatform*, const char* name, int32_t value);
};
struct mDebuggerSymbols;

View File

@ -14,6 +14,7 @@ CXX_GUARD_START
extern const char* ERROR_MISSING_ARGS;
extern const char* ERROR_OVERFLOW;
extern const char* ERROR_INVALID_ARGS;
struct CLIDebugger;
@ -51,7 +52,6 @@ struct CLIDebuggerSystem {
void (*disassemble)(struct CLIDebuggerSystem*, struct CLIDebugVector* dv);
uint32_t (*lookupIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);
uint32_t (*lookupPlatformIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);
void (*printStatus)(struct CLIDebuggerSystem*);
struct CLIDebuggerCommandSummary* commands;

View File

@ -17,7 +17,6 @@ static void _disassembleArm(struct CLIDebugger*, struct CLIDebugVector*);
static void _disassembleThumb(struct CLIDebugger*, struct CLIDebugVector*);
static void _setBreakpointARM(struct CLIDebugger*, struct CLIDebugVector*);
static void _setBreakpointThumb(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeRegister(struct CLIDebugger*, struct CLIDebugVector*);
static void _disassembleMode(struct CLIDebugger*, struct CLIDebugVector*, enum ExecutionMode mode);
static uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode);
@ -33,7 +32,6 @@ static struct CLIDebuggerCommandSummary _armCommands[] = {
{ "disasm/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" },
{ "disassemble/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" },
{ "disassemble/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" },
{ "w/r", _writeRegister, "SI", "Write a register" },
{ 0, 0, 0, 0 }
};
@ -145,31 +143,6 @@ static void _printStatus(struct CLIDebuggerSystem* debugger) {
_printLine(debugger->p, cpu->gprs[ARM_PC] - instructionLength, mode);
}
static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
struct ARMCore* cpu = debugger->d.core->cpu;
if (!dv || dv->type != CLIDV_CHAR_TYPE) {
be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return;
}
if (!dv->next || dv->next->type != CLIDV_INT_TYPE) {
be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return;
}
char* end;
uint32_t regid = strtoul(&dv->charValue[1], &end, 10);
if (dv->charValue[0] != 'r' || (*end && !isspace(*end)) || regid > ARM_PC) {
be->printf(be, "%s\n", "Unknown register name");
return;
}
if (regid == ARM_PC) {
be->printf(be, "%s\n", "Cannot write to program counter");
return;
}
uint32_t value = dv->next->intValue;
cpu->gprs[regid] = value;
}
static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
if (!dv || dv->type != CLIDV_INT_TYPE) {
@ -190,38 +163,9 @@ static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVec
ARMDebuggerSetSoftwareBreakpoint(debugger->d.platform, address, MODE_THUMB);
}
static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) {
struct ARMCore* cpu = debugger->p->d.core->cpu;
if (strcmp(name, "sp") == 0) {
return cpu->gprs[ARM_SP];
}
if (strcmp(name, "lr") == 0) {
return cpu->gprs[ARM_LR];
}
if (strcmp(name, "pc") == 0) {
return cpu->gprs[ARM_PC];
}
if (strcmp(name, "cpsr") == 0) {
return cpu->cpsr.packed;
}
// TODO: test if mode has SPSR
if (strcmp(name, "spsr") == 0) {
return cpu->spsr.packed;
}
if (name[0] == 'r' && name[1] >= '0' && name[1] <= '9') {
int reg = atoi(&name[1]);
if (reg < 16) {
return cpu->gprs[reg];
}
}
dv->type = CLIDV_ERROR_TYPE;
return 0;
}
void ARMCLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
debugger->printStatus = _printStatus;
debugger->disassemble = _disassemble;
debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier;
debugger->platformName = "ARM";
debugger->platformCommands = _armCommands;
}

View File

@ -56,6 +56,8 @@ static void ARMDebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t addre
static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform*);
static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform*);
static void ARMDebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length);
static bool ARMDebuggerGetRegister(struct mDebuggerPlatform*, const char* name, int32_t* value);
static bool ARMDebuggerSetRegister(struct mDebuggerPlatform*, const char* name, int32_t value);
struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) {
struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct ARMDebugger));
@ -69,6 +71,8 @@ struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) {
platform->checkBreakpoints = ARMDebuggerCheckBreakpoints;
platform->hasBreakpoints = ARMDebuggerHasBreakpoints;
platform->trace = ARMDebuggerTrace;
platform->getRegister = ARMDebuggerGetRegister;
platform->setRegister = ARMDebuggerSetRegister;
return platform;
}
@ -246,3 +250,81 @@ static void ARMDebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* len
cpu->gprs[12], cpu->gprs[13], cpu->gprs[14], cpu->gprs[15],
cpu->cpsr.packed, disassembly);
}
bool ARMDebuggerGetRegister(struct mDebuggerPlatform* d, const char* name, int32_t* value) {
struct ARMDebugger* debugger = (struct ARMDebugger*) d;
struct ARMCore* cpu = debugger->cpu;
if (strcmp(name, "sp") == 0) {
*value = cpu->gprs[ARM_SP];
return true;
}
if (strcmp(name, "lr") == 0) {
*value = cpu->gprs[ARM_LR];
return true;
}
if (strcmp(name, "pc") == 0) {
*value = cpu->gprs[ARM_PC];
return true;
}
if (strcmp(name, "cpsr") == 0) {
*value = cpu->cpsr.packed;
return true;
}
// TODO: test if mode has SPSR
if (strcmp(name, "spsr") == 0) {
*value = cpu->spsr.packed;
return true;
}
if (name[0] == 'r') {
char* end;
uint32_t reg = strtoul(&name[1], &end, 10);
if (reg <= ARM_PC) {
*value = cpu->gprs[reg];
return true;
}
}
return false;
}
bool ARMDebuggerSetRegister(struct mDebuggerPlatform* d, const char* name, int32_t value) {
struct ARMDebugger* debugger = (struct ARMDebugger*) d;
struct ARMCore* cpu = debugger->cpu;
if (strcmp(name, "sp") == 0) {
cpu->gprs[ARM_SP] = value;
return true;
}
if (strcmp(name, "lr") == 0) {
cpu->gprs[ARM_LR] = value;
return true;
}
if (strcmp(name, "pc") == 0) {
cpu->gprs[ARM_PC] = value;
int32_t currentCycles = 0;
if (cpu->executionMode == MODE_ARM) {
ARM_WRITE_PC;
} else {
THUMB_WRITE_PC;
}
return true;
}
if (name[0] == 'r') {
char* end;
uint32_t reg = strtoul(&name[1], &end, 10);
if (reg > ARM_PC) {
return false;
}
cpu->gprs[reg] = value;
if (reg == ARM_PC) {
int32_t currentCycles = 0;
if (cpu->executionMode == MODE_ARM) {
ARM_WRITE_PC;
} else {
THUMB_WRITE_PC;
}
}
return true;
}
return false;
}

View File

@ -26,6 +26,7 @@
const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share
const char* ERROR_OVERFLOW = "Arguments overflow";
const char* ERROR_INVALID_ARGS = "Invalid arguments";
#if !defined(NDEBUG) && !defined(_WIN32)
static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);
@ -51,6 +52,7 @@ static void _setWriteWatchpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _trace(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeRegister(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*);
@ -92,6 +94,7 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
{ "w", _setWatchpoint, "I", "Set a watchpoint" },
{ "w/1", _writeByte, "II", "Write a byte at a specified offset" },
{ "w/2", _writeHalfword, "II", "Write a halfword at a specified offset" },
{ "w/r", _writeRegister, "SI", "Write a register" },
{ "w/4", _writeWord, "II", "Write a word at a specified offset" },
{ "watch", _setWatchpoint, "I", "Set a watchpoint" },
{ "watch/r", _setReadWatchpoint, "I", "Set a read watchpoint" },
@ -273,12 +276,12 @@ static void _readWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
}
static void _writeByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) {
if (!dv || !dv->next) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return;
}
if (!dv->next || dv->next->type != CLIDV_INT_TYPE) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
return;
}
uint32_t address = dv->intValue;
@ -295,12 +298,12 @@ static void _writeByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv)
}
static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) {
if (!dv || !dv->next) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return;
}
if (!dv->next || dv->next->type != CLIDV_INT_TYPE) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
return;
}
uint32_t address = dv->intValue;
@ -316,15 +319,29 @@ static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector*
}
}
static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) {
static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || !dv->next) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return;
}
if (!dv->next || dv->next->type != CLIDV_INT_TYPE) {
if (dv->type != CLIDV_CHAR_TYPE || dv->next->type != CLIDV_INT_TYPE) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
return;
}
if (!debugger->d.platform->setRegister(debugger->d.platform, dv->charValue, dv->next->intValue)) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
}
}
static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || !dv->next) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return;
}
if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
return;
}
uint32_t address = dv->intValue;
uint32_t value = dv->next->intValue;
if (dv->segmentValue >= 0) {
@ -559,12 +576,10 @@ static void _lookupIdentifier(struct mDebugger* debugger, const char* name, stru
if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) {
return;
}
value = cliDebugger->system->lookupPlatformIdentifier(cliDebugger->system, name, dv);
if (dv->type != CLIDV_ERROR_TYPE) {
dv->intValue = value;
dv->type = CLIDV_INT_TYPE;
if (debugger->platform->getRegister(debugger->platform, name, &dv->intValue)) {
return;
}
dv->type = CLIDV_INT_TYPE;
value = cliDebugger->system->lookupIdentifier(cliDebugger->system, name, dv);
if (dv->type != CLIDV_ERROR_TYPE) {
dv->intValue = value;

View File

@ -100,58 +100,9 @@ static void _printStatus(struct CLIDebuggerSystem* debugger) {
_printLine(debugger->p, cpu->pc, cpu->memory.currentSegment(cpu, cpu->pc));
}
static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) {
struct LR35902Core* cpu = debugger->p->d.core->cpu;
if (strcmp(name, "a") == 0) {
return cpu->a;
}
if (strcmp(name, "b") == 0) {
return cpu->b;
}
if (strcmp(name, "c") == 0) {
return cpu->c;
}
if (strcmp(name, "d") == 0) {
return cpu->d;
}
if (strcmp(name, "e") == 0) {
return cpu->e;
}
if (strcmp(name, "h") == 0) {
return cpu->h;
}
if (strcmp(name, "l") == 0) {
return cpu->l;
}
if (strcmp(name, "bc") == 0) {
return cpu->bc;
}
if (strcmp(name, "de") == 0) {
return cpu->de;
}
if (strcmp(name, "hl") == 0) {
return cpu->hl;
}
if (strcmp(name, "af") == 0) {
return cpu->af;
}
if (strcmp(name, "pc") == 0) {
return cpu->pc;
}
if (strcmp(name, "sp") == 0) {
return cpu->sp;
}
if (strcmp(name, "f") == 0) {
return cpu->f.packed;
}
dv->type = CLIDV_ERROR_TYPE;
return 0;
}
void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
debugger->printStatus = _printStatus;
debugger->disassemble = _disassemble;
debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier;
debugger->platformName = "GB-Z80";
debugger->platformCommands = _lr35902Commands;
}

View File

@ -50,6 +50,8 @@ static void LR35902DebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t a
static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform*);
static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform*);
static void LR35902DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length);
static bool LR35902DebuggerGetRegister(struct mDebuggerPlatform*, const char* name, int32_t* value);
static bool LR35902DebuggerSetRegister(struct mDebuggerPlatform*, const char* name, int32_t value);
struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) {
struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct LR35902Debugger));
@ -63,6 +65,8 @@ struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) {
platform->checkBreakpoints = LR35902DebuggerCheckBreakpoints;
platform->hasBreakpoints = LR35902DebuggerHasBreakpoints;
platform->trace = LR35902DebuggerTrace;
platform->getRegister = LR35902DebuggerGetRegister;
platform->setRegister = LR35902DebuggerSetRegister;
return platform;
}
@ -168,3 +172,131 @@ static void LR35902DebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t*
cpu->d, cpu->e, cpu->h, cpu->l,
cpu->sp, cpu->pc, disassembly);
}
bool LR35902DebuggerGetRegister(struct mDebuggerPlatform* d, const char* name, int32_t* value) {
struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
struct LR35902Core* cpu = debugger->cpu;
if (strcmp(name, "a") == 0) {
*value = cpu->a;
return true;
}
if (strcmp(name, "b") == 0) {
*value = cpu->b;
return true;
}
if (strcmp(name, "c") == 0) {
*value = cpu->c;
return true;
}
if (strcmp(name, "d") == 0) {
*value = cpu->d;
return true;
}
if (strcmp(name, "e") == 0) {
*value = cpu->e;
return true;
}
if (strcmp(name, "h") == 0) {
*value = cpu->h;
return true;
}
if (strcmp(name, "l") == 0) {
*value = cpu->l;
return true;
}
if (strcmp(name, "bc") == 0) {
*value = cpu->bc;
return true;
}
if (strcmp(name, "de") == 0) {
*value = cpu->de;
return true;
}
if (strcmp(name, "hl") == 0) {
*value = cpu->hl;
return true;
}
if (strcmp(name, "af") == 0) {
*value = cpu->af;
return true;
}
if (strcmp(name, "pc") == 0) {
*value = cpu->pc;
return true;
}
if (strcmp(name, "sp") == 0) {
*value = cpu->sp;
return true;
}
if (strcmp(name, "f") == 0) {
*value = cpu->f.packed;
return true;
}
return false;
}
bool LR35902DebuggerSetRegister(struct mDebuggerPlatform* d, const char* name, int32_t value) {
struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
struct LR35902Core* cpu = debugger->cpu;
if (strcmp(name, "a") == 0) {
cpu->a = value;
return true;
}
if (strcmp(name, "b") == 0) {
cpu->b = value;
return true;
}
if (strcmp(name, "c") == 0) {
cpu->c = value;
return true;
}
if (strcmp(name, "d") == 0) {
cpu->d = value;
return true;
}
if (strcmp(name, "e") == 0) {
cpu->e = value;
return true;
}
if (strcmp(name, "h") == 0) {
cpu->h = value;
return true;
}
if (strcmp(name, "l") == 0) {
cpu->l = value;
return true;
}
if (strcmp(name, "bc") == 0) {
cpu->bc = value;
return true;
}
if (strcmp(name, "de") == 0) {
cpu->de = value;
return true;
}
if (strcmp(name, "hl") == 0) {
cpu->hl = value;
return true;
}
if (strcmp(name, "af") == 0) {
cpu->af = value;
cpu->f.packed &= 0xF0;
return true;
}
if (strcmp(name, "pc") == 0) {
cpu->pc = value;
cpu->memory.setActiveRegion(cpu, cpu->pc);
return true;
}
if (strcmp(name, "sp") == 0) {
cpu->sp = value;
return true;
}
if (strcmp(name, "f") == 0) {
cpu->f.packed = value & 0xF0;
return true;
}
return false;
}