[NTOS:KE]
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.c
index fdf6a8f..6d3151f 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-/* GLOBALS *******************************************************************/
-
-/* DR Registers in the CONTEXT structure */
-UCHAR KiDebugRegisterContextOffsets[9] =
-{
-    FIELD_OFFSET(CONTEXT, Dr0),
-    FIELD_OFFSET(CONTEXT, Dr1),
-    FIELD_OFFSET(CONTEXT, Dr2),
-    FIELD_OFFSET(CONTEXT, Dr3),
-    0,
-    0,
-    FIELD_OFFSET(CONTEXT, Dr6),
-    FIELD_OFFSET(CONTEXT, Dr7),
-    0,
-};
-
-/* DR Registers in the KTRAP_FRAME structure */
-UCHAR KiDebugRegisterTrapOffsets[9] =
-{
-    FIELD_OFFSET(KTRAP_FRAME, Dr0),
-    FIELD_OFFSET(KTRAP_FRAME, Dr1),
-    FIELD_OFFSET(KTRAP_FRAME, Dr2),
-    FIELD_OFFSET(KTRAP_FRAME, Dr3),
-    0,
-    0,
-    FIELD_OFFSET(KTRAP_FRAME, Dr6),
-    FIELD_OFFSET(KTRAP_FRAME, Dr7),
-    0,
-};
 
 /* FUNCTIONS *****************************************************************/
 
@@ -153,8 +124,7 @@ KiRecordDr7(OUT PULONG Dr7Ptr,
         if (Mask != NewMask)
         {
             /* Update it */
-            KeGetCurrentThread()->Header.DebugActive =
-                (BOOLEAN)NewMask;
+            KeGetCurrentThread()->Header.DebugActive = (UCHAR)NewMask;
         }
     }
 
@@ -167,7 +137,7 @@ NTAPI
 KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
 {
     /* Check if this is user-mode or V86 */
-    if ((TrapFrame->SegCs & MODE_MASK) ||
+    if (KiUserTrap(TrapFrame) ||
         (TrapFrame->EFlags & EFLAGS_V86_MASK))
     {
         /* Return it directly */
@@ -205,7 +175,7 @@ KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
     Previous = KiEspFromTrapFrame(TrapFrame);
 
     /* Check if this is user-mode or V86 */
-    if ((TrapFrame->SegCs & MODE_MASK) ||
+    if (KiUserTrap(TrapFrame) ||
         (TrapFrame->EFlags & EFLAGS_V86_MASK))
     {
         /* Write it directly */
@@ -255,7 +225,7 @@ KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
         /* Just return it */
         return TrapFrame->HardwareSegSs;
     }
-    else if (TrapFrame->SegCs & MODE_MASK)
+    else if (KiUserTrap(TrapFrame))
     {
         /* User mode, return the User SS */
         return TrapFrame->HardwareSegSs | RPL_MASK;
@@ -281,7 +251,7 @@ KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
         /* Just write it */
         TrapFrame->HardwareSegSs = Ss;
     }
-    else if (TrapFrame->SegCs & MODE_MASK)
+    else if (KiUserTrap(TrapFrame))
     {
         /* Usermode, save the User SS */
         TrapFrame->HardwareSegSs = Ss | RPL_MASK;
@@ -312,11 +282,11 @@ Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame)
     PKTHREAD Thread;
     ULONG_PTR Stack;
     ULONG EFlags;
-    
+
     /* Get the current thread's stack */
     Thread = KeGetCurrentThread();
     Stack = (ULONG_PTR)Thread->InitialStack;
-    
+
     /* Check if we are in V8086 mode */
     if (!(TrapFrame->EFlags & EFLAGS_V86_MASK))
     {
@@ -324,17 +294,17 @@ Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame)
         Stack -= (FIELD_OFFSET(KTRAP_FRAME, V86Gs) -
                   FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs));
     }
-    
+
     /* Bias the stack for the FPU area */
     Stack -= sizeof(FX_SAVE_AREA);
-    
+
     /* Disable interrupts */
     EFlags = __readeflags();
     _disable();
-    
+
     /* Set new ESP0 value in the TSS */
     KeGetPcr()->TSS->Esp0 = Stack;
-    
+
     /* Restore old interrupt state */
     __writeeflags(EFlags);
 }
@@ -352,7 +322,6 @@ KeContextToTrapFrame(IN PCONTEXT Context,
     BOOLEAN V86Switch = FALSE;
     KIRQL OldIrql;
     ULONG DrMask = 0;
-    PVOID SafeDr;
 
     /* Do this at APC_LEVEL */
     OldIrql = KeGetCurrentIrql();
@@ -429,7 +398,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
             TrapFrame->V86Fs = Context->SegFs;
             TrapFrame->V86Gs = Context->SegGs;
         }
-        else if (!(TrapFrame->SegCs & MODE_MASK))
+        else if (!KiUserTrap(TrapFrame))
         {
             /* For kernel mode, write the standard values */
             TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
@@ -460,7 +429,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
 
     /* Handle the extended registers */
     if (((ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
-        CONTEXT_EXTENDED_REGISTERS) && (TrapFrame->SegCs & MODE_MASK))
+        CONTEXT_EXTENDED_REGISTERS) && KiUserTrap(TrapFrame))
     {
         /* Get the FX Area */
         FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
@@ -494,7 +463,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
 
     /* Handle the floating point state */
     if (((ContextFlags & CONTEXT_FLOATING_POINT) ==
-        CONTEXT_FLOATING_POINT) && (TrapFrame->SegCs & MODE_MASK))
+        CONTEXT_FLOATING_POINT) && KiUserTrap(TrapFrame))
     {
         /* Get the FX Area */
         FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
@@ -584,26 +553,35 @@ KeContextToTrapFrame(IN PCONTEXT Context,
     }
 
     /* Handle the Debug Registers */
-    if (0 && (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
+    if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
     {
-        /* Loop DR registers */
-        for (i = 0; i < 4; i++)
-        {
-            /* Sanitize the context DR Address */
-            SafeDr = Ke386SanitizeDr(KiDrFromContext(i, Context), PreviousMode);
-
-            /* Save it in the trap frame */
-            *KiDrFromTrapFrame(i, TrapFrame) = SafeDr;
+        /* Copy Dr0 - Dr4 */
+        TrapFrame->Dr0 = Context->Dr0;
+        TrapFrame->Dr1 = Context->Dr1;
+        TrapFrame->Dr2 = Context->Dr2;
+        TrapFrame->Dr3 = Context->Dr3;
 
-            /* Check if this DR address is active and add it in the DR mask */
-            if (SafeDr) DrMask |= DR_MASK(i);
+        /* If we're in user-mode */
+        if (PreviousMode != KernelMode)
+        {
+            /* Make sure, no Dr address is above user space */
+            if (Context->Dr0 > (ULONG)MmHighestUserAddress) TrapFrame->Dr0 = 0;
+            if (Context->Dr1 > (ULONG)MmHighestUserAddress) TrapFrame->Dr1 = 0;
+            if (Context->Dr2 > (ULONG)MmHighestUserAddress) TrapFrame->Dr2 = 0;
+            if (Context->Dr3 > (ULONG)MmHighestUserAddress) TrapFrame->Dr3 = 0;
         }
 
-        /* Now save and sanitize DR6 */
+        /* Now sanitize and save DR6 */
         TrapFrame->Dr6 = Context->Dr6 & DR6_LEGAL;
+
+        /* Update the Dr active mask */
+        if (TrapFrame->Dr0) DrMask |= DR_MASK(0);
+        if (TrapFrame->Dr1) DrMask |= DR_MASK(1);
+        if (TrapFrame->Dr2) DrMask |= DR_MASK(2);
+        if (TrapFrame->Dr3) DrMask |= DR_MASK(3);
         if (TrapFrame->Dr6) DrMask |= DR_MASK(6);
 
-        /* Save and sanitize DR7 */
+        /* Sanitize and save DR7 */
         TrapFrame->Dr7 = Context->Dr7 & DR7_LEGAL;
         KiRecordDr7(&TrapFrame->Dr7, &DrMask);
 
@@ -611,7 +589,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
         if (PreviousMode != KernelMode)
         {
             /* Save the mask */
-            KeGetCurrentThread()->Header.DebugActive = (DrMask != 0);
+            KeGetCurrentThread()->Header.DebugActive = (UCHAR)DrMask;
         }
     }
 
@@ -714,7 +692,7 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
 
     /* Handle extended registers */
     if (((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
-        CONTEXT_EXTENDED_REGISTERS) && (TrapFrame->SegCs & MODE_MASK))
+        CONTEXT_EXTENDED_REGISTERS) && KiUserTrap(TrapFrame))
     {
         /* Get the FX Save Area */
         FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
@@ -734,7 +712,7 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
 
     /* Handle Floating Point */
     if (((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
-        CONTEXT_FLOATING_POINT) && (TrapFrame->SegCs & MODE_MASK))
+        CONTEXT_FLOATING_POINT) && KiUserTrap(TrapFrame))
     {
         /* Get the FX Save Area */
         FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
@@ -962,7 +940,7 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
         /* User mode exception, was it first-chance? */
         if (FirstChance)
         {
-            /* 
+            /*
              * Break into the kernel debugger unless a user mode debugger
              * is present or user mode exceptions are ignored, except if this
              * is a debug service which we must always pass to KD
@@ -1067,6 +1045,13 @@ DispatchToUser:
                 }
             }
             _SEH2_END;
+
+            DPRINT("First chance exception in %.16s, ExceptionCode: %lx, ExceptionAddress: %p, P0: %lx, P1: %lx\n",
+                   PsGetCurrentProcess()->ImageFileName,
+                   ExceptionRecord->ExceptionCode,
+                   ExceptionRecord->ExceptionAddress,
+                   ExceptionRecord->ExceptionInformation[0],
+                   ExceptionRecord->ExceptionInformation[1]);
         }
 
         /* Try second chance */
@@ -1082,11 +1067,13 @@ DispatchToUser:
         }
 
         /* 3rd strike, kill the process */
-        DPRINT1("Kill %.16s, ExceptionCode: %lx, ExceptionAddress: %lx, BaseAddress: %lx\n",
+        DPRINT1("Kill %.16s, ExceptionCode: %lx, ExceptionAddress: %p, BaseAddress: %p, P0: %lx, P1: %lx\n",
                 PsGetCurrentProcess()->ImageFileName,
                 ExceptionRecord->ExceptionCode,
                 ExceptionRecord->ExceptionAddress,
-                PsGetCurrentProcess()->SectionBaseAddress);
+                PsGetCurrentProcess()->SectionBaseAddress,
+                ExceptionRecord->ExceptionInformation[0],
+                ExceptionRecord->ExceptionInformation[1]);
 
         ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
         KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
@@ -1110,6 +1097,7 @@ DECLSPEC_NORETURN
 VOID
 NTAPI
 KiDispatchExceptionFromTrapFrame(IN NTSTATUS Code,
+                                 IN ULONG Flags,
                                  IN ULONG_PTR Address,
                                  IN ULONG ParameterCount,
                                  IN ULONG_PTR Parameter1,
@@ -1121,7 +1109,7 @@ KiDispatchExceptionFromTrapFrame(IN NTSTATUS Code,
 
     /* Build the exception record */
     ExceptionRecord.ExceptionCode = Code;
-    ExceptionRecord.ExceptionFlags = 0;
+    ExceptionRecord.ExceptionFlags = Flags;
     ExceptionRecord.ExceptionRecord = NULL;
     ExceptionRecord.ExceptionAddress = (PVOID)Address;
     ExceptionRecord.NumberParameters = ParameterCount;
@@ -1132,7 +1120,7 @@ KiDispatchExceptionFromTrapFrame(IN NTSTATUS Code,
         ExceptionRecord.ExceptionInformation[1] = Parameter2;
         ExceptionRecord.ExceptionInformation[2] = Parameter3;
     }
-    
+
     /* Now go dispatch the exception */
     KiDispatchException(&ExceptionRecord,
                         NULL,