all repos — mgba @ 201da5adacddb6db11e023a23247e94e774260d5

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