all repos — mgba @ 5134e39681e4cd9c0241b8d08533ef4d75054171

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
 12#ifdef USE_GDB_STUB
 13#include <mgba/internal/debugger/gdb-stub.h>
 14#endif
 15
 16#if ENABLE_SCRIPTING
 17#include <mgba/core/scripting.h>
 18#endif
 19
 20const uint32_t DEBUGGER_ID = 0xDEADBEEF;
 21
 22mLOG_DEFINE_CATEGORY(DEBUGGER, "Debugger", "core.debugger");
 23
 24static void mDebuggerInit(void* cpu, struct mCPUComponent* component);
 25static void mDebuggerDeinit(struct mCPUComponent* component);
 26
 27struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore* core) {
 28	if (!core->supportsDebuggerType(core, type)) {
 29		return NULL;
 30	}
 31
 32	union DebugUnion {
 33		struct mDebugger d;
 34		struct CLIDebugger cli;
 35#ifdef USE_GDB_STUB
 36		struct GDBStub gdb;
 37#endif
 38	};
 39
 40	union DebugUnion* debugger = malloc(sizeof(union DebugUnion));
 41	memset(debugger, 0, sizeof(*debugger));
 42
 43	switch (type) {
 44	case DEBUGGER_CLI:
 45		CLIDebuggerCreate(&debugger->cli);
 46		struct CLIDebuggerSystem* sys = core->cliDebuggerSystem(core);
 47		CLIDebuggerAttachSystem(&debugger->cli, sys);
 48		break;
 49#ifdef USE_GDB_STUB
 50	case DEBUGGER_GDB:
 51		GDBStubCreate(&debugger->gdb);
 52		GDBStubListen(&debugger->gdb, 2345, 0);
 53		break;
 54#endif
 55	case DEBUGGER_NONE:
 56	case DEBUGGER_MAX:
 57		free(debugger);
 58		return 0;
 59		break;
 60	}
 61
 62	return &debugger->d;
 63}
 64
 65void mDebuggerAttach(struct mDebugger* debugger, struct mCore* core) {
 66	debugger->d.id = DEBUGGER_ID;
 67	debugger->d.init = mDebuggerInit;
 68	debugger->d.deinit = mDebuggerDeinit;
 69	debugger->core = core;
 70	if (!debugger->core->symbolTable) {
 71		debugger->core->loadSymbols(debugger->core, NULL);
 72	}
 73	debugger->platform = core->debuggerPlatform(core);
 74	debugger->platform->p = debugger;
 75	core->attachDebugger(core, debugger);
 76}
 77
 78void mDebuggerRun(struct mDebugger* debugger) {
 79	switch (debugger->state) {
 80	case DEBUGGER_RUNNING:
 81		if (!debugger->platform->hasBreakpoints(debugger->platform)) {
 82			debugger->core->runLoop(debugger->core);
 83		} else {
 84			debugger->core->step(debugger->core);
 85			debugger->platform->checkBreakpoints(debugger->platform);
 86		}
 87		break;
 88	case DEBUGGER_CUSTOM:
 89		debugger->core->step(debugger->core);
 90		debugger->platform->checkBreakpoints(debugger->platform);
 91		debugger->custom(debugger);
 92		break;
 93	case DEBUGGER_PAUSED:
 94		if (debugger->paused) {
 95			debugger->paused(debugger);
 96		} else {
 97			debugger->state = DEBUGGER_RUNNING;
 98		}
 99		break;
100	case DEBUGGER_SHUTDOWN:
101		return;
102	}
103}
104
105void mDebuggerRunFrame(struct mDebugger* debugger) {
106	int32_t frame = debugger->core->frameCounter(debugger->core);
107	do {
108		mDebuggerRun(debugger);
109	} while (debugger->core->frameCounter(debugger->core) == frame);
110}
111
112void mDebuggerEnter(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
113	debugger->state = DEBUGGER_PAUSED;
114	if (debugger->platform->entered) {
115		debugger->platform->entered(debugger->platform, reason, info);
116	}
117#ifdef ENABLE_SCRIPTING
118	if (debugger->bridge) {
119		mScriptBridgeDebuggerEntered(debugger->bridge, reason, info);
120	}
121#endif
122}
123
124static void mDebuggerInit(void* cpu, struct mCPUComponent* component) {
125	struct mDebugger* debugger = (struct mDebugger*) component;
126	debugger->state = DEBUGGER_RUNNING;
127	debugger->platform->init(cpu, debugger->platform);
128	if (debugger->init) {
129		debugger->init(debugger);
130	}
131}
132
133static void mDebuggerDeinit(struct mCPUComponent* component) {
134	struct mDebugger* debugger = (struct mDebugger*) component;
135	if (debugger->deinit) {
136		debugger->deinit(debugger);
137	}
138	debugger->platform->deinit(debugger->platform);
139}