all repos — mgba @ f96b08c52f6effe8cb882a2f4cf7b03c1dfec38e

mGBA Game Boy Advance Emulator

src/debugger/debugger.c (view raw)

  1/* Copyright (c) 2013-2016 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba/debugger/debugger.h>
  7
  8#include <mgba/core/core.h>
  9
 10#include <mgba/internal/debugger/cli-debugger.h>
 11#include <mgba/internal/debugger/symbols.h>
 12
 13#ifdef USE_GDB_STUB
 14#include <mgba/internal/debugger/gdb-stub.h>
 15#endif
 16
 17#if ENABLE_SCRIPTING
 18#include <mgba/core/scripting.h>
 19#endif
 20
 21const uint32_t DEBUGGER_ID = 0xDEADBEEF;
 22
 23mLOG_DEFINE_CATEGORY(DEBUGGER, "Debugger", "core.debugger");
 24
 25DEFINE_VECTOR(mBreakpointList, struct mBreakpoint);
 26DEFINE_VECTOR(mWatchpointList, struct mWatchpoint);
 27
 28static void mDebuggerInit(void* cpu, struct mCPUComponent* component);
 29static void mDebuggerDeinit(struct mCPUComponent* component);
 30
 31struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore* core) {
 32	if (!core->supportsDebuggerType(core, type)) {
 33		return NULL;
 34	}
 35
 36	union DebugUnion {
 37		struct mDebugger d;
 38		struct CLIDebugger cli;
 39#ifdef USE_GDB_STUB
 40		struct GDBStub gdb;
 41#endif
 42	};
 43
 44	union DebugUnion* debugger = malloc(sizeof(union DebugUnion));
 45	memset(debugger, 0, sizeof(*debugger));
 46
 47	switch (type) {
 48	case DEBUGGER_CLI:
 49		CLIDebuggerCreate(&debugger->cli);
 50		struct CLIDebuggerSystem* sys = core->cliDebuggerSystem(core);
 51		CLIDebuggerAttachSystem(&debugger->cli, sys);
 52		break;
 53	case DEBUGGER_GDB:
 54#ifdef USE_GDB_STUB
 55		GDBStubCreate(&debugger->gdb);
 56		GDBStubListen(&debugger->gdb, 2345, 0);
 57		break;
 58#endif
 59	case DEBUGGER_NONE:
 60	case DEBUGGER_CUSTOM:
 61	case DEBUGGER_MAX:
 62		free(debugger);
 63		return 0;
 64		break;
 65	}
 66
 67	return &debugger->d;
 68}
 69
 70void mDebuggerAttach(struct mDebugger* debugger, struct mCore* core) {
 71	debugger->d.id = DEBUGGER_ID;
 72	debugger->d.init = mDebuggerInit;
 73	debugger->d.deinit = mDebuggerDeinit;
 74	debugger->core = core;
 75	if (!debugger->core->symbolTable) {
 76		debugger->core->loadSymbols(debugger->core, NULL);
 77	}
 78	debugger->platform = core->debuggerPlatform(core);
 79	debugger->platform->p = debugger;
 80	core->attachDebugger(core, debugger);
 81}
 82
 83void mDebuggerRun(struct mDebugger* debugger) {
 84	switch (debugger->state) {
 85	case DEBUGGER_RUNNING:
 86		if (!debugger->platform->hasBreakpoints(debugger->platform)) {
 87			debugger->core->runLoop(debugger->core);
 88		} else {
 89			debugger->core->step(debugger->core);
 90			debugger->platform->checkBreakpoints(debugger->platform);
 91		}
 92		break;
 93	case DEBUGGER_CALLBACK:
 94		debugger->core->step(debugger->core);
 95		debugger->platform->checkBreakpoints(debugger->platform);
 96		debugger->custom(debugger);
 97		break;
 98	case DEBUGGER_PAUSED:
 99		if (debugger->paused) {
100			debugger->paused(debugger);
101		} else {
102			debugger->state = DEBUGGER_RUNNING;
103		}
104		break;
105	case DEBUGGER_SHUTDOWN:
106		return;
107	}
108}
109
110void mDebuggerRunFrame(struct mDebugger* debugger) {
111	int32_t frame = debugger->core->frameCounter(debugger->core);
112	do {
113		mDebuggerRun(debugger);
114	} while (debugger->core->frameCounter(debugger->core) == frame);
115}
116
117void mDebuggerEnter(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
118	debugger->state = DEBUGGER_PAUSED;
119	if (debugger->platform->entered) {
120		debugger->platform->entered(debugger->platform, reason, info);
121	}
122#ifdef ENABLE_SCRIPTING
123	if (debugger->bridge) {
124		mScriptBridgeDebuggerEntered(debugger->bridge, reason, info);
125	}
126#endif
127}
128
129static void mDebuggerInit(void* cpu, struct mCPUComponent* component) {
130	struct mDebugger* debugger = (struct mDebugger*) component;
131	debugger->state = DEBUGGER_RUNNING;
132	debugger->platform->init(cpu, debugger->platform);
133	if (debugger->init) {
134		debugger->init(debugger);
135	}
136}
137
138static void mDebuggerDeinit(struct mCPUComponent* component) {
139	struct mDebugger* debugger = (struct mDebugger*) component;
140	if (debugger->deinit) {
141		debugger->deinit(debugger);
142	}
143	debugger->platform->deinit(debugger->platform);
144}
145
146bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int32_t* value, int* segment) {
147	*segment = -1;
148#ifdef ENABLE_SCRIPTING
149	if (debugger->bridge && mScriptBridgeLookupSymbol(debugger->bridge, name, value)) {
150		return true;
151	}
152#endif
153	if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, value, segment)) {
154		return true;
155	}
156	if (debugger->core->lookupIdentifier(debugger->core, name, value, segment)) {
157		return true;
158	}
159	if (debugger->platform && debugger->platform->getRegister(debugger->platform, name, value)) {
160		return true;
161	}
162	return false;
163}