all repos — mgba @ 67750e351b484d0898ee03e1886216b86607fbb8

mGBA Game Boy Advance Emulator

src/debugger.c (view raw)

  1#include "debugger.h"
  2
  3#include "arm.h"
  4
  5#include <signal.h>
  6#include <stdio.h>
  7#include <stdarg.h>
  8#include <stdlib.h>
  9#include <strings.h>
 10#include <unistd.h>
 11#include "linenoise.h"
 12
 13typedef void (DebuggerComamnd)(struct ARMDebugger*);
 14
 15static void _breakInto(struct ARMDebugger*);
 16static void _printStatus(struct ARMDebugger*);
 17static void _quit(struct ARMDebugger*);
 18
 19struct {
 20	const char* name;
 21	DebuggerComamnd* command;
 22} debuggerCommands[] = {
 23	{ "i", _printStatus },
 24	{ "info", _printStatus },
 25	{ "q", _quit },
 26	{ "quit", _quit },
 27	{ "status", _printStatus },
 28	{ "x", _breakInto },
 29	{ 0, 0 }
 30};
 31
 32static inline void _printPSR(union PSR psr) {
 33	printf("%08X [%c%c%c%c%c%c%c]\n", psr.packed,
 34		psr.n ? 'N' : '-',
 35		psr.z ? 'Z' : '-',
 36		psr.c ? 'C' : '-',
 37		psr.v ? 'V' : '-',
 38		psr.i ? 'I' : '-',
 39		psr.f ? 'F' : '-',
 40		psr.t ? 'T' : '-');
 41}
 42
 43static void _handleDeath(int sig) {
 44	(void)(sig);
 45	printf("No debugger attached!\n");
 46}
 47
 48static void _breakInto(struct ARMDebugger* debugger) {
 49	(void)(debugger);
 50	sig_t oldSignal = signal(SIGTRAP, _handleDeath);
 51	kill(getpid(), SIGTRAP);
 52	signal(SIGTRAP, oldSignal);
 53}
 54
 55static void _printStatus(struct ARMDebugger* debugger) {
 56	int r;
 57	for (r = 0; r < 4; ++r) {
 58		printf("%08X %08X %08X %08X\n",
 59			debugger->cpu->gprs[r << 2],
 60			debugger->cpu->gprs[(r << 2) + 1],
 61			debugger->cpu->gprs[(r << 2) + 2],
 62			debugger->cpu->gprs[(r << 2) + 3]);
 63	}
 64	_printPSR(debugger->cpu->cpsr);
 65}
 66
 67static void _quit(struct ARMDebugger* debugger) {
 68	debugger->state = DEBUGGER_EXITING;
 69}
 70
 71static void _parse(struct ARMDebugger* debugger, const char* line) {
 72	char* firstSpace = strchr(line, ' ');
 73	size_t cmdLength;
 74	if (firstSpace) {
 75		cmdLength = line - firstSpace;
 76	} else {
 77		cmdLength = strlen(line);
 78	}
 79
 80	int i;
 81	const char* name;
 82	for (i = 0; (name = debuggerCommands[i].name); ++i) {
 83		if (strlen(name) != cmdLength) {
 84			continue;
 85		}
 86		if (strncasecmp(name, line, cmdLength) == 0) {
 87			debuggerCommands[i].command(debugger);
 88			return;
 89		}
 90	}
 91	ARMRun(debugger->cpu);
 92	_printStatus(debugger);
 93}
 94
 95void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
 96	debugger->cpu = cpu;
 97}
 98
 99void ARMDebuggerEnter(struct ARMDebugger* debugger) {
100	char* line;
101	_printStatus(debugger);
102	while ((line = linenoise("> "))) {
103		_parse(debugger, line);
104		free(line);
105		switch (debugger->state) {
106		case DEBUGGER_EXITING:
107			return;
108		default:
109			break;
110		}
111	}
112}