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