src/debugger/memory-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 "memory-debugger.h"
7
8#include "debugger.h"
9
10#include <string.h>
11
12static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width);
13
14#define FIND_DEBUGGER(DEBUGGER, CPU) \
15 { \
16 DEBUGGER = 0; \
17 int i; \
18 for (i = 0; i < CPU->numComponents; ++i) { \
19 if (CPU->components[i]->id == ARM_DEBUGGER_ID) { \
20 DEBUGGER = (struct ARMDebugger*) cpu->components[i]; \
21 break; \
22 } \
23 } \
24 }
25
26#define CREATE_SHIM(NAME, RETURN, TYPES, ARGS...) \
27 static RETURN ARMDebuggerShim_ ## NAME TYPES { \
28 struct ARMDebugger* debugger; \
29 FIND_DEBUGGER(debugger, cpu); \
30 return debugger->originalMemory.NAME(cpu, ARGS); \
31 }
32
33#define CREATE_WATCHPOINT_SHIM(NAME, WIDTH, RETURN, TYPES, ARGS...) \
34 static RETURN ARMDebuggerShim_ ## NAME TYPES { \
35 struct ARMDebugger* debugger; \
36 FIND_DEBUGGER(debugger, cpu); \
37 if (_checkWatchpoints(debugger->watchpoints, address, WIDTH)) { \
38 ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT); \
39 } \
40 return debugger->originalMemory.NAME(cpu, ARGS); \
41 }
42
43CREATE_WATCHPOINT_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
44CREATE_WATCHPOINT_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
45CREATE_WATCHPOINT_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
46CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), address, value, cycleCounter)
47CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), address, value, cycleCounter)
48CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), address, value, cycleCounter)
49CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address)
50
51static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) {
52 width -= 1;
53 for (; watchpoints; watchpoints = watchpoints->next) {
54 if (!((watchpoints->address ^ address) & ~width)) {
55 return true;
56 }
57 }
58 return false;
59}
60
61void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) {
62 debugger->originalMemory = debugger->cpu->memory;
63 debugger->cpu->memory.store32 = ARMDebuggerShim_store32;
64 debugger->cpu->memory.store16 = ARMDebuggerShim_store16;
65 debugger->cpu->memory.store8 = ARMDebuggerShim_store8;
66 debugger->cpu->memory.load32 = ARMDebuggerShim_load32;
67 debugger->cpu->memory.load16 = ARMDebuggerShim_load16;
68 debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
69 debugger->cpu->memory.setActiveRegion = ARMDebuggerShim_setActiveRegion;
70}
71
72void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger) {
73 debugger->cpu->memory.store32 = debugger->originalMemory.store32;
74 debugger->cpu->memory.store16 = debugger->originalMemory.store16;
75 debugger->cpu->memory.store8 = debugger->originalMemory.store8;
76 debugger->cpu->memory.load32 = debugger->originalMemory.load32;
77 debugger->cpu->memory.load16 = debugger->originalMemory.load16;
78 debugger->cpu->memory.load8 = debugger->originalMemory.load8;
79 debugger->cpu->memory.setActiveRegion = debugger->originalMemory.setActiveRegion;
80}