src/debugger/debugger.c (view raw)
1/* Copyright (c) 2013-2014 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 "arm.h"
9
10#include "memory-debugger.h"
11
12const uint32_t ARM_DEBUGGER_ID = 0xDEADBEEF;
13
14static void _checkBreakpoints(struct ARMDebugger* debugger) {
15 struct DebugBreakpoint* breakpoint;
16 int instructionLength;
17 enum ExecutionMode mode = debugger->cpu->cpsr.t;
18 if (mode == MODE_ARM) {
19 instructionLength = WORD_SIZE_ARM;
20 } else {
21 instructionLength = WORD_SIZE_THUMB;
22 }
23 for (breakpoint = debugger->breakpoints; breakpoint; breakpoint = breakpoint->next) {
24 if (breakpoint->address + instructionLength == (uint32_t) debugger->cpu->gprs[ARM_PC]) {
25 ARMDebuggerEnter(debugger, DEBUGGER_ENTER_BREAKPOINT);
26 break;
27 }
28 }
29}
30
31static void ARMDebuggerInit(struct ARMCore*, struct ARMComponent*);
32static void ARMDebuggerDeinit(struct ARMComponent*);
33
34void ARMDebuggerCreate(struct ARMDebugger* debugger) {
35 debugger->d.id = ARM_DEBUGGER_ID;
36 debugger->d.init = ARMDebuggerInit;
37 debugger->d.deinit = ARMDebuggerDeinit;
38}
39
40void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) {
41 struct ARMDebugger* debugger = (struct ARMDebugger*) component;
42 debugger->cpu = cpu;
43 debugger->state = DEBUGGER_RUNNING;
44 debugger->breakpoints = 0;
45 debugger->originalMemory = cpu->memory;
46 debugger->watchpoints = 0;
47 if (debugger->init) {
48 debugger->init(debugger);
49 }
50}
51
52void ARMDebuggerDeinit(struct ARMComponent* component) {
53 struct ARMDebugger* debugger = (struct ARMDebugger*) component;
54 debugger->deinit(debugger);
55}
56
57void ARMDebuggerRun(struct ARMDebugger* debugger) {
58 if (debugger->state == DEBUGGER_EXITING) {
59 debugger->state = DEBUGGER_RUNNING;
60 }
61 while (debugger->state < DEBUGGER_EXITING) {
62 if (!debugger->breakpoints && !debugger->watchpoints) {
63 while (debugger->state == DEBUGGER_RUNNING) {
64 ARMRunLoop(debugger->cpu);
65 }
66 } else if (!debugger->breakpoints) {
67 while (debugger->state == DEBUGGER_RUNNING) {
68 ARMRun(debugger->cpu);
69 }
70 } else {
71 while (debugger->state == DEBUGGER_RUNNING) {
72 ARMRun(debugger->cpu);
73 _checkBreakpoints(debugger);
74 }
75 }
76 switch (debugger->state) {
77 case DEBUGGER_RUNNING:
78 break;
79 case DEBUGGER_CUSTOM:
80 while (debugger->state == DEBUGGER_CUSTOM) {
81 ARMRun(debugger->cpu);
82 _checkBreakpoints(debugger);
83 debugger->custom(debugger);
84 }
85 break;
86 case DEBUGGER_PAUSED:
87 if (debugger->paused) {
88 debugger->paused(debugger);
89 } else {
90 debugger->state = DEBUGGER_RUNNING;
91 }
92 break;
93 case DEBUGGER_EXITING:
94 case DEBUGGER_SHUTDOWN:
95 return;
96 }
97 }
98}
99
100void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason reason) {
101 debugger->state = DEBUGGER_PAUSED;
102 if (debugger->entered) {
103 debugger->entered(debugger, reason);
104 }
105}
106
107void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
108 struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
109 breakpoint->address = address;
110 breakpoint->next = debugger->breakpoints;
111 debugger->breakpoints = breakpoint;
112}
113
114void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
115 struct DebugBreakpoint** previous = &debugger->breakpoints;
116 struct DebugBreakpoint* breakpoint;
117 for (; (breakpoint = *previous); previous = &breakpoint->next) {
118 if (breakpoint->address == address) {
119 *previous = breakpoint->next;
120 free(breakpoint);
121 }
122 }
123}
124
125void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
126 if (!debugger->watchpoints) {
127 ARMDebuggerInstallMemoryShim(debugger);
128 }
129 struct DebugBreakpoint* watchpoint = malloc(sizeof(struct DebugBreakpoint));
130 watchpoint->address = address;
131 watchpoint->next = debugger->watchpoints;
132 debugger->watchpoints = watchpoint;
133}
134
135void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
136 struct DebugBreakpoint** previous = &debugger->watchpoints;
137 struct DebugBreakpoint* breakpoint;
138 for (; (breakpoint = *previous); previous = &breakpoint->next) {
139 if (breakpoint->address == address) {
140 *previous = breakpoint->next;
141 free(breakpoint);
142 }
143 }
144 if (!debugger->watchpoints) {
145 ARMDebuggerRemoveMemoryShim(debugger);
146 }
147}