From f715534083f4101b94ddbae5a0dd38c3e52bc526 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 13 Apr 2013 01:23:41 -0700 Subject: [PATCH] Begin command line parsing --- src/debugger.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 285 insertions(+), 11 deletions(-) diff --git a/src/debugger.c b/src/debugger.c index f8a5b673b..e7c128b07 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -10,16 +10,32 @@ #include #include "linenoise.h" -typedef void (DebuggerComamnd)(struct ARMDebugger*); +struct DebugVector { + struct DebugVector* next; + enum DVType { + ERROR_TYPE, + INT_TYPE, + CHAR_TYPE + } type; + union { + int32_t intValue; + const char* charValue; + }; +}; -static void _breakInto(struct ARMDebugger*); -static void _printStatus(struct ARMDebugger*); -static void _quit(struct ARMDebugger*); +typedef void (DebuggerComamnd)(struct ARMDebugger*, struct DebugVector*); + +static void _breakInto(struct ARMDebugger*, struct DebugVector*); +static void _print(struct ARMDebugger*, struct DebugVector*); +static void _printStatus(struct ARMDebugger*, struct DebugVector*); +static void _quit(struct ARMDebugger*, struct DebugVector*); struct { const char* name; DebuggerComamnd* command; } debuggerCommands[] = { + { "p", _print }, + { "print", _print }, { "i", _printStatus }, { "info", _printStatus }, { "q", _quit }, @@ -45,13 +61,22 @@ static void _handleDeath(int sig) { printf("No debugger attached!\n"); } -static void _breakInto(struct ARMDebugger* debugger) { +static void _breakInto(struct ARMDebugger* debugger, struct DebugVector* dv) { (void)(debugger); + (void)(dv); sig_t oldSignal = signal(SIGTRAP, _handleDeath); kill(getpid(), SIGTRAP); signal(SIGTRAP, oldSignal); } +static void _print(struct ARMDebugger* debugger, struct DebugVector* dv) { + (void)(debugger); + for ( ; dv; dv = dv->next) { + printf(" %u", dv->intValue); + } + printf("\n"); +} + static inline void _printLine(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode) { // TODO: write a disassembler if (mode == MODE_ARM) { @@ -63,7 +88,8 @@ static inline void _printLine(struct ARMDebugger* debugger, uint32_t address, en } } -static void _printStatus(struct ARMDebugger* debugger) { +static void _printStatus(struct ARMDebugger* debugger, struct DebugVector* dv) { + (void)(dv); int r; for (r = 0; r < 4; ++r) { printf("%08X %08X %08X %08X\n", @@ -83,15 +109,260 @@ static void _printStatus(struct ARMDebugger* debugger) { _printLine(debugger, debugger->cpu->gprs[ARM_PC] - instructionLength, mode); } -static void _quit(struct ARMDebugger* debugger) { +static void _quit(struct ARMDebugger* debugger, struct DebugVector* dv) { + (void)(dv); debugger->state = DEBUGGER_EXITING; } +enum _DVParseState { + PARSE_ERROR = -1, + PARSE_ROOT = 0, + PARSE_EXPECT_REGISTER, + PARSE_EXPECT_REGISTER_2, + PARSE_EXPECT_LR, + PARSE_EXPECT_PC, + PARSE_EXPECT_SP, + PARSE_EXPECT_DECIMAL, + PARSE_EXPECT_HEX, + PARSE_EXPECT_PREFIX, + PARSE_EXPECT_SUFFIX, +}; + +static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* string) { + if (!string || !string[0]) { + return 0; + } + + enum _DVParseState state = PARSE_ROOT; + struct DebugVector dvTemp = { .type = INT_TYPE }; + uint32_t current = 0; + + while (string[0] && string[0] != ' ' && state != PARSE_ERROR) { + char token = string[0]; + ++string; + switch (state) { + case PARSE_ROOT: + switch (token) { + case 'r': + state = PARSE_EXPECT_REGISTER; + break; + case 'p': + state = PARSE_EXPECT_PC; + break; + case 's': + state = PARSE_EXPECT_SP; + break; + case 'l': + state = PARSE_EXPECT_LR; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + state = PARSE_EXPECT_DECIMAL; + current = token - '0'; + break; + case '0': + state = PARSE_EXPECT_PREFIX; + break; + case '$': + state = PARSE_EXPECT_HEX; + current = 0; + break; + default: + state = PARSE_ERROR; + break; + }; + break; + case PARSE_EXPECT_LR: + switch (token) { + case 'r': + current = debugger->cpu->gprs[ARM_LR]; + state = PARSE_EXPECT_SUFFIX; + break; + default: + state = PARSE_ERROR; + break; + } + break; + case PARSE_EXPECT_PC: + switch (token) { + case 'c': + current = debugger->cpu->gprs[ARM_PC]; + state = PARSE_EXPECT_SUFFIX; + break; + default: + state = PARSE_ERROR; + break; + } + break; + case PARSE_EXPECT_SP: + switch (token) { + case 'p': + current = debugger->cpu->gprs[ARM_SP]; + state = PARSE_EXPECT_SUFFIX; + break; + default: + state = PARSE_ERROR; + break; + } + break; + case PARSE_EXPECT_REGISTER: + switch (token) { + case '0': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + current = debugger->cpu->gprs[token - '0']; + state = PARSE_EXPECT_SUFFIX; + break; + case '1': + state = PARSE_EXPECT_REGISTER_2; + break; + default: + state = PARSE_ERROR; + break; + } + break; + case PARSE_EXPECT_REGISTER_2: + switch (token) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + current = debugger->cpu->gprs[token - '0' + 10]; + state = PARSE_EXPECT_SUFFIX; + break; + default: + state = PARSE_ERROR; + break; + } + break; + case PARSE_EXPECT_DECIMAL: + switch (token) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // TODO: handle overflow + current *= 10; + current += token - '0'; + break; + default: + state = PARSE_ERROR; + } + break; + case PARSE_EXPECT_HEX: + switch (token) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // TODO: handle overflow + current *= 16; + current += token - '0'; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + // TODO: handle overflow + current *= 16; + current += token - 'A' + 10; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + // TODO: handle overflow + current *= 16; + current += token - 'a' + 10; + break; + default: + state = PARSE_ERROR; + break; + } + break; + case PARSE_EXPECT_PREFIX: + switch (token) { + case 'X': + case 'x': + current = 0; + state = PARSE_EXPECT_HEX; + break; + default: + state = PARSE_ERROR; + break; + } + break; + case PARSE_EXPECT_SUFFIX: + // TODO + state = PARSE_ERROR; + break; + case PARSE_ERROR: + // This shouldn't be reached + break; + } + } + + struct DebugVector* dv = malloc(sizeof(struct DebugVector)); + if (state == PARSE_ERROR) { + dv->type = ERROR_TYPE; + dv->next = 0; + } else { + dvTemp.intValue = current; + *dv = dvTemp; + if (string[0] == ' ') { + dv->next = _DVParse(debugger, string + 1); + } + } + return dv; +} + +static void _DVFree(struct DebugVector* dv) { + struct DebugVector* next; + while (dv) { + next = dv->next; + free(dv); + dv = next; + } +} + static void _parse(struct ARMDebugger* debugger, const char* line) { char* firstSpace = strchr(line, ' '); size_t cmdLength; + struct DebugVector* dv = 0; if (firstSpace) { - cmdLength = line - firstSpace; + cmdLength = firstSpace - line; + dv = _DVParse(debugger, firstSpace + 1); } else { cmdLength = strlen(line); } @@ -103,12 +374,15 @@ static void _parse(struct ARMDebugger* debugger, const char* line) { continue; } if (strncasecmp(name, line, cmdLength) == 0) { - debuggerCommands[i].command(debugger); + debuggerCommands[i].command(debugger, dv); + _DVFree(dv); + linenoiseHistoryAdd(line); return; } } + _DVFree(dv); ARMRun(debugger->cpu); - _printStatus(debugger); + _printStatus(debugger, 0); } void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) { @@ -117,7 +391,7 @@ void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) { void ARMDebuggerEnter(struct ARMDebugger* debugger) { char* line; - _printStatus(debugger); + _printStatus(debugger, 0); while ((line = linenoise("> "))) { _parse(debugger, line); free(line);