Debugger: Add support for additional platforms in CLI

This commit is contained in:
Jeffrey Pfau 2014-11-27 09:39:45 -08:00
parent 8ec961d2e8
commit a8731d280f
6 changed files with 193 additions and 130 deletions

View File

@ -8,95 +8,71 @@
#include <pthread.h> #include <pthread.h>
#endif #endif
struct DebugVector {
struct DebugVector* next;
enum DVType {
DV_ERROR_TYPE,
DV_INT_TYPE,
DV_CHAR_TYPE
} type;
union {
int32_t intValue;
char* charValue;
};
};
static const char* ERROR_MISSING_ARGS = "Arguments missing"; static const char* ERROR_MISSING_ARGS = "Arguments missing";
static struct CLIDebugger* _activeDebugger; static struct CLIDebugger* _activeDebugger;
typedef void (*DebuggerCommand)(struct CLIDebugger*, struct DebugVector*); static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);
typedef struct DebugVector* (*DVParser)(struct CLIDebugger* debugger, const char* string, size_t length); static void _continue(struct CLIDebugger*, struct CLIDebugVector*);
static void _disassemble(struct CLIDebugger*, struct CLIDebugVector*);
static struct DebugVector* _DVParse(struct CLIDebugger* debugger, const char* string, size_t length); static void _disassembleArm(struct CLIDebugger*, struct CLIDebugVector*);
static struct DebugVector* _DVStringParse(struct CLIDebugger* debugger, const char* string, size_t length); static void _disassembleThumb(struct CLIDebugger*, struct CLIDebugVector*);
static void _next(struct CLIDebugger*, struct CLIDebugVector*);
static void _breakInto(struct CLIDebugger*, struct DebugVector*); static void _print(struct CLIDebugger*, struct CLIDebugVector*);
static void _continue(struct CLIDebugger*, struct DebugVector*); static void _printBin(struct CLIDebugger*, struct CLIDebugVector*);
static void _disassemble(struct CLIDebugger*, struct DebugVector*); static void _printHex(struct CLIDebugger*, struct CLIDebugVector*);
static void _disassembleArm(struct CLIDebugger*, struct DebugVector*); static void _printStatus(struct CLIDebugger*, struct CLIDebugVector*);
static void _disassembleThumb(struct CLIDebugger*, struct DebugVector*); static void _printHelp(struct CLIDebugger*, struct CLIDebugVector*);
static void _next(struct CLIDebugger*, struct DebugVector*); static void _quit(struct CLIDebugger*, struct CLIDebugVector*);
static void _print(struct CLIDebugger*, struct DebugVector*); static void _readByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _printBin(struct CLIDebugger*, struct DebugVector*); static void _reset(struct CLIDebugger*, struct CLIDebugVector*);
static void _printHex(struct CLIDebugger*, struct DebugVector*); static void _readHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _printStatus(struct CLIDebugger*, struct DebugVector*); static void _readWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _printHelp(struct CLIDebugger*, struct DebugVector*); static void _setBreakpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _quit(struct CLIDebugger*, struct DebugVector*); static void _clearBreakpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _readByte(struct CLIDebugger*, struct DebugVector*); static void _setWatchpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _reset(struct CLIDebugger*, struct DebugVector*);
static void _readHalfword(struct CLIDebugger*, struct DebugVector*);
static void _readWord(struct CLIDebugger*, struct DebugVector*);
static void _setBreakpoint(struct CLIDebugger*, struct DebugVector*);
static void _clearBreakpoint(struct CLIDebugger*, struct DebugVector*);
static void _setWatchpoint(struct CLIDebugger*, struct DebugVector*);
static void _breakIntoDefault(int signal); static void _breakIntoDefault(int signal);
static void _disassembleMode(struct CLIDebugger*, struct DebugVector*, enum ExecutionMode mode); static void _disassembleMode(struct CLIDebugger*, struct CLIDebugVector*, enum ExecutionMode mode);
static void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode); static void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode);
static struct { static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
const char* name; { "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
DebuggerCommand command; { "break", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
DVParser parser;
const char* summary;
} _debuggerCommands[] = {
{ "b", _setBreakpoint, _DVParse, "Set a breakpoint" },
{ "break", _setBreakpoint, _DVParse, "Set a breakpoint" },
{ "c", _continue, 0, "Continue execution" }, { "c", _continue, 0, "Continue execution" },
{ "continue", _continue, 0, "Continue execution" }, { "continue", _continue, 0, "Continue execution" },
{ "d", _clearBreakpoint, _DVParse, "Delete a breakpoint" }, { "d", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" },
{ "delete", _clearBreakpoint, _DVParse, "Delete a breakpoint" }, { "delete", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" },
{ "dis", _disassemble, _DVParse, "Disassemble instructions" }, { "dis", _disassemble, CLIDVParse, "Disassemble instructions" },
{ "dis/a", _disassembleArm, _DVParse, "Disassemble instructions as ARM" }, { "dis/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" },
{ "dis/t", _disassembleThumb, _DVParse, "Disassemble instructions as Thumb" }, { "dis/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" },
{ "disasm", _disassemble, _DVParse, "Disassemble instructions" }, { "disasm", _disassemble, CLIDVParse, "Disassemble instructions" },
{ "disasm/a", _disassembleArm, _DVParse, "Disassemble instructions as ARM" }, { "disasm/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" },
{ "disasm/t", _disassembleThumb, _DVParse, "Disassemble instructions as Thumb" }, { "disasm/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" },
{ "disassemble", _disassemble, _DVParse, "Disassemble instructions" }, { "disassemble", _disassemble, CLIDVParse, "Disassemble instructions" },
{ "disassemble/a", _disassembleArm, _DVParse, "Disassemble instructions as ARM" }, { "disassemble/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" },
{ "disassemble/t", _disassembleThumb, _DVParse, "Disassemble instructions as Thumb" }, { "disassemble/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" },
{ "h", _printHelp, _DVStringParse, "Print help" }, { "h", _printHelp, CLIDVStringParse, "Print help" },
{ "help", _printHelp, _DVStringParse, "Print help" }, { "help", _printHelp, CLIDVStringParse, "Print help" },
{ "i", _printStatus, 0, "Print the current status" }, { "i", _printStatus, 0, "Print the current status" },
{ "info", _printStatus, 0, "Print the current status" }, { "info", _printStatus, 0, "Print the current status" },
{ "n", _next, 0, "Execute next instruction" }, { "n", _next, 0, "Execute next instruction" },
{ "next", _next, 0, "Execute next instruction" }, { "next", _next, 0, "Execute next instruction" },
{ "p", _print, _DVParse, "Print a value" }, { "p", _print, CLIDVParse, "Print a value" },
{ "p/t", _printBin, _DVParse, "Print a value as binary" }, { "p/t", _printBin, CLIDVParse, "Print a value as binary" },
{ "p/x", _printHex, _DVParse, "Print a value as hexadecimal" }, { "p/x", _printHex, CLIDVParse, "Print a value as hexadecimal" },
{ "print", _print, _DVParse, "Print a value" }, { "print", _print, CLIDVParse, "Print a value" },
{ "print/t", _printBin, _DVParse, "Print a value as binary" }, { "print/t", _printBin, CLIDVParse, "Print a value as binary" },
{ "print/x", _printHex, _DVParse, "Print a value as hexadecimal" }, { "print/x", _printHex, CLIDVParse, "Print a value as hexadecimal" },
{ "q", _quit, 0, "Quit the emulator" }, { "q", _quit, 0, "Quit the emulator" },
{ "quit", _quit, 0, "Quit the emulator" }, { "quit", _quit, 0, "Quit the emulator" },
{ "rb", _readByte, _DVParse, "Read a byte from a specified offset" }, { "rb", _readByte, CLIDVParse, "Read a byte from a specified offset" },
{ "reset", _reset, 0, "Reset the emulation" }, { "reset", _reset, 0, "Reset the emulation" },
{ "rh", _readHalfword, _DVParse, "Read a halfword from a specified offset" }, { "rh", _readHalfword, CLIDVParse, "Read a halfword from a specified offset" },
{ "rw", _readWord, _DVParse, "Read a word from a specified offset" }, { "rw", _readWord, CLIDVParse, "Read a word from a specified offset" },
{ "status", _printStatus, 0, "Print the current status" }, { "status", _printStatus, 0, "Print the current status" },
{ "w", _setWatchpoint, _DVParse, "Set a watchpoint" }, { "w", _setWatchpoint, CLIDVParse, "Set a watchpoint" },
{ "watch", _setWatchpoint, _DVParse, "Set a watchpoint" }, { "watch", _setWatchpoint, CLIDVParse, "Set a watchpoint" },
{ "x", _breakInto, 0, "Break into attached debugger (for developers)" }, { "x", _breakInto, 0, "Break into attached debugger (for developers)" },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
@ -117,7 +93,7 @@ static void _handleDeath(int sig) {
printf("No debugger attached!\n"); printf("No debugger attached!\n");
} }
static void _breakInto(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _breakInto(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger); UNUSED(debugger);
UNUSED(dv); UNUSED(dv);
struct sigaction sa, osa; struct sigaction sa, osa;
@ -134,30 +110,30 @@ static void _breakInto(struct CLIDebugger* debugger, struct DebugVector* dv) {
sigaction(SIGTRAP, &osa, 0); sigaction(SIGTRAP, &osa, 0);
} }
static void _continue(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _continue(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(dv); UNUSED(dv);
debugger->d.state = DEBUGGER_RUNNING; debugger->d.state = DEBUGGER_RUNNING;
} }
static void _next(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _next(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(dv); UNUSED(dv);
ARMRun(debugger->d.cpu); ARMRun(debugger->d.cpu);
_printStatus(debugger, 0); _printStatus(debugger, 0);
} }
static void _disassemble(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _disassemble(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
_disassembleMode(debugger, dv, debugger->d.cpu->executionMode); _disassembleMode(debugger, dv, debugger->d.cpu->executionMode);
} }
static void _disassembleArm(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _disassembleArm(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
_disassembleMode(debugger, dv, MODE_ARM); _disassembleMode(debugger, dv, MODE_ARM);
} }
static void _disassembleThumb(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _disassembleThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
_disassembleMode(debugger, dv, MODE_THUMB); _disassembleMode(debugger, dv, MODE_THUMB);
} }
static void _disassembleMode(struct CLIDebugger* debugger, struct DebugVector* dv, enum ExecutionMode mode) { static void _disassembleMode(struct CLIDebugger* debugger, struct CLIDebugVector* dv, enum ExecutionMode mode) {
uint32_t address; uint32_t address;
int size; int size;
int wordSize; int wordSize;
@ -168,14 +144,14 @@ static void _disassembleMode(struct CLIDebugger* debugger, struct DebugVector* d
wordSize = WORD_SIZE_THUMB; wordSize = WORD_SIZE_THUMB;
} }
if (!dv || dv->type != DV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
address = debugger->d.cpu->gprs[ARM_PC] - wordSize; address = debugger->d.cpu->gprs[ARM_PC] - wordSize;
} else { } else {
address = dv->intValue; address = dv->intValue;
dv = dv->next; dv = dv->next;
} }
if (!dv || dv->type != DV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
size = 1; size = 1;
} else { } else {
size = dv->intValue; size = dv->intValue;
@ -189,7 +165,7 @@ static void _disassembleMode(struct CLIDebugger* debugger, struct DebugVector* d
} }
} }
static void _print(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _print(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger); UNUSED(debugger);
for ( ; dv; dv = dv->next) { for ( ; dv; dv = dv->next) {
printf(" %u", dv->intValue); printf(" %u", dv->intValue);
@ -197,7 +173,7 @@ static void _print(struct CLIDebugger* debugger, struct DebugVector* dv) {
printf("\n"); printf("\n");
} }
static void _printBin(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _printBin(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger); UNUSED(debugger);
for ( ; dv; dv = dv->next) { for ( ; dv; dv = dv->next) {
printf(" 0b"); printf(" 0b");
@ -209,7 +185,7 @@ static void _printBin(struct CLIDebugger* debugger, struct DebugVector* dv) {
printf("\n"); printf("\n");
} }
static void _printHex(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _printHex(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger); UNUSED(debugger);
for ( ; dv; dv = dv->next) { for ( ; dv; dv = dv->next) {
printf(" 0x%08X", dv->intValue); printf(" 0x%08X", dv->intValue);
@ -217,14 +193,21 @@ static void _printHex(struct CLIDebugger* debugger, struct DebugVector* dv) {
printf("\n"); printf("\n");
} }
static void _printHelp(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger); UNUSED(debugger);
UNUSED(dv); UNUSED(dv);
if (!dv) { if (!dv) {
puts("ARM commands:");
int i; int i;
for (i = 0; _debuggerCommands[i].name; ++i) { for (i = 0; _debuggerCommands[i].name; ++i) {
printf("%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary); printf("%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary);
} }
if (debugger->system) {
printf("%s commands:\n", debugger->system->name);
for (i = 0; debugger->system->commands[i].name; ++i) {
printf("%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary);
}
}
} else { } else {
int i; int i;
for (i = 0; _debuggerCommands[i].name; ++i) { for (i = 0; _debuggerCommands[i].name; ++i) {
@ -232,6 +215,14 @@ static void _printHelp(struct CLIDebugger* debugger, struct DebugVector* dv) {
printf(" %s\n", _debuggerCommands[i].summary); printf(" %s\n", _debuggerCommands[i].summary);
} }
} }
if (debugger->system) {
printf("\n%s commands:\n", debugger->system->name);
for (i = 0; debugger->system->commands[i].name; ++i) {
if (strcmp(debugger->system->commands[i].name, dv->charValue) == 0) {
printf(" %s\n", debugger->system->commands[i].summary);
}
}
}
} }
} }
@ -252,7 +243,7 @@ static inline void _printLine(struct CLIDebugger* debugger, uint32_t address, en
} }
} }
static void _printStatus(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(dv); UNUSED(dv);
int r; int r;
for (r = 0; r < 4; ++r) { for (r = 0; r < 4; ++r) {
@ -273,13 +264,13 @@ static void _printStatus(struct CLIDebugger* debugger, struct DebugVector* dv) {
_printLine(debugger, debugger->d.cpu->gprs[ARM_PC] - instructionLength, mode); _printLine(debugger, debugger->d.cpu->gprs[ARM_PC] - instructionLength, mode);
} }
static void _quit(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _quit(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(dv); UNUSED(dv);
debugger->d.state = DEBUGGER_SHUTDOWN; debugger->d.state = DEBUGGER_SHUTDOWN;
} }
static void _readByte(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _readByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != DV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); printf("%s\n", ERROR_MISSING_ARGS);
return; return;
} }
@ -288,14 +279,14 @@ static void _readByte(struct CLIDebugger* debugger, struct DebugVector* dv) {
printf(" 0x%02X\n", value); printf(" 0x%02X\n", value);
} }
static void _reset(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _reset(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(dv); UNUSED(dv);
ARMReset(debugger->d.cpu); ARMReset(debugger->d.cpu);
_printStatus(debugger, 0); _printStatus(debugger, 0);
} }
static void _readHalfword(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _readHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != DV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); printf("%s\n", ERROR_MISSING_ARGS);
return; return;
} }
@ -304,8 +295,8 @@ static void _readHalfword(struct CLIDebugger* debugger, struct DebugVector* dv)
printf(" 0x%04X\n", value); printf(" 0x%04X\n", value);
} }
static void _readWord(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _readWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != DV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); printf("%s\n", ERROR_MISSING_ARGS);
return; return;
} }
@ -314,8 +305,8 @@ static void _readWord(struct CLIDebugger* debugger, struct DebugVector* dv) {
printf(" 0x%08X\n", value); printf(" 0x%08X\n", value);
} }
static void _setBreakpoint(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != DV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); printf("%s\n", ERROR_MISSING_ARGS);
return; return;
} }
@ -323,8 +314,8 @@ static void _setBreakpoint(struct CLIDebugger* debugger, struct DebugVector* dv)
ARMDebuggerSetBreakpoint(&debugger->d, address); ARMDebuggerSetBreakpoint(&debugger->d, address);
} }
static void _clearBreakpoint(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != DV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); printf("%s\n", ERROR_MISSING_ARGS);
return; return;
} }
@ -332,8 +323,8 @@ static void _clearBreakpoint(struct CLIDebugger* debugger, struct DebugVector* d
ARMDebuggerClearBreakpoint(&debugger->d, address); ARMDebuggerClearBreakpoint(&debugger->d, address);
} }
static void _setWatchpoint(struct CLIDebugger* debugger, struct DebugVector* dv) { static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != DV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); printf("%s\n", ERROR_MISSING_ARGS);
return; return;
} }
@ -346,7 +337,7 @@ static void _breakIntoDefault(int signal) {
ARMDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL); ARMDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL);
} }
static uint32_t _performOperation(enum Operation operation, uint32_t current, uint32_t next, struct DebugVector* dv) { static uint32_t _performOperation(enum Operation operation, uint32_t current, uint32_t next, struct CLIDebugVector* dv) {
switch (operation) { switch (operation) {
case OP_ASSIGN: case OP_ASSIGN:
current = next; current = next;
@ -364,7 +355,7 @@ static uint32_t _performOperation(enum Operation operation, uint32_t current, ui
if (next != 0) { if (next != 0) {
current /= next; current /= next;
} else { } else {
dv->type = DV_ERROR_TYPE; dv->type = CLIDV_ERROR_TYPE;
return 0; return 0;
} }
break; break;
@ -372,7 +363,8 @@ 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 DebugVector* dv) { static uint32_t _lookupIdentifier(struct ARMDebugger* debugger, const char* name, struct CLIDebugVector* dv) {
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];
} }
@ -395,11 +387,18 @@ static uint32_t _lookupIdentifier(struct ARMDebugger* debugger, const char* name
return debugger->cpu->gprs[reg]; return debugger->cpu->gprs[reg];
} }
} }
dv->type = DV_ERROR_TYPE; if (cliDebugger->system) {
uint32_t value = cliDebugger->system->lookupIdentifier(cliDebugger->system, name, dv);
if (dv->type != CLIDV_ERROR_TYPE) {
return value;
}
} else {
dv->type = CLIDV_ERROR_TYPE;
}
return 0; return 0;
} }
static uint32_t _evaluateParseTree(struct ARMDebugger* debugger, struct ParseTree* tree, struct DebugVector* dv) { static uint32_t _evaluateParseTree(struct ARMDebugger* 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;
@ -409,29 +408,29 @@ static uint32_t _evaluateParseTree(struct ARMDebugger* debugger, struct ParseTre
return _lookupIdentifier(debugger, tree->token.identifierValue, dv); return _lookupIdentifier(debugger, tree->token.identifierValue, dv);
case TOKEN_ERROR_TYPE: case TOKEN_ERROR_TYPE:
default: default:
dv->type = DV_ERROR_TYPE; dv->type = CLIDV_ERROR_TYPE;
} }
return 0; return 0;
} }
static struct DebugVector* _DVParse(struct CLIDebugger* debugger, const char* string, size_t length) { struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length) {
if (!string || length < 1) { if (!string || length < 1) {
return 0; return 0;
} }
struct DebugVector dvTemp = { .type = DV_INT_TYPE }; struct CLIDebugVector dvTemp = { .type = CLIDV_INT_TYPE };
struct LexVector lv = { .next = 0 }; struct LexVector lv = { .next = 0 };
size_t adjusted = lexExpression(&lv, string, length); size_t adjusted = lexExpression(&lv, string, length);
if (adjusted > length) { if (adjusted > length) {
dvTemp.type = DV_ERROR_TYPE; dvTemp.type = CLIDV_ERROR_TYPE;
lexFree(lv.next); lexFree(lv.next);
} }
struct ParseTree tree; struct ParseTree tree;
parseLexedExpression(&tree, &lv); parseLexedExpression(&tree, &lv);
if (tree.token.type == TOKEN_ERROR_TYPE) { if (tree.token.type == TOKEN_ERROR_TYPE) {
dvTemp.type = DV_ERROR_TYPE; dvTemp.type = CLIDV_ERROR_TYPE;
} else { } else {
dvTemp.intValue = _evaluateParseTree(&debugger->d, &tree, &dvTemp); dvTemp.intValue = _evaluateParseTree(&debugger->d, &tree, &dvTemp);
} }
@ -442,28 +441,28 @@ static struct DebugVector* _DVParse(struct CLIDebugger* debugger, const char* st
length -= adjusted; length -= adjusted;
string += adjusted; string += adjusted;
struct DebugVector* dv = malloc(sizeof(struct DebugVector)); struct CLIDebugVector* dv = malloc(sizeof(struct CLIDebugVector));
if (dvTemp.type == DV_ERROR_TYPE) { if (dvTemp.type == CLIDV_ERROR_TYPE) {
dv->type = DV_ERROR_TYPE; dv->type = CLIDV_ERROR_TYPE;
dv->next = 0; dv->next = 0;
} else { } else {
*dv = dvTemp; *dv = dvTemp;
if (string[0] == ' ') { if (string[0] == ' ') {
dv->next = _DVParse(debugger, string + 1, length - 1); dv->next = CLIDVParse(debugger, string + 1, length - 1);
if (dv->next && dv->next->type == DV_ERROR_TYPE) { if (dv->next && dv->next->type == CLIDV_ERROR_TYPE) {
dv->type = DV_ERROR_TYPE; dv->type = CLIDV_ERROR_TYPE;
} }
} }
} }
return dv; return dv;
} }
static struct DebugVector* _DVStringParse(struct CLIDebugger* debugger, const char* string, size_t length) { struct CLIDebugVector* CLIDVStringParse(struct CLIDebugger* debugger, const char* string, size_t length) {
if (!string || length < 1) { if (!string || length < 1) {
return 0; return 0;
} }
struct DebugVector dvTemp = { .type = DV_CHAR_TYPE }; struct CLIDebugVector dvTemp = { .type = CLIDV_CHAR_TYPE };
size_t adjusted; size_t adjusted;
const char* next = strchr(string, ' '); const char* next = strchr(string, ' ');
@ -478,22 +477,22 @@ static struct DebugVector* _DVStringParse(struct CLIDebugger* debugger, const ch
length -= adjusted; length -= adjusted;
string += adjusted; string += adjusted;
struct DebugVector* dv = malloc(sizeof(struct DebugVector)); struct CLIDebugVector* dv = malloc(sizeof(struct CLIDebugVector));
*dv = dvTemp; *dv = dvTemp;
if (string[0] == ' ') { if (string[0] == ' ') {
dv->next = _DVStringParse(debugger, string + 1, length - 1); dv->next = CLIDVStringParse(debugger, string + 1, length - 1);
if (dv->next && dv->next->type == DV_ERROR_TYPE) { if (dv->next && dv->next->type == CLIDV_ERROR_TYPE) {
dv->type = DV_ERROR_TYPE; dv->type = CLIDV_ERROR_TYPE;
} }
} }
return dv; return dv;
} }
static void _DVFree(struct DebugVector* dv) { static void _DVFree(struct CLIDebugVector* dv) {
struct DebugVector* next; struct CLIDebugVector* next;
while (dv) { while (dv) {
next = dv->next; next = dv->next;
if (dv->type == DV_CHAR_TYPE) { if (dv->type == CLIDV_CHAR_TYPE) {
free(dv->charValue); free(dv->charValue);
} }
free(dv); free(dv);
@ -504,7 +503,7 @@ static void _DVFree(struct DebugVector* dv) {
static bool _parse(struct CLIDebugger* debugger, const char* line, size_t count) { static bool _parse(struct CLIDebugger* debugger, const char* line, size_t count) {
const char* firstSpace = strchr(line, ' '); const char* firstSpace = strchr(line, ' ');
size_t cmdLength; size_t cmdLength;
struct DebugVector* dv = 0; struct CLIDebugVector* dv = 0;
if (firstSpace) { if (firstSpace) {
cmdLength = firstSpace - line; cmdLength = firstSpace - line;
} else { } else {
@ -521,7 +520,7 @@ static bool _parse(struct CLIDebugger* debugger, const char* line, size_t count)
if (_debuggerCommands[i].parser) { if (_debuggerCommands[i].parser) {
if (firstSpace) { if (firstSpace) {
dv = _debuggerCommands[i].parser(debugger, firstSpace + 1, count - cmdLength - 1); dv = _debuggerCommands[i].parser(debugger, firstSpace + 1, count - cmdLength - 1);
if (dv && dv->type == DV_ERROR_TYPE) { if (dv && dv->type == CLIDV_ERROR_TYPE) {
printf("Parse error\n"); printf("Parse error\n");
_DVFree(dv); _DVFree(dv);
return false; return false;
@ -659,6 +658,12 @@ static void _cliDebuggerDeinit(struct ARMDebugger* 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);
if (cliDebugger->system) {
cliDebugger->system->deinit(cliDebugger->system);
free(cliDebugger->system);
cliDebugger->system = 0;
}
} }
void CLIDebuggerCreate(struct CLIDebugger* debugger) { void CLIDebuggerCreate(struct CLIDebugger* debugger) {
@ -667,4 +672,16 @@ void CLIDebuggerCreate(struct CLIDebugger* debugger) {
debugger->d.deinit = _cliDebuggerDeinit; debugger->d.deinit = _cliDebuggerDeinit;
debugger->d.paused = _commandLine; debugger->d.paused = _commandLine;
debugger->d.entered = _reportEntry; debugger->d.entered = _reportEntry;
debugger->system = 0;
}
void CLIDebuggerAttachSystem(struct CLIDebugger* debugger, struct CLIDebuggerSystem* system) {
if (debugger->system) {
debugger->system->deinit(debugger->system);
free(debugger->system);
}
debugger->system = system;
system->p = debugger;
} }

View File

@ -7,13 +7,56 @@
#include <histedit.h> #include <histedit.h>
struct CLIDebugger;
struct CLIDebugVector {
struct CLIDebugVector* next;
enum CLIDVType {
CLIDV_ERROR_TYPE,
CLIDV_INT_TYPE,
CLIDV_CHAR_TYPE
} type;
union {
int32_t intValue;
char* charValue;
};
};
typedef void (*CLIDebuggerCommand)(struct CLIDebugger*, struct CLIDebugVector*);
typedef struct CLIDebugVector* (*CLIDVParser)(struct CLIDebugger* debugger, const char* string, size_t length);
struct CLIDebuggerCommandSummary {
const char* name;
CLIDebuggerCommand command;
CLIDVParser parser;
const char* summary;
};
struct CLIDebuggerSystem {
struct CLIDebugger* p;
void (*init)(struct CLIDebuggerSystem*);
void (*deinit)(struct CLIDebuggerSystem*);
uint32_t (*lookupIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);
struct CLIDebuggerCommandSummary* commands;
const char* name;
};
struct CLIDebugger { struct CLIDebugger {
struct ARMDebugger d; struct ARMDebugger d;
struct CLIDebuggerSystem* system;
EditLine* elstate; EditLine* elstate;
History* histate; History* histate;
}; };
struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length);
struct CLIDebugVector* CLIDVStringParse(struct CLIDebugger* debugger, const char* string, size_t length);
void CLIDebuggerCreate(struct CLIDebugger*); void CLIDebuggerCreate(struct CLIDebugger*);
void CLIDebuggerAttachSystem(struct CLIDebugger*, struct CLIDebuggerSystem*);
#endif #endif

View File

@ -145,7 +145,8 @@ bool _parseGraphicsArg(struct SubParser* parser, struct GBAConfig* config, int o
} }
} }
struct ARMDebugger* createDebugger(struct GBAArguments* opts) { struct ARMDebugger* createDebugger(struct GBAArguments* opts, struct GBAThread* context) {
UNUSED(context);
union DebugUnion { union DebugUnion {
struct ARMDebugger d; struct ARMDebugger d;
#ifdef USE_CLI_DEBUGGER #ifdef USE_CLI_DEBUGGER

View File

@ -36,12 +36,14 @@ struct GraphicsOpts {
int multiplier; int multiplier;
}; };
struct GBAThread;
bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int argc, char* const* argv, struct SubParser* subparser); bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int argc, char* const* argv, struct SubParser* subparser);
void freeArguments(struct GBAArguments* opts); void freeArguments(struct GBAArguments* opts);
void usage(const char* arg0, const char* extraOptions); void usage(const char* arg0, const char* extraOptions);
void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts); void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts);
struct ARMDebugger* createDebugger(struct GBAArguments* opts); struct ARMDebugger* createDebugger(struct GBAArguments* opts, struct GBAThread* context);
#endif #endif

View File

@ -69,7 +69,7 @@ int main(int argc, char** argv) {
context.renderer = &renderer.d; context.renderer = &renderer.d;
} }
context.debugger = createDebugger(&args); context.debugger = createDebugger(&args, &context);
char gameCode[5] = { 0 }; char gameCode[5] = { 0 };
GBAConfigMap(&config, &opts); GBAConfigMap(&config, &opts);

View File

@ -82,7 +82,7 @@ int main(int argc, char** argv) {
.userData = &renderer .userData = &renderer
}; };
context.debugger = createDebugger(&args); context.debugger = createDebugger(&args, &context);
GBAMapOptionsToContext(&opts, &context); GBAMapOptionsToContext(&opts, &context);
GBAMapArgumentsToContext(&args, &context); GBAMapArgumentsToContext(&args, &context);