Beste medetweakers,
Ik loop tegen een probleem aan dat ik met de documentatie van Intel tot zover niet heb kunnen oplossen. Ik ben bezig met het ontwikkelen van een hardware-breakpoint systeem waarin het mogelijk is om een breakpoint te zetten op executable code maar ook op data.
De executable breakpoints werken perfect. Echter heb ik wat problemen met de data breakpoints. Het probleem is namelijk dat het exception adress altijd het adres is van de instructie ná de instructie die daadwerkelijk zou moeten breaken. Ik heb de EFlags en flags in DR7 bekeken en geprobeerd maar deze hebben allen niet de invloed die ik had gehoopt. De code van het opzetten van een breakpoint is hieronder zichtbaar. Mijn debugger is bedoeld om zowel 32 bit als 64 bits applicaties te ondersteunen, al hebben beide functies hetzelfde probleem. Vandaar hieronder de 64-bit code, omdat deze een stuk overzichtelijker is.
Ik heb de flags ook gecontroleerd wanneer het breakpoint gezet werd en de EFlags waren 0x202, DR7: 0xF0001.
Kan iemand me misschien een hint geven waarom het wellicht niet zou kunnen werken? Breakpoints met size 1 op executable code werken perfect en ik heb de documentatie van Intel aardig doorgespit. Ik heb ook gekeken of wellicht de RF flag invloed zou hebben op deze code maar aangezien ik daar niets mee doe lijkt me dit vreemd.
Ik loop tegen een probleem aan dat ik met de documentatie van Intel tot zover niet heb kunnen oplossen. Ik ben bezig met het ontwikkelen van een hardware-breakpoint systeem waarin het mogelijk is om een breakpoint te zetten op executable code maar ook op data.
De executable breakpoints werken perfect. Echter heb ik wat problemen met de data breakpoints. Het probleem is namelijk dat het exception adress altijd het adres is van de instructie ná de instructie die daadwerkelijk zou moeten breaken. Ik heb de EFlags en flags in DR7 bekeken en geprobeerd maar deze hebben allen niet de invloed die ik had gehoopt. De code van het opzetten van een breakpoint is hieronder zichtbaar. Mijn debugger is bedoeld om zowel 32 bit als 64 bits applicaties te ondersteunen, al hebben beide functies hetzelfde probleem. Vandaar hieronder de 64-bit code, omdat deze een stuk overzichtelijker is.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
| // Sets bit flags on a specified numeric value. inline void SetBits(DWORD_PTR* dw, const int lowBit, const int bits, const int newValue) { const DWORD_PTR mask = (1 << bits) - 1; *dw = (*dw & ~(mask << lowBit)) | (newValue << lowBit); } bool CryDebugger64::BreakpointRoutine(HardwareBreakpoint* pHwbp) const { HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE, pHwbp->ThreadId[pHwbp->ThreadId.GetCount() - 1]); // Prepare thread context struct and retrieve thread context into it. if (!pHwbp->ProcessorTrapFlag && SuspendThread(hThread) == (DWORD)-1) { return false; } void* ctxBase = VirtualAlloc(NULL, sizeof(CONTEXT) + 8, MEM_COMMIT, PAGE_READWRITE); PCONTEXT ctx = (PCONTEXT)ctxBase; AlignPointer((DWORD_PTR*)&ctx, 8); memset(ctx, 0, sizeof(CONTEXT)); ctx->ContextFlags = CONTEXT_DEBUG_REGISTERS; if (!GetThreadContext(hThread, ctx)) { VirtualFree(ctxBase, 0, MEM_RELEASE); ResumeThread(hThread); return false; } if (pHwbp->MustSet) { unsigned long m_index = 0; // Find available debug register. for (; m_index < 4; ++m_index) { if ((ctx->Dr7 & (1i64 << (m_index * 2))) == 0) { break; } } // If this condition is true, all breakpoints are used, meaning the new breakpoint cannot be set. if (m_index >= 4) { VirtualFree(ctxBase, 0, MEM_RELEASE); return false; } // Set address in selected debug register. switch (m_index) { case 0: ctx->Dr0 = pHwbp->Address; pHwbp->DebugRegister = 0; break; case 1: ctx->Dr1 = pHwbp->Address; pHwbp->DebugRegister = 1; break; case 2: ctx->Dr2 = pHwbp->Address; pHwbp->DebugRegister = 2; break; case 3: ctx->Dr3 = pHwbp->Address; pHwbp->DebugRegister = 3; break; } SetBits(&ctx->Dr7, 16 + (m_index * 4), 2, pHwbp->Type); SetBits(&ctx->Dr7, 18 + (m_index * 4), 2, pHwbp->Size); SetBits(&ctx->Dr7, m_index * 2, 1, 1); } else { switch (pHwbp->DebugRegister) { case 0: ctx->Dr0 = 0; break; case 1: ctx->Dr1 = 0; break; case 2: ctx->Dr2 = 0; break; case 3: ctx->Dr3 = 0; break; } SetBits((DWORD_PTR*)&ctx->Dr7, pHwbp->DebugRegister * 2, 1, 0); pHwbp->DebugRegister = 0; } ctx->Dr6 = 0; // Prepare context struct and set it into the threads context. if (!SetThreadContext(hThread, ctx)) { VirtualFree(ctxBase, 0, MEM_RELEASE); ResumeThread(hThread); return false; } VirtualFree(ctxBase, 0, MEM_RELEASE); // Everything succeeded until now. resume thread and return. if (!pHwbp->ProcessorTrapFlag) { ResumeThread(hThread); } CloseHandle(hThread); return true; } |
Ik heb de flags ook gecontroleerd wanneer het breakpoint gezet werd en de EFlags waren 0x202, DR7: 0xF0001.
Kan iemand me misschien een hint geven waarom het wellicht niet zou kunnen werken? Breakpoints met size 1 op executable code werken perfect en ik heb de documentatie van Intel aardig doorgespit. Ik heb ook gekeken of wellicht de RF flag invloed zou hebben op deze code maar aangezien ik daar niets mee doe lijkt me dit vreemd.