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 debugger->platform = core->debuggerPlatform(core);
66 debugger->platform->p = debugger;
67 core->attachDebugger(core, debugger);
68}
69
70void mDebuggerRun(struct mDebugger* debugger) {
71 switch (debugger->state) {
72 case DEBUGGER_RUNNING:
73 if (!debugger->platform->hasBreakpoints(debugger->platform)) {
74 debugger->core->runLoop(debugger->core);
75 } else {
76 debugger->core->step(debugger->core);
77 debugger->platform->checkBreakpoints(debugger->platform);
78 }
79 break;
80 case DEBUGGER_CUSTOM:
81 debugger->core->step(debugger->core);
82 debugger->platform->checkBreakpoints(debugger->platform);
83 debugger->custom(debugger);
84 break;
85 case DEBUGGER_PAUSED:
86 if (debugger->paused) {
87 debugger->paused(debugger);
88 } else {
89 debugger->state = DEBUGGER_RUNNING;
90 }
91 break;
92 case DEBUGGER_SHUTDOWN:
93 return;
94 }
95}
96
97void mDebuggerEnter(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
98 debugger->state = DEBUGGER_PAUSED;
99 if (debugger->platform->entered) {
100 debugger->platform->entered(debugger->platform, reason, info);
101 }
102}
103
104static void mDebuggerInit(void* cpu, struct mCPUComponent* component) {
105 struct mDebugger* debugger = (struct mDebugger*) component;
106 debugger->state = DEBUGGER_RUNNING;
107 debugger->platform->init(cpu, debugger->platform);
108 if (debugger->init) {
109 debugger->init(debugger);
110 }
111}
112
113static void mDebuggerDeinit(struct mCPUComponent* component) {
114 struct mDebugger* debugger = (struct mDebugger*) component;
115 if (debugger->deinit) {
116 debugger->deinit(debugger);
117 }
118 debugger->platform->deinit(debugger->platform);
119}