all repos — mgba @ 25b4faef1262e37154e955d21d0fe1befa07e23b

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_SCRIPT:
101#ifdef ENABLE_SCRIPTING
102		mScriptBridgeRun(debugger->bridge);
103#endif
104		if (debugger->state == DEBUGGER_SCRIPT) {
105			debugger->state = DEBUGGER_PAUSED;
106		}
107		break;
108	case DEBUGGER_SHUTDOWN:
109		return;
110	}
111}
112
113void mDebuggerRunFrame(struct mDebugger* debugger) {
114	int32_t frame = debugger->core->frameCounter(debugger->core);
115	do {
116		mDebuggerRun(debugger);
117	} while (debugger->core->frameCounter(debugger->core) == frame);
118}
119
120void mDebuggerEnter(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
121	debugger->state = DEBUGGER_PAUSED;
122	if (debugger->platform->entered) {
123		debugger->platform->entered(debugger->platform, reason, info);
124	}
125}
126
127static void mDebuggerInit(void* cpu, struct mCPUComponent* component) {
128	struct mDebugger* debugger = (struct mDebugger*) component;
129	debugger->state = DEBUGGER_RUNNING;
130	debugger->platform->init(cpu, debugger->platform);
131	if (debugger->init) {
132		debugger->init(debugger);
133	}
134}
135
136static void mDebuggerDeinit(struct mCPUComponent* component) {
137	struct mDebugger* debugger = (struct mDebugger*) component;
138	if (debugger->deinit) {
139		debugger->deinit(debugger);
140	}
141	debugger->platform->deinit(debugger->platform);
142}