all repos — mgba @ 108b0fc867292c554a6ef9b643fc39209561e35a

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
 25static void mDebuggerInit(void* cpu, struct mCPUComponent* component);
 26static void mDebuggerDeinit(struct mCPUComponent* component);
 27
 28struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore* core) {
 29	if (!core->supportsDebuggerType(core, type)) {
 30		return NULL;
 31	}
 32
 33	union DebugUnion {
 34		struct mDebugger d;
 35		struct CLIDebugger cli;
 36#ifdef USE_GDB_STUB
 37		struct GDBStub gdb;
 38#endif
 39	};
 40
 41	union DebugUnion* debugger = malloc(sizeof(union DebugUnion));
 42	memset(debugger, 0, sizeof(*debugger));
 43
 44	switch (type) {
 45	case DEBUGGER_CLI:
 46		CLIDebuggerCreate(&debugger->cli);
 47		struct CLIDebuggerSystem* sys = core->cliDebuggerSystem(core);
 48		CLIDebuggerAttachSystem(&debugger->cli, sys);
 49		break;
 50#ifdef USE_GDB_STUB
 51	case DEBUGGER_GDB:
 52		GDBStubCreate(&debugger->gdb);
 53		GDBStubListen(&debugger->gdb, 2345, 0);
 54		break;
 55#endif
 56	case DEBUGGER_NONE:
 57	case DEBUGGER_MAX:
 58		free(debugger);
 59		return 0;
 60		break;
 61	}
 62
 63	return &debugger->d;
 64}
 65
 66void mDebuggerAttach(struct mDebugger* debugger, struct mCore* core) {
 67	debugger->d.id = DEBUGGER_ID;
 68	debugger->d.init = mDebuggerInit;
 69	debugger->d.deinit = mDebuggerDeinit;
 70	debugger->core = core;
 71	if (!debugger->core->symbolTable) {
 72		debugger->core->loadSymbols(debugger->core, NULL);
 73	}
 74	debugger->platform = core->debuggerPlatform(core);
 75	debugger->platform->p = debugger;
 76	core->attachDebugger(core, debugger);
 77}
 78
 79void mDebuggerRun(struct mDebugger* debugger) {
 80	switch (debugger->state) {
 81	case DEBUGGER_RUNNING:
 82		if (!debugger->platform->hasBreakpoints(debugger->platform)) {
 83			debugger->core->runLoop(debugger->core);
 84		} else {
 85			debugger->core->step(debugger->core);
 86			debugger->platform->checkBreakpoints(debugger->platform);
 87		}
 88		break;
 89	case DEBUGGER_CUSTOM:
 90		debugger->core->step(debugger->core);
 91		debugger->platform->checkBreakpoints(debugger->platform);
 92		debugger->custom(debugger);
 93		break;
 94	case DEBUGGER_PAUSED:
 95		if (debugger->paused) {
 96			debugger->paused(debugger);
 97		} else {
 98			debugger->state = DEBUGGER_RUNNING;
 99		}
100		break;
101	case DEBUGGER_SHUTDOWN:
102		return;
103	}
104}
105
106void mDebuggerRunFrame(struct mDebugger* debugger) {
107	int32_t frame = debugger->core->frameCounter(debugger->core);
108	do {
109		mDebuggerRun(debugger);
110	} while (debugger->core->frameCounter(debugger->core) == frame);
111}
112
113void mDebuggerEnter(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
114	debugger->state = DEBUGGER_PAUSED;
115	if (debugger->platform->entered) {
116		debugger->platform->entered(debugger->platform, reason, info);
117	}
118#ifdef ENABLE_SCRIPTING
119	if (debugger->bridge) {
120		mScriptBridgeDebuggerEntered(debugger->bridge, reason, info);
121	}
122#endif
123}
124
125static void mDebuggerInit(void* cpu, struct mCPUComponent* component) {
126	struct mDebugger* debugger = (struct mDebugger*) component;
127	debugger->state = DEBUGGER_RUNNING;
128	debugger->platform->init(cpu, debugger->platform);
129	if (debugger->init) {
130		debugger->init(debugger);
131	}
132}
133
134static void mDebuggerDeinit(struct mCPUComponent* component) {
135	struct mDebugger* debugger = (struct mDebugger*) component;
136	if (debugger->deinit) {
137		debugger->deinit(debugger);
138	}
139	debugger->platform->deinit(debugger->platform);
140}
141
142bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int32_t* value, int* segment) {
143	*segment = -1;
144#ifdef ENABLE_SCRIPTING
145	if (debugger->bridge && mScriptBridgeLookupSymbol(debugger->bridge, name, value)) {
146		return true;
147	}
148#endif
149	if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, value, segment)) {
150		return true;
151	}
152	if (debugger->core->lookupIdentifier(debugger->core, name, value, segment)) {
153		return true;
154	}
155	if (debugger->platform && debugger->platform->getRegister(debugger->platform, name, value)) {
156		return true;
157	}
158	return false;
159}