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 struct DebuggerEntryInfo info = {
26 .address = breakpoint->address
27 };
28 ARMDebuggerEnter(debugger, DEBUGGER_ENTER_BREAKPOINT, &info);
29 break;
30 }
31 }
32}
33
34static void ARMDebuggerInit(struct ARMCore*, struct ARMComponent*);
35static void ARMDebuggerDeinit(struct ARMComponent*);
36
37void ARMDebuggerCreate(struct ARMDebugger* debugger) {
38 debugger->d.id = ARM_DEBUGGER_ID;
39 debugger->d.init = ARMDebuggerInit;
40 debugger->d.deinit = ARMDebuggerDeinit;
41}
42
43void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) {
44 struct ARMDebugger* debugger = (struct ARMDebugger*) component;
45 debugger->cpu = cpu;
46 debugger->state = DEBUGGER_RUNNING;
47 debugger->breakpoints = 0;
48 debugger->originalMemory = cpu->memory;
49 debugger->watchpoints = 0;
50 if (debugger->init) {
51 debugger->init(debugger);
52 }
53}
54
55void ARMDebuggerDeinit(struct ARMComponent* component) {
56 struct ARMDebugger* debugger = (struct ARMDebugger*) component;
57 debugger->deinit(debugger);
58}
59
60void ARMDebuggerRun(struct ARMDebugger* debugger) {
61 switch (debugger->state) {
62 case DEBUGGER_RUNNING:
63 if (!debugger->breakpoints && !debugger->watchpoints) {
64 ARMRunLoop(debugger->cpu);
65 } else {
66 ARMRun(debugger->cpu);
67 _checkBreakpoints(debugger);
68 }
69 break;
70 case DEBUGGER_CUSTOM:
71 ARMRun(debugger->cpu);
72 _checkBreakpoints(debugger);
73 debugger->custom(debugger);
74 break;
75 case DEBUGGER_PAUSED:
76 if (debugger->paused) {
77 debugger->paused(debugger);
78 } else {
79 debugger->state = DEBUGGER_RUNNING;
80 }
81 break;
82 case DEBUGGER_SHUTDOWN:
83 return;
84 }
85}
86
87void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) {
88 debugger->state = DEBUGGER_PAUSED;
89 if (debugger->entered) {
90 debugger->entered(debugger, reason, info);
91 }
92}
93
94void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
95 struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
96 breakpoint->address = address;
97 breakpoint->next = debugger->breakpoints;
98 debugger->breakpoints = breakpoint;
99}
100
101void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
102 struct DebugBreakpoint** previous = &debugger->breakpoints;
103 struct DebugBreakpoint* breakpoint;
104 for (; (breakpoint = *previous); previous = &breakpoint->next) {
105 if (breakpoint->address == address) {
106 *previous = breakpoint->next;
107 free(breakpoint);
108 }
109 }
110}
111
112void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
113 if (!debugger->watchpoints) {
114 ARMDebuggerInstallMemoryShim(debugger);
115 }
116 struct DebugWatchpoint* watchpoint = malloc(sizeof(struct DebugWatchpoint));
117 watchpoint->address = address;
118 watchpoint->next = debugger->watchpoints;
119 debugger->watchpoints = watchpoint;
120}
121
122void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
123 struct DebugWatchpoint** previous = &debugger->watchpoints;
124 struct DebugWatchpoint* breakpoint;
125 for (; (breakpoint = *previous); previous = &breakpoint->next) {
126 if (breakpoint->address == address) {
127 *previous = breakpoint->next;
128 free(breakpoint);
129 }
130 }
131 if (!debugger->watchpoints) {
132 ARMDebuggerRemoveMemoryShim(debugger);
133 }
134}