Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C++] Hardware breakpoint op data

Pagina: 1
Acties:

  • evolution536
  • Registratie: Maart 2009
  • Laatst online: 05-06-2024
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.

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.

  • _js_
  • Registratie: Oktober 2002
  • Laatst online: 25-10 14:28
Wat je ziet is wel hoe het hoort, het staat opgesomd in tabel 17-2 van boek 3b deel 2, een trap stopt op de volgende instructie, een fault op de instructie die de exception gooit.

Breakpoints op read/write zijn traps en daar komt de processor pas achter wanneer die al lang bezig is met het uitvoeren van de instructie die het geheugen raakt, en stopt pas daarna.

  • evolution536
  • Registratie: Maart 2009
  • Laatst online: 05-06-2024
_js_ schreef op donderdag 06 februari 2014 @ 15:31:
Wat je ziet is wel hoe het hoort, het staat opgesomd in tabel 17-2 van boek 3b deel 2, een trap stopt op de volgende instructie, een fault op de instructie die de exception gooit.

Breakpoints op read/write zijn traps en daar komt de processor pas achter wanneer die al lang bezig is met het uitvoeren van de instructie die het geheugen raakt, en stopt pas daarna.
Dankjewel voor je reactie! Ik heb het verschil tussen faults en traps even helemaal gemist. Middels de flags in DR6 heb ik exact wat ik graag zou willen.

Dankjewel :)