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