root/Cheat Engine/DBKKernel/debugger.c @ 298

Revision 298, 37.9 kB (checked in by dark_byte, 9 months ago)

fix scan when first splitup buffer is bigger than the rest
fix unhooking interrupts

Line 
1/*
2debugger.c:
3This unit will handle all debugging related code, from hooking, to handling interrupts
4*/
5#pragma warning( disable: 4103)
6#include "ntifs.h"
7#include <windef.h>
8
9#include "DBKFunc.h"
10#include "interruptHook.h"
11
12#include "debugger.h"
13
14#ifdef AMD64 
15extern void interrupt1_asmentry( void ); //declared in debuggera.asm
16#else
17
18void interrupt1_asmentry( void );
19#endif
20
21
22
23
24
25volatile struct
26{
27        BOOL            isDebugging;            //TRUE if a process is currently being debugged
28        DWORD           debuggedProcessID;      //The processID that is currently debugger
29        struct {
30                BOOL            active;
31                UINT_PTR        address;                //Up to 4 addresses to break on
32                BreakType       breakType;              //What type of breakpoint for each seperate address
33                BreakLength breakLength;        //How many bytes does this breakpoint look at
34        } breakpoint[4];
35
36        //...
37        BOOL globalDebug;                       //If set all threads of every process will raise an interrupt on taskswitch
38
39        //while debugging:
40        UINT_PTR *LastStackPointer;
41        UINT_PTR *LastRealDebugRegisters;
42        HANDLE LastThreadID;
43        BOOL handledlastevent;
44
45        volatile struct {               
46                UINT_PTR DR0;
47                UINT_PTR DR1;
48                UINT_PTR DR2;
49                UINT_PTR DR3;
50                UINT_PTR DR6;
51                UINT_PTR DR7;
52                UINT_PTR reserved;
53                volatile int inEpilogue; //if set the global debug bit does no faking
54        } FakedDebugRegisterState[256];
55
56} DebuggerState;
57
58
59KEVENT debugger_event_WaitForContinue; //event for kernelmode. Waits till it's set by usermode (usermode function: DBK_Continue_Debug_Event sets it)
60KEVENT debugger_event_CanBreak; //event for kernelmode. Waits till a break has been handled so a new one can enter
61KEVENT debugger_event_WaitForDebugEvent; //event for usermode. Waits till it's set by a debugged event
62
63DebugReg7 debugger_dr7_getValue(void);
64void debugger_dr7_setValue(DebugReg7 value);
65DebugReg6 debugger_dr6_getValue(void);
66
67JUMPBACK Int1JumpBackLocation;
68
69
70void debugger_dr7_setGD(int state)
71{
72
73        DebugReg7 _dr7=debugger_dr7_getValue();
74        _dr7.GD=state; //usually 1
75        debugger_dr7_setValue(_dr7);
76
77       
78}
79
80void debugger_dr0_setValue(UINT_PTR value)
81{
82        __writedr(0,value);
83}
84
85UINT_PTR debugger_dr0_getValue(void)
86{
87        return __readdr(0);
88}
89
90void debugger_dr1_setValue(UINT_PTR value)
91{
92        __writedr(1,value);
93}
94
95UINT_PTR debugger_dr1_getValue(void)
96{
97        return __readdr(1);
98}
99
100void debugger_dr2_setValue(UINT_PTR value)
101{
102        __writedr(2,value);
103}
104
105UINT_PTR debugger_dr2_getValue(void)
106{
107        return __readdr(2);
108}
109
110void debugger_dr3_setValue(UINT_PTR value)
111{
112        __writedr(3,value);
113}
114
115UINT_PTR debugger_dr3_getValue(void)
116{
117        return __readdr(3);
118}
119
120void debugger_dr6_setValue(UINT_PTR value)
121{
122        __writedr(6,value);
123}
124
125void debugger_dr7_setValue(DebugReg7 value)
126{
127        UINT_PTR temp=*(UINT_PTR *)&value;             
128        __writedr(7,temp);
129}
130
131void debugger_dr7_setValueDword(UINT_PTR value)
132{
133        __writedr(7,value);     
134}
135
136UINT_PTR debugger_dr7_getValueDword(void) //I wonder why I couldn't just typecast the DebugReg7 to a dword...
137{
138        return __readdr(7);
139}
140
141
142DebugReg7 debugger_dr7_getValue(void)
143{
144        UINT_PTR temp=debugger_dr7_getValueDword();
145        return *(DebugReg7 *)&temp;
146}
147
148UINT_PTR debugger_dr6_getValueDword(void)
149{
150        return __readdr(6);
151}
152
153DebugReg6 debugger_dr6_getValue(void)
154{
155        UINT_PTR temp=debugger_dr6_getValueDword();
156        return *(DebugReg6 *)&temp;
157}
158
159
160
161void debugger_touchDebugRegister(void)
162{
163        debugger_dr0_setValue(debugger_dr0_getValue());
164}
165
166void debugger_initialize(void)
167{
168        DbgPrint("Initializing debugger events\n");
169
170        KeInitializeEvent(&debugger_event_WaitForContinue, SynchronizationEvent, FALSE);       
171        KeInitializeEvent(&debugger_event_CanBreak, SynchronizationEvent, TRUE); //true so the first can enter
172        KeInitializeEvent(&debugger_event_WaitForDebugEvent, SynchronizationEvent, FALSE);
173}
174
175void debugger_setInitialFakeState(void)
176{       
177        DbgPrint("setInitialFakeState for cpu %d\n",cpunr());
178        DebuggerState.FakedDebugRegisterState[cpunr()].DR0=debugger_dr0_getValue();
179        DebuggerState.FakedDebugRegisterState[cpunr()].DR1=debugger_dr1_getValue();
180        DebuggerState.FakedDebugRegisterState[cpunr()].DR2=debugger_dr2_getValue();
181        DebuggerState.FakedDebugRegisterState[cpunr()].DR3=debugger_dr3_getValue();
182        DebuggerState.FakedDebugRegisterState[cpunr()].DR6=debugger_dr6_getValueDword();
183        DebuggerState.FakedDebugRegisterState[cpunr()].DR7=debugger_dr7_getValueDword();
184}
185
186int debugger_initHookForCurrentCPU(void)
187/*
188Must be called for each cpu
189*/
190{
191        int result=TRUE;
192        DbgPrint("Hooking int1 for this cpu\n");
193       
194        result=inthook_HookInterrupt(1,getCS() & 0xfff8, (ULONG_PTR)interrupt1_asmentry, &Int1JumpBackLocation);       
195
196#ifdef AMD64
197        if (result)
198        {
199                DbgPrint("hooked int1. Int1JumpBackLocation=%x:%llx\n", Int1JumpBackLocation.cs, Int1JumpBackLocation.eip);
200        }
201#endif
202
203
204        if (DebuggerState.globalDebug)
205        {
206                //set the fake state
207                //debugger_setInitialFakeState();
208                DbgPrint("Setting GD bit for cpu %d\n",cpunr());
209
210                debugger_dr7_setGD(1); //enable the GD flag             
211        }
212               
213        return result;
214}
215
216int debugger_setGlobalDebugState(BOOL state)
217//call this BEFORE debugging, if already debugging, the user must call this for each cpu
218{
219        DbgPrint("debugger_setGlobalDebugState(%d)\n",state);
220        if (state)
221          DebuggerState.globalDebug=state; //on enable set this first
222
223        if (inthook_isHooked(1))
224        {
225                int oldEpilogueState=DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue;
226
227                DbgPrint("Int 1 is hooked,%ssetting GD\n",(state ? "":"un"));
228                //debugger_setInitialFakeState();
229
230                DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=TRUE;
231                DebuggerState.globalDebug=state;
232                debugger_dr7_setGD(state);
233                //DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=oldEpilogueState;
234
235               
236
237                DebuggerState.FakedDebugRegisterState[cpunr()].DR7=0x400;
238                debugger_dr7_setValueDword(0x400);             
239        }
240
241        return TRUE;
242}
243
244int debugger_removeHookForCurrentCPU(void)
245{
246        DbgPrint("Dehooking int1 for this cpu\n");
247
248        if (DebuggerState.globalDebug)
249                return FALSE;
250        else
251                return inthook_UnhookInterrupt(1);     
252}
253
254int debugger_startDebugging(DWORD debuggedProcessID)
255/*
256Call this AFTER the interrupts are hooked
257*/
258{
259        DbgPrint("debugger_startDebugging. Processid=%x\n",debuggedProcessID);
260        Int1JumpBackLocation.eip=inthook_getOriginalEIP(1);
261        Int1JumpBackLocation.cs=inthook_getOriginalCS(1);
262
263#ifdef AMD64
264        DbgPrint("Int1 jump back = %x:%llx\n", Int1JumpBackLocation.cs, Int1JumpBackLocation.eip);
265#endif
266
267
268        DebuggerState.isDebugging=TRUE;
269        DebuggerState.debuggedProcessID=debuggedProcessID;
270
271        return TRUE;
272}
273
274int debugger_stopDebugging(void)
275{       
276        int i;
277
278        DbgPrint("Stopping the debugger if it is running\n");
279
280        DebuggerState.isDebugging=FALSE;
281        //DebuggerState.globalDebug=FALSE; //stop when possible, saves speed
282
283        for (i=0; i<4; i++)
284                DebuggerState.breakpoint[i].active=FALSE;
285
286        return TRUE;
287}
288
289int debugger_unsetGDBreakpoint(int breakpointnr)
290{
291        int result=DebuggerState.breakpoint[breakpointnr].active;
292        DebuggerState.breakpoint[breakpointnr].active=FALSE;
293        return result; //returns true if it was active
294}
295
296int debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakType bt, BreakLength bl)
297/*
298Will register a specific breakpoint. If global debug is used it'll set this debug register accordingly
299*/
300{
301        DbgPrint("debugger_setGDBreakpoint(%d, %x, %d, %d)\n", breakpointnr, Address, bt, bl);
302        DebuggerState.breakpoint[breakpointnr].active=TRUE;
303        DebuggerState.breakpoint[breakpointnr].address=Address;
304        DebuggerState.breakpoint[breakpointnr].breakType=bt;
305        DebuggerState.breakpoint[breakpointnr].breakLength=bl;
306        return TRUE;
307}
308
309NTSTATUS debugger_waitForDebugEvent(ULONG timeout)
310{
311        NTSTATUS r;
312        LARGE_INTEGER wait;
313
314        //DbgPrint("debugger_waitForDebugEvent with timeout of %d\n",timeout);
315
316        //-10000000LL=1 second
317        //-10000LL should be 1 millisecond
318        //-10000LL
319        wait.QuadPart=-10000LL * timeout;
320
321        if (timeout==0xffffffff) //infinite wait
322          r=KeWaitForSingleObject(&debugger_event_WaitForDebugEvent, UserRequest, KernelMode, TRUE, NULL);
323        else
324          r=KeWaitForSingleObject(&debugger_event_WaitForDebugEvent, UserRequest, KernelMode, TRUE, &wait);
325
326        if (r==STATUS_SUCCESS)
327                return r;
328        else
329                return STATUS_UNSUCCESSFUL;     
330}
331
332NTSTATUS debugger_continueDebugEvent(BOOL handled)
333/*
334Only call this by one thread only, and only when there's actually a debug eevnt in progress
335*/
336{
337        DbgPrint("debugger_continueDebugEvent\n");
338       
339        DebuggerState.handledlastevent=handled;
340        KeSetEvent(&debugger_event_WaitForContinue, 0,FALSE);
341
342        return STATUS_SUCCESS;
343}
344
345UINT_PTR *debugger_getLastStackPointer(void)
346{
347        return DebuggerState.LastStackPointer;
348}
349
350
351NTSTATUS debugger_getDebuggerState(PDebugStackState state)
352{
353        DbgPrint("debugger_getDebuggerState\n");
354        state->threadid=(UINT64)DebuggerState.LastThreadID;
355        state->rflags=(UINT_PTR)DebuggerState.LastStackPointer[si_eflags];
356        state->rax=DebuggerState.LastStackPointer[si_eax];
357        state->rbx=DebuggerState.LastStackPointer[si_ebx];
358        state->rcx=DebuggerState.LastStackPointer[si_ecx];
359        state->rdx=DebuggerState.LastStackPointer[si_edx];
360        state->rsi=DebuggerState.LastStackPointer[si_esi];
361        state->rdi=DebuggerState.LastStackPointer[si_edi];
362        state->rbp=DebuggerState.LastStackPointer[si_ebp];
363
364       
365
366#ifdef AMD64
367        //fill in the extra registers
368        state->r8=DebuggerState.LastStackPointer[si_r8];
369        state->r9=DebuggerState.LastStackPointer[si_r9];
370        state->r10=DebuggerState.LastStackPointer[si_r10];
371        state->r11=DebuggerState.LastStackPointer[si_r11];
372        state->r12=DebuggerState.LastStackPointer[si_r12];
373        state->r13=DebuggerState.LastStackPointer[si_r13];
374        state->r14=DebuggerState.LastStackPointer[si_r14];
375        state->r15=DebuggerState.LastStackPointer[si_r15];     
376#endif
377
378
379        //generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow
380        if ((DebuggerState.LastStackPointer[si_cs] & 3) == 3) //if usermode code segment
381        {
382                //priv level change, so the stack info was pushed as well
383                state->rsp=DebuggerState.LastStackPointer[si_esp];
384                state->ss=DebuggerState.LastStackPointer[si_ss];
385
386        }
387        else
388        {
389                //kernelmode stack, yeah, it's really useless here since changing it here only means certain doom, but hey...
390                state->rsp=(UINT_PTR)(DebuggerState.LastStackPointer)-4;
391                state->ss=getSS();; //unchangeble by the user
392        }
393
394       
395        state->rip=DebuggerState.LastStackPointer[si_eip];
396        state->cs=DebuggerState.LastStackPointer[si_cs];
397        state->ds=DebuggerState.LastStackPointer[si_ds];
398#ifdef AMD64
399        state->fs=0;
400        state->gs=0;
401#else
402
403        state->fs=DebuggerState.LastStackPointer[si_fs];
404        state->gs=DebuggerState.LastStackPointer[si_gs];
405#endif
406
407
408        state->dr0=DebuggerState.LastRealDebugRegisters[0];
409        state->dr1=DebuggerState.LastRealDebugRegisters[1];
410        state->dr2=DebuggerState.LastRealDebugRegisters[2];
411        state->dr3=DebuggerState.LastRealDebugRegisters[3];
412        state->dr6=DebuggerState.LastRealDebugRegisters[4];
413        state->dr7=DebuggerState.LastRealDebugRegisters[5];
414
415
416        return STATUS_SUCCESS;
417}
418
419NTSTATUS debugger_setDebuggerState(PDebugStackState state)
420{
421        DebuggerState.LastStackPointer[si_eflags]=(UINT_PTR)state->rflags;
422
423        DbgPrint("have set eflags to %x\n",DebuggerState.LastStackPointer[si_eflags]);
424
425
426        DebuggerState.LastStackPointer[si_eax]=(UINT_PTR)state->rax;
427        DebuggerState.LastStackPointer[si_ebx]=(UINT_PTR)state->rbx;
428        DebuggerState.LastStackPointer[si_ecx]=(UINT_PTR)state->rcx;
429        DebuggerState.LastStackPointer[si_edx]=(UINT_PTR)state->rdx;
430       
431        DebuggerState.LastStackPointer[si_esi]=(UINT_PTR)state->rsi;
432        DebuggerState.LastStackPointer[si_edi]=(UINT_PTR)state->rdi;
433       
434        DebuggerState.LastStackPointer[si_ebp]=(UINT_PTR)state->rbp;
435
436        //generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow
437        if ((DebuggerState.LastStackPointer[si_cs] & 3) == 3) //if usermode code segment
438        {
439                //priv level change, so the stack info was pushed as well
440                DebuggerState.LastStackPointer[si_esp]=(UINT_PTR)state->rsp;
441                //don't mess with ss
442        }
443        else
444        {
445                //no change in kernelmode allowed               
446        }
447
448       
449        DebuggerState.LastStackPointer[si_eip]=(UINT_PTR)state->rip;
450        DebuggerState.LastStackPointer[si_cs]=(UINT_PTR)state->cs;
451        DebuggerState.LastStackPointer[si_ds]=(UINT_PTR)state->ds;
452#ifndef AMD64
453        DebuggerState.LastStackPointer[si_fs]=(UINT_PTR)state->fs;
454        DebuggerState.LastStackPointer[si_gs]=(UINT_PTR)state->gs;
455#else //don't touch fs or gs in 64-bit
456        DebuggerState.LastStackPointer[si_r8]=(UINT_PTR)state->r8;
457        DebuggerState.LastStackPointer[si_r9]=(UINT_PTR)state->r9;
458        DebuggerState.LastStackPointer[si_r10]=(UINT_PTR)state->r10;
459        DebuggerState.LastStackPointer[si_r11]=(UINT_PTR)state->r11;
460        DebuggerState.LastStackPointer[si_r12]=(UINT_PTR)state->r12;
461        DebuggerState.LastStackPointer[si_r13]=(UINT_PTR)state->r13;
462        DebuggerState.LastStackPointer[si_r14]=(UINT_PTR)state->r14;
463        DebuggerState.LastStackPointer[si_r15]=(UINT_PTR)state->r15;
464#endif
465
466
467        if (!DebuggerState.globalDebug)
468        {
469                //no idea why someone would want to use this method, but it's in (for NON globaldebug only)
470
471                //updating this array too just so the user can see it got executed. (it eases their state of mind...)
472                DebuggerState.LastRealDebugRegisters[0]=(UINT_PTR)state->dr0;
473                DebuggerState.LastRealDebugRegisters[1]=(UINT_PTR)state->dr1;
474                DebuggerState.LastRealDebugRegisters[2]=(UINT_PTR)state->dr2;
475                DebuggerState.LastRealDebugRegisters[3]=(UINT_PTR)state->dr3;
476                DebuggerState.LastRealDebugRegisters[4]=(UINT_PTR)state->dr6;
477                DebuggerState.LastRealDebugRegisters[5]=(UINT_PTR)state->dr7;
478
479                //no setting of the DebugRegs here
480
481        }
482
483        return STATUS_SUCCESS;
484}
485
486int breakpointHandler_kernel(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs)
487//Notice: This routine is called when interrupts are enabled and the GD bit has been set if globaL DEBUGGING HAS BEEN USED
488//Interrupts are enabled and should be at passive level, so taskswitching is possible
489{
490        NTSTATUS r=STATUS_UNSUCCESSFUL;
491        int handled=0; //0 means let the OS handle it
492        LARGE_INTEGER timeout;
493        timeout.QuadPart=-100000;
494       
495       
496       
497        DbgPrint("breakpointHandler for kernel breakpoints\n");
498
499#ifdef AMD64
500        DbgPrint("cs=%x ss=%x ds=%x es=%x fs=%x gs=%x\n",getCS(), getSS(), getDS(), getES(), getFS(), getGS());
501
502        DbgPrint("fsbase=%llx gsbase=%llx gskernel=%llx\n", readMSR(0xc0000100), readMSR(0xc0000101), readMSR(0xc0000102));
503
504        DbgPrint("rbp=%llx\n", getRBP());
505
506        DbgPrint("gs:188=%llx\n", __readgsqword(0x188));
507#endif
508
509       
510        if (KeGetCurrentIrql()==0)
511        {
512                //crititical section here
513                if ((stackpointer[si_cs] & 3)==0)
514                {
515                        DbgPrint("Going to wait in a kernelmode routine\n");
516                }
517
518       
519                //block other threads from breaking until this one has been handled
520                while (r != STATUS_SUCCESS)
521                {
522                        r=KeWaitForSingleObject(&debugger_event_CanBreak,UserRequest, KernelMode, TRUE, NULL);
523                        //check r and handle specific events
524                               
525                }
526
527                if ((stackpointer[si_cs] & 3)==0)
528                {
529                        DbgPrint("Woke up in a kernelmode routine\n");
530                }
531               
532
533                //We're here, let's notify the usermode debugger of our situation
534                //first store the stackpointer so it can be manipulated externally
535                DebuggerState.LastStackPointer=stackpointer;
536                DebuggerState.LastRealDebugRegisters=currentdebugregs;         
537                DebuggerState.LastThreadID=PsGetCurrentThreadId();
538
539
540                //notify usermore app that this thread has halted due to a debug event
541               
542                KeSetEvent(&debugger_event_WaitForDebugEvent,0,FALSE);
543
544
545                //wait for event from usermode that debgu event has been handled
546                //KeWaitForSingleObject();
547                //continue with state
548
549                while (1)
550                {
551
552
553                        //LARGE_INTEGER wt;
554                        NTSTATUS s;
555                       
556                        //wt.QuadPart=-10000000LL;
557                        //s=KeDelayExecutionThread(KernelMode, FALSE, &wt);
558
559                        DbgPrint("Waiting...\n");
560
561                        s=KeWaitForSingleObject(&debugger_event_WaitForContinue, UserRequest, KernelMode, TRUE, NULL);
562
563                        DbgPrint("KeWaitForSingleObject=%x\n",s);               
564
565                        if (s==STATUS_SUCCESS)
566                        {
567                                if (DebuggerState.handledlastevent)
568                                {
569                                        //DbgPrint("handledlastevent=TRUE");
570                                        handled=1;
571                                }
572                                else
573                                        handled=0;
574
575                                break;
576                        }
577                               
578                }
579
580                //i'm done, let other threads catch it
581                KeSetEvent(&debugger_event_CanBreak, 0, FALSE);
582
583                DbgPrint("Returning after a wait. handled=%d and eflags=%x\n",handled, stackpointer[si_eflags]);
584                if ((stackpointer[si_cs] & 3)==0) //check rpl of cs
585                {
586                        DbgPrint("and in kernelmode\n");
587                }
588
589                return handled;
590        }
591        else
592        {
593                DbgPrint("Breakpoint wasn't at passive level. Screw this, i'm not going to break here\n");
594               
595                return 1;
596        }
597
598}
599
600int interrupt1_handler(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs)
601{
602        HANDLE CurrentProcessID=PsGetCurrentProcessId();       
603        UINT_PTR originaldr6=currentdebugregs[4];
604        DebugReg6 _dr6=*(DebugReg6 *)&currentdebugregs[4];
605        DebugReg7 _dr7=*(DebugReg7 *)&currentdebugregs[5];
606
607       
608        //check if this break should be handled or not
609       
610        if (DebuggerState.globalDebug)
611        {
612                //DbgPrint("DebuggerState.globalDebug=TRUE\n");
613                //global debugging is being used
614                if (_dr6.BD)
615                {
616                        //The debug registers are being accessed, emulate it with DebuggerState.FakedDebugRegisterState[cpunr()].DRx
617                        int instructionPointer;
618                        int currentcpunr=cpunr();
619                        int debugregister;
620                        int generalpurposeregister;
621                        unsigned char *instruction=(unsigned char *)stackpointer[si_eip];
622
623                        //unset this flag in DR6
624                        _dr6.BD=0;
625                        debugger_dr6_setValue(*(UINT_PTR *)&_dr6);
626
627                        if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue)
628                        {                                       
629                                ((EFLAGS *)&stackpointer[si_eflags])->RF=1; //repeat this instruction and don't break
630                                return 2;
631                        }
632
633               
634                        //DbgPrint("handler: Setting fake dr6 to %x\n",*(UINT_PTR *)&_dr6);
635                       
636                        //DebuggerState.FakedDebugRegisterState[cpunr()].DR6=*(UINT_PTR *)&_dr6;
637
638                        for (instructionPointer=0; instruction[instructionPointer] != 0x0f; instructionPointer++) ; //find the start of the instruction, skipping prefixes etc...
639                       
640                        //we now have the start of the instruction.
641                        //Find out which instruction it is, and which register is used
642                        debugregister=(instruction[instructionPointer+2] >> 3) & 7;     
643                        generalpurposeregister=instruction[instructionPointer+2] & 7;
644
645                        //DbgPrint("debugregister=%d, generalpurposeregister=%d\n",debugregister,generalpurposeregister);
646
647                        if (instruction[instructionPointer+1]==0x21)
648                        {
649                                UINT_PTR drvalue;
650                                //DbgPrint("read opperation\n");
651                                //21=read
652                                switch (debugregister)
653                                {
654                                        case 0:
655                                               
656                                                drvalue=DebuggerState.FakedDebugRegisterState[cpunr()].DR0;
657                                                //DbgPrint("Reading DR0 (returning %x real %x)\n", drvalue, currentdebugregs[0]);
658                                                break;
659
660                                        case 1:
661                                                drvalue=DebuggerState.FakedDebugRegisterState[cpunr()].DR1;
662                                                break;
663
664                                        case 2:
665                                                drvalue=DebuggerState.FakedDebugRegisterState[cpunr()].DR2;
666                                                break;
667
668                                        case 3:
669                                                drvalue=DebuggerState.FakedDebugRegisterState[cpunr()].DR3;
670                                                break;
671
672                                        case 4:
673                                        case 6:
674                                                drvalue=DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
675                                                //DbgPrint("reading dr6 value:%x\n",drvalue);
676                                                break;
677
678                                        case 5:
679                                        case 7:
680                                                drvalue=DebuggerState.FakedDebugRegisterState[cpunr()].DR7;                                             
681                                                break;
682
683                                }
684
685                                switch (generalpurposeregister)
686                                {
687                                        case 0:
688                                                stackpointer[si_eax]=drvalue;
689                                                break;
690
691                                        case 1:
692                                                stackpointer[si_ecx]=drvalue;
693                                                break;
694
695                                        case 2:
696                                                stackpointer[si_edx]=drvalue;
697                                                break;
698
699                                        case 3:
700                                                stackpointer[si_ebx]=drvalue;
701                                                break;
702
703                                        case 4:
704                                                if ((stackpointer[si_cs] & 3) == 3)
705                                                        stackpointer[si_esp]=drvalue;
706                                                else
707                                                        stackpointer[si_stack_esp]=drvalue;
708
709                                                break;
710
711                                        case 5:
712                                                stackpointer[si_ebp]=drvalue;
713                                                break;
714
715                                        case 6:
716                                                stackpointer[si_esi]=drvalue;
717                                                break;
718
719                                        case 7:
720                                                stackpointer[si_edi]=drvalue;
721                                                break;
722                                }
723
724                        }
725                        else 
726                        if (instruction[instructionPointer+1]==0x23)
727                        {
728                                //23=write
729                                UINT_PTR gpvalue;
730                                //DbgPrint("Write operation\n");
731                                switch (generalpurposeregister)
732                                {
733                                        case 0:
734                                                gpvalue=stackpointer[si_eax];
735                                                break;
736
737                                        case 1:
738                                                gpvalue=stackpointer[si_ecx];
739                                                break;
740
741                                        case 2:
742                                                gpvalue=stackpointer[si_edx];
743                                                break;
744
745                                        case 3:
746                                                gpvalue=stackpointer[si_ebx];
747                                                break;
748
749                                        case 4:
750                                                if ((stackpointer[si_cs] & 3) == 3)
751                                                        gpvalue=stackpointer[si_esp];
752
753                                                break;
754
755                                        case 5:
756                                                gpvalue=stackpointer[si_ebp];
757                                                break;
758
759                                        case 6:
760                                                gpvalue=stackpointer[si_esi];
761                                                break;
762
763                                        case 7:
764                                                gpvalue=stackpointer[si_edi];
765                                                break;
766                                }
767
768                                //gpvalue now contains the value to set the debug register
769                                switch (debugregister)
770                                {
771                                        case 0:         
772                                                //DbgPrint("Writing DR0. Original value=%x new value=%x\n", currentdebugregs[0], gpvalue);
773                                                debugger_dr0_setValue(gpvalue);
774                                                DebuggerState.FakedDebugRegisterState[cpunr()].DR0=debugger_dr0_getValue();
775                                                break;
776
777                                        case 1:                                                 
778                                                debugger_dr1_setValue(gpvalue);
779                                                DebuggerState.FakedDebugRegisterState[cpunr()].DR1=debugger_dr1_getValue();
780                                                break;
781
782                                        case 2:                                                 
783                                                debugger_dr2_setValue(gpvalue);
784                                                DebuggerState.FakedDebugRegisterState[cpunr()].DR2=debugger_dr2_getValue();
785                                                break;
786
787                                        case 3:                                                 
788                                                debugger_dr3_setValue(gpvalue);
789                                                DebuggerState.FakedDebugRegisterState[cpunr()].DR3=debugger_dr3_getValue();
790                                                break;
791
792                                        case 4:
793                                        case 6:                                         
794                                                //DbgPrint("Setting dr6 to %x (was %x)\n", gpvalue, DebuggerState.FakedDebugRegisterState[cpunr()].DR6);
795                                                debugger_dr6_setValue(gpvalue);                                         
796                                                DebuggerState.FakedDebugRegisterState[cpunr()].DR6=debugger_dr6_getValueDword();
797                                                break;
798
799                                        case 5:
800                                        case 7:
801                                                //make sure it doesn't set the GD flag nowgpvalue
802                                               
803                                                if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue)
804                                                {
805                                                //      DbgPrint("Was in epilogue\n");
806                                                }
807
808                                                gpvalue=gpvalue | 0x400;
809                                                ((DebugReg7 *)&gpvalue)->GD=0;                                         
810
811                                                debugger_dr7_setValue(*((DebugReg7 *)&gpvalue));
812                                                DebuggerState.FakedDebugRegisterState[cpunr()].DR7=debugger_dr7_getValueDword();
813                                               
814                                                break;
815                                }
816
817
818
819                        }
820                        else 
821                        {
822                                //DbgPrint("Some unknown instruction accessed the debug registers?\n");
823                                //if (CurrentProcessID==(HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID)
824                                //      DbgPrint("Happened inside the target process\n");
825
826                                //DbgPrint("interrupt1_handler dr6=%x (original=%x) dr7=%d\n",_dr6, originaldr6, _dr7);
827                                //DbgPrint("eip=%x\n",stackpointer[si_eip]);
828                        }
829
830                        //adjust eip to after this instruction
831                        stackpointer[si_eip]+=instructionPointer+3; //0f xx /r
832
833                        return 1; //don't tell windows about it
834                }
835        }
836
837       
838       
839        if (DebuggerState.isDebugging)
840        {
841                //check if this should break
842                if (CurrentProcessID==(HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID)
843                {       
844                        UINT_PTR originaldebugregs[6];
845                        UINT64 oldDR7=getDR7();
846
847                        if (DebuggerState.globalDebug)
848                        {
849                                originaldebugregs[0]=DebuggerState.FakedDebugRegisterState[cpunr()].DR0;
850                                originaldebugregs[1]=DebuggerState.FakedDebugRegisterState[cpunr()].DR1;
851                                originaldebugregs[2]=DebuggerState.FakedDebugRegisterState[cpunr()].DR2;
852                                originaldebugregs[3]=DebuggerState.FakedDebugRegisterState[cpunr()].DR3;
853                                originaldebugregs[4]=DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
854                                originaldebugregs[5]=DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
855                        }
856
857                        //DbgPrint("BP in target process\n");
858                       
859                        //no extra checks if it's caused by the debugger or not. That is now done in the usermode part
860                        //if (*(PEFLAGS)(&stackpointer[si_eflags]).IF) 
861                        if (((PEFLAGS)&stackpointer[si_eflags])->IF==0)
862                        {
863                                //DbgPrint("Breakpoint while interrupts are disabled: %x\n",stackpointer[si_eip]);
864                                ((PEFLAGS)&stackpointer[si_eflags])->RF=1;
865                                ((PEFLAGS)&stackpointer[si_eflags])->TF=1; //keep going until IF=1
866                                return 1; //don't handle it but also don't tell windows
867                        }
868
869                        //set the real debug registers to what it is according to the guest (so taskswitches take over these values) .... shouldn't be needed as global debug is on which fakes that read...
870
871                       
872
873                        if (DebuggerState.globalDebug)
874                        {
875                                //enable the GD flag for taskswitches that will occur as soon as interrupts are enabled
876                                //this also means: DO NOT EDIT THE DEBUG REGISTERS IN GLOBAL DEBUG MODE at this point. Only in the epilogue
877                                debugger_dr7_setGD(DebuggerState.globalDebug);
878                        }       
879                        else
880                        {
881                                //unset ALL debug registers before enablin taskswitching. Just re-enable it when back when interrupts are disabled again
882                                debugger_dr7_setValueDword(0x400);
883                                debugger_dr0_setValue(0);
884                                debugger_dr1_setValue(0);
885                                debugger_dr2_setValue(0);
886                                debugger_dr3_setValue(0);
887                                debugger_dr6_setValue(0xffff0ff0);
888                        }
889
890                        //start the windows taskswitching mode
891                        enableInterrupts();
892                        {
893                                int rs=1;
894                                //DbgPrint("calling breakpointHandler_kernel\n");
895                               
896                                rs=breakpointHandler_kernel(stackpointer, currentdebugregs);   
897                                //DbgPrint("After handler dr6=%x and before handling it was %x\n",debugger_dr6_getValue(), DebuggerState.FakedDebugRegisterState[cpunr()].DR6);
898
899                                //DbgPrint("rs=%d\n",rs);
900
901
902                                disableInterrupts();
903
904
905                                //we might be on a different CPU now
906                                if (DebuggerState.globalDebug)
907                                {
908                                        DebuggerState.FakedDebugRegisterState[cpunr()].DR0=originaldebugregs[0];
909                                        DebuggerState.FakedDebugRegisterState[cpunr()].DR1=originaldebugregs[1];
910                                        DebuggerState.FakedDebugRegisterState[cpunr()].DR2=originaldebugregs[2];
911                                        DebuggerState.FakedDebugRegisterState[cpunr()].DR3=originaldebugregs[3];
912                                        DebuggerState.FakedDebugRegisterState[cpunr()].DR6=originaldebugregs[4];
913                                        DebuggerState.FakedDebugRegisterState[cpunr()].DR7=originaldebugregs[5];
914                                }
915                                else
916                                {
917                                        if (getDR7() != oldDR7)
918                                        {
919                                                DbgPrint("Something changed DR7. old=%llx new=%llx\n",oldDR7, getDR7());
920                                        }
921
922                                       
923                                        //set the debugregisters to what they where set to before taskswitching was enable
924                                        //with global debug this is done elsewhere
925                                        debugger_dr0_setValue(currentdebugregs[0]);
926                                        debugger_dr1_setValue(currentdebugregs[1]);
927                                        debugger_dr2_setValue(currentdebugregs[2]);
928                                        debugger_dr3_setValue(currentdebugregs[3]);
929                                        debugger_dr6_setValue(currentdebugregs[4]);
930                                        debugger_dr7_setValue(*(DebugReg7 *)&currentdebugregs[5]);                                     
931                                }
932                               
933                                return rs;
934                        }
935                }
936                else 
937                {
938                        //DbgPrint("Not the debugged process (%x != %x)\n",CurrentProcessID,DebuggerState.debuggedProcessID );
939                        //check if this break is due to a breakpoint ce has set. (during global debug threadsurfing))
940                        //do that by checking if the breakpoint condition exists in the FAKE dr7 registers
941                        //if so, let windows handle it, if not, it is caused by ce, which then means, skip (so execute normally)
942
943                        if (DebuggerState.globalDebug)
944                        {                       
945                                DebugReg6 dr6=debugger_dr6_getValue();
946                                DebugReg7 dr7=*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
947
948                                //real dr6              //fake dr7
949                                if ((dr6.B0) && (!(dr7.L0 || dr7.G0))) { DbgPrint("setting RF because of B0\n"); ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } //break caused by DR0 and not expected by the current process, ignore this bp and continue
950                                if ((dr6.B1) && (!(dr7.L1 || dr7.G1))) { DbgPrint("setting RF because of B1\n"); ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } //              ...             DR1             ...
951                                if ((dr6.B2) && (!(dr7.L2 || dr7.G2))) { DbgPrint("setting RF because of B2\n"); ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; }  //             ...             DR2             ...
952                                if ((dr6.B3) && (!(dr7.L3 || dr7.G3))) { DbgPrint("setting RF because of B3\n"); ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; }  //             ...             DR3             ...
953                        }
954
955                        return 0; //still here, so let windows handle it
956
957                }
958        }
959        else
960                return 0; //Let windows handle it
961
962        //get the current processid
963        //is it being debugged
964        //if yes, check if the breakpoint is something done by me
965        //if no, exit
966       
967}
968
969int interrupt1_centry(UINT_PTR *stackpointer) //code segment 8 has a 32-bit stackpointer
970{
971        UINT_PTR before,after;
972        UINT_PTR currentdebugregs[6]; //used for determining if the current bp is caused by the debugger ot not
973        int handled=0; //if 0 at return, the interupt will be passed down to the operating system
974        int i;
975
976        DbgPrint("interrupt1_centry:%d\n",cpunr());
977
978        before=getRSP();
979
980       
981#ifdef AMD64
982        //DbgPrint("gs:180=%x\n", __readgsdword(0x180));
983       
984
985        //DbgPrint("current csr=%x\n", _mm_getcsr());
986
987        //DbgPrint("stackpointer RAX=%llx\n",stackpointer[si_eax]);
988        //DbgPrint("stackpointer RBX=%llx\n",stackpointer[si_ebx]);
989        //DbgPrint("stackpointer RCX=%llx\n",stackpointer[si_ecx]);
990        //DbgPrint("stackpointer RDX=%llx\n",stackpointer[si_edx]);
991        //DbgPrint("stackpointer cs:rip=%llx:%llx\n",stackpointer[si_cs], stackpointer[si_eip]);
992        //DbgPrint("stackpointer ss:rsp=%llx:%llx\n",stackpointer[si_ss], stackpointer[si_esp]);
993
994#endif
995
996
997       
998        //Fetch current debug registers
999        currentdebugregs[0]=debugger_dr0_getValue();
1000        currentdebugregs[1]=debugger_dr1_getValue();
1001        currentdebugregs[2]=debugger_dr2_getValue();
1002        currentdebugregs[3]=debugger_dr3_getValue();
1003        currentdebugregs[4]=debugger_dr6_getValueDword();
1004        currentdebugregs[5]=debugger_dr7_getValueDword();
1005
1006
1007        handled=interrupt1_handler(stackpointer, currentdebugregs);
1008
1009
1010       
1011
1012        DbgPrint("handled=%d\n",handled);
1013
1014        //DbgPrint("After interrupt1_handler dr6=%x\n",currentdebugregs[4]);
1015       
1016
1017        //epilogue:
1018        //At the end when returning:
1019       
1020       
1021
1022        //
1023        ///--------------------------------------------------------------------------\
1024        //|--------------EPILOGUE (AFTER HAVING HANDLED THE BREAKPOINT)--------------|
1025        //\--------------------------------------------------------------------------/
1026        //
1027       
1028       
1029        disableInterrupts(); //just making sure..       
1030
1031
1032        DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1;
1033        debugger_dr7_setGD(0); //make sure the GD bit is disabled (int1 within int1, oooh the fun..., and yes, THIS itself will cause one too)
1034        DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1; //just be sure...
1035
1036
1037        if (inthook_isDBVMHook(1))
1038        {
1039                //update the int1 return address, could have been changed
1040                IDT idt;       
1041                GetIDT(&idt);
1042
1043                //DbgPrint("This was a dbvm hook. Changing if the interrupt return address is still valid\n");
1044
1045                Int1JumpBackLocation.cs=idt.vector[1].wSelector;
1046                Int1JumpBackLocation.eip=idt.vector[1].wLowOffset+(idt.vector[1].wHighOffset << 16);
1047#ifdef AMD64
1048                Int1JumpBackLocation.eip+=((UINT64)idt.vector[1].TopOffset << 32);             
1049#endif
1050
1051        }
1052
1053
1054
1055
1056
1057       
1058        //DbgPrint("interrupt1_centry returning %d\n",handled);
1059
1060        //rf should be set by the usermode debugger part. reason: gd bit, there handled = 1 but rf must not be 1 because eip is changed
1061        //if (handled) //set the resume flag so it executes at least one instruction
1062                //((PEFLAGS)&DebuggerState.LastStackPointer[si_eflags])->RF=1;
1063       
1064       
1065
1066        if (DebuggerState.globalDebug) //DR's are only accesses when there are DR's(no idea how it handles breakpoints in a different process...), so set them in each thread even those that don't belong original: && (PsGetCurrentProcessId()==(HANDLE)DebuggerState.debuggedProcessID))
1067        {
1068                //set the breakpoint in this thread.           
1069        DebugReg6 dr6=debugger_dr6_getValue();
1070                //DebugReg7 dr7=debugger_dr7_getValue();
1071
1072                DebugReg6 _dr6=*(DebugReg6 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
1073        DebugReg7 _dr7=*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
1074                int debugregister=0, breakpoint=0;
1075               
1076
1077
1078        //first clear the DR6 bits caused by the debugger
1079
1080                if (!handled)
1081                {
1082                        //it's going to get sent to windows
1083                        if (dr6.BD && _dr7.GD) _dr6.BD=1; //should already have been done, but what the heck...
1084                        if (dr6.B0 && (_dr7.L0 || _dr7.G0)) _dr6.B0=1;
1085                        if (dr6.B1 && (_dr7.L1 || _dr7.G1)) _dr6.B1=1;
1086                        if (dr6.B2 && (_dr7.L2 || _dr7.G2)) _dr6.B2=1;
1087                        if (dr6.B3 && (_dr7.L3 || _dr7.G3)) _dr6.B3=1;
1088
1089                        _dr6.BS=dr6.BS;
1090                        _dr6.BT=dr6.BT;
1091                        //DbgPrint("epilogue: Setting fake dr6 to %x (fake=%x)\n",*(DWORD *)&dr6, *(DWORD *)&_dr6);
1092                }
1093               
1094
1095                debugger_dr6_setValue(0xffff0ff0);
1096
1097               
1098                //set the debug registers of active breakpoints. Doesn't have to be in the specified order. Just find an unused debug registers
1099                //check DebuggerState.FakedDebugRegisterState[cpunumber].DR7 for unused breakpoints
1100
1101                //set state to what the guest thinks it is
1102                debugger_dr0_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR0);
1103                debugger_dr1_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR1);
1104                debugger_dr2_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR2);
1105                debugger_dr3_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR3);
1106                debugger_dr6_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR6);
1107
1108               
1109                //
1110                //if ((*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[currentcpunr].DR7).GD)
1111                //{
1112                        //DbgPrint("DR7.GD IS SET IN THE GUEST STATE\n");
1113                //}
1114                //debugger_dr7_setValue(*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[currentcpunr].DR7);
1115
1116//              DbgPrint("PID/TID:%x/%x\n", PsGetCurrentProcessId(), PsGetCurrentThreadId());
1117//              DbgPrint("before fake DR0=%x real DR0=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR0, debugger_dr0_getValue());
1118//              DbgPrint("before fake DR1=%x real DR1=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR1, debugger_dr1_getValue());
1119//              DbgPrint("before fake DR2=%x real DR2=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR2, debugger_dr2_getValue());
1120//              DbgPrint("before fake DR3=%x real DR3=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR3, debugger_dr3_getValue());
1121//              DbgPrint("before fake DR6=%x real DR6=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR6, debugger_dr6_getValueDword());
1122//              DbgPrint("before fake DR7=%x real DR7=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR7, debugger_dr7_getValueDword());
1123
1124                //
1125                //if (!DebuggerState.FakedDebugRegisterState[currentcpunr].inEpilogue)
1126                //{
1127//                     
1128                        //DbgPrint("Before: It wasn't in the epilogue. eflags=%x\n");
1129                        //DebuggerState.FakedDebugRegisterState[currentcpunr].inEpilogue=1;
1130                //}
1131               
1132               
1133                for (breakpoint=0; breakpoint<4; breakpoint++)
1134                {
1135                       
1136                        if (DebuggerState.breakpoint[breakpoint].active)
1137                        {
1138                               
1139                                int foundone=0;
1140                        //      DbgPrint("Want to set breakpoint %d\n",breakpoint);
1141                       
1142                               
1143
1144                                //find a usable debugregister
1145                                while ((debugregister<4) && (foundone==0))                             
1146                                {
1147                               
1148                                        if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue==0)
1149                                        {
1150                                                DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1;
1151                                        }
1152                                       
1153
1154                                        //check if this debugregister is usable
1155                                        if (((DebuggerState.FakedDebugRegisterState[cpunr()].DR7 >> (debugregister*2)) & 3)==0)  //DR7.Gx and DR7.Lx are 0
1156                                        {
1157                                          //  DbgPrint("debugregister %d is free to be used\n",debugregister);
1158                                                foundone=1;
1159                                               
1160                                                //set address
1161                                                switch (debugregister)
1162                                                {
1163                                                        case 0:
1164                                                                debugger_dr0_setValue(DebuggerState.breakpoint[breakpoint].address);
1165                                                                _dr7.L0=1;
1166                                                                _dr7.LEN0=DebuggerState.breakpoint[breakpoint].breakLength;
1167                                                                _dr7.RW0=DebuggerState.breakpoint[breakpoint].breakType;
1168                                                                break;
1169
1170                                                        case 1:
1171                                                                debugger_dr1_setValue(DebuggerState.breakpoint[breakpoint].address);
1172                                                                _dr7.L1=1;
1173                                                                _dr7.LEN1=DebuggerState.breakpoint[breakpoint].breakLength;
1174                                                                _dr7.RW1=DebuggerState.breakpoint[breakpoint].breakType;
1175                                                                break;
1176
1177                                                        case 2:
1178                                                                debugger_dr2_setValue(DebuggerState.breakpoint[breakpoint].address);
1179                                                                _dr7.L2=1;
1180                                                                _dr7.LEN2=DebuggerState.breakpoint[breakpoint].breakLength;
1181                                                                _dr7.RW2=DebuggerState.breakpoint[breakpoint].breakType;
1182                                                                break;
1183
1184                                                        case 3:
1185                                                                debugger_dr3_setValue(DebuggerState.breakpoint[breakpoint].address);
1186                                                                _dr7.L3=1;
1187                                                                _dr7.LEN3=DebuggerState.breakpoint[breakpoint].breakLength;
1188                                                                _dr7.RW3=DebuggerState.breakpoint[breakpoint].breakType;
1189                                                                break;
1190                                                }
1191                                               
1192
1193                                        }
1194
1195                                        debugregister++;
1196
1197                                }
1198                               
1199                               
1200                        }
1201                       
1202                       
1203                }
1204               
1205
1206                debugger_dr7_setValue(_dr7);
1207
1208                //DbgPrint("after:\n");
1209
1210                //DbgPrint("after fake DR0=%x real DR0=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR0, debugger_dr0_getValue());
1211                //DbgPrint("after fake DR1=%x real DR1=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR1, debugger_dr1_getValue());
1212                //DbgPrint("after fake DR2=%x real DR2=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR2, debugger_dr2_getValue());
1213                //DbgPrint("after fake DR3=%x real DR3=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR3, debugger_dr3_getValue());
1214                //DbgPrint("after fake DR6=%x real DR6=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR6, debugger_dr6_getValueDword());
1215                //DbgPrint("after fake DR7=%x real DR7=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR7, debugger_dr7_getValueDword());
1216
1217                __nop();
1218        }
1219        else
1220        {
1221                __nop();       
1222
1223                //not global debug, just clear all flags and be done with it
1224                debugger_dr6_setValue(0xffff0ff0);
1225               
1226        }
1227
1228
1229        if (handled == 2)
1230        {
1231                handled = 1; //epilogue = 1 Dr handler
1232        }
1233        else
1234        {               
1235                //not handled by the epilogue set DR0, so the actual epilogue
1236                DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=0;
1237                debugger_dr7_setGD(DebuggerState.globalDebug);         
1238        }
1239
1240        after=getRSP();
1241
1242        DbgPrint("before=%llx after=%llx\n",before,after);
1243
1244        return handled;
1245}
1246
1247#ifndef AMD64
1248_declspec( naked ) void interrupt1_asmentry( void )
1249//This routine is called upon an interrupt 1, even before windows gets it
1250{
1251        __asm{
1252                //save stack position
1253                push 0 //push an errorcode on the stack so the stackindex can stay the same
1254                push ebp
1255                mov ebp,esp
1256
1257                //save state
1258                pushad
1259                push ds
1260                push es
1261                push fs
1262                push gs
1263
1264                mov ax,0x23 //0x10 should work too, but even windows itself is using 0x23
1265                mov ds,ax
1266                mov es,ax
1267                mov gs,ax
1268                mov ax,0x30
1269                mov fs,ax
1270
1271                push ebp
1272                call interrupt1_centry
1273
1274                cmp eax,1       //set flag
1275
1276
1277
1278                //restore state
1279                pop gs
1280                pop fs
1281                pop es
1282                pop ds
1283                popad
1284
1285                pop ebp         
1286
1287                je skip_original_int1
1288               
1289                add esp,4 //undo errorcode push (add effects eflags, so set it at both locations)
1290
1291                jmp far [Int1JumpBackLocation]
1292
1293skip_original_int1:
1294                add esp,4 //undo errorcode push
1295                iretd
1296        }
1297}
1298#endif
Note: See TracBrowser for help on using the browser.