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