fix infinite loop in KeRosDumpStackFrames()
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.c
index d87c224..ce154ab 100644 (file)
 #define _STR(x) #x
 #define STR(x) _STR(x)
 
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
+#endif
+
 extern void interrupt_handler2e(void);
 extern void interrupt_handler2d(void);
 
@@ -60,6 +64,9 @@ extern VOID KiTrap13(VOID);
 extern VOID KiTrap14(VOID);
 extern VOID KiTrap15(VOID);
 extern VOID KiTrap16(VOID);
+extern VOID KiTrap17(VOID);
+extern VOID KiTrap18(VOID);
+extern VOID KiTrap19(VOID);
 extern VOID KiTrapUnknown(VOID);
 
 extern ULONG init_stack;
@@ -84,9 +91,11 @@ static char *ExceptionTypeStrings[] =
     "Stack Segment Fault",
     "General Protection",
     "Page Fault",
+    "Reserved(15)",
     "Math Fault",
     "Alignment Check",
-    "Machine Check"
+    "Machine Check",
+    "SIMD Fault"
   };
 
 static NTSTATUS ExceptionToNtStatus[] =
@@ -106,14 +115,16 @@ static NTSTATUS ExceptionToNtStatus[] =
     STATUS_STACK_OVERFLOW,
     STATUS_ACCESS_VIOLATION,
     STATUS_ACCESS_VIOLATION,
+    STATUS_ACCESS_VIOLATION, /* RESERVED */
     STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
     STATUS_DATATYPE_MISALIGNMENT,
-    STATUS_ACCESS_VIOLATION
+    STATUS_ACCESS_VIOLATION,
+    STATUS_ACCESS_VIOLATION  /* STATUS_FLT_MULTIPLE_TRAPS? */
   };
 
 /* FUNCTIONS ****************************************************************/
 
-#ifdef KDBG
+#if defined(DBG) || defined(KDBG)
 BOOLEAN STDCALL
 KeRosPrintAddress(PVOID address)
 {
@@ -167,7 +178,7 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
     }
   else
     {
-      if (ExceptionNr < 16)
+      if (ExceptionNr < ARRAY_SIZE(ExceptionToNtStatus))
        {
          Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
        }
@@ -190,7 +201,7 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
 ULONG
 KiDoubleFaultHandler(VOID)
 {
-  unsigned int cr2_;
+  unsigned int cr2;
   ULONG StackLimit;
   ULONG StackBase;
   ULONG Esp0;
@@ -211,15 +222,7 @@ KiDoubleFaultHandler(VOID)
   Esp0 = OldTss->Esp;
 
   /* Get CR2 */
-#if defined(__GNUC__)
-  __asm__("movl %%cr2,%0\n\t" : "=d" (cr2_));
-#elif defined(_MSC_VER)
-  __asm mov eax, cr2;
-  __asm mov cr2_, eax;
-#else
-#error Unknown compiler for inline assembler
-#endif
-
+  cr2 = Ke386GetCr2();
   if (PsGetCurrentThread() != NULL &&
       PsGetCurrentThread()->ThreadsProcess != NULL)
     {
@@ -245,7 +248,7 @@ KiDoubleFaultHandler(VOID)
    /*
     * Print out the CPU registers
     */
-   if (ExceptionNr < 19)
+   if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
      {
        DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
                ExceptionNr, 0);
@@ -257,7 +260,7 @@ KiDoubleFaultHandler(VOID)
    DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
    KeRosPrintAddress((PVOID)OldTss->Eip);
    DbgPrint("\n");
-   DbgPrint("cr2 %x cr3 %x ", cr2_, OldCr3);
+   DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
    DbgPrint("Proc: %x ",PsGetCurrentProcess());
    if (PsGetCurrentProcess() != NULL)
      {
@@ -420,7 +423,7 @@ KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
    /*
     * Print out the CPU registers
     */
-   if (ExceptionNr < 19)
+   if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
      {
        DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
                 ExceptionNr, Tf->ErrorCode&0xffff);
@@ -495,7 +498,6 @@ KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
        if (!KeRosPrintAddress(Eip))
         {
           DbgPrint("<%X>", Eip);
-          break;
         }
        Status = MmSafeCopyFromUser(&Frame, Frame, sizeof(Frame));
        if (!NT_SUCCESS(Status))
@@ -529,7 +531,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
  *        Complete CPU context
  */
 {
-   unsigned int cr2_;
+   unsigned int cr2;
    NTSTATUS Status;
    ULONG Esp0;
 
@@ -540,22 +542,20 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
    Esp0 = (ULONG)&Tf->Eip;
 
    /* Get CR2 */
-#if defined(__GNUC__)
-   __asm__("movl %%cr2,%0\n\t" : "=d" (cr2_));
-#elif defined(_MSC_VER)
-  __asm mov eax, cr2;
-  __asm mov cr2_, eax;
-#else
-#error Unknown compiler for inline assembler
-#endif
-   Tf->DebugPointer = (PVOID)cr2_;
+   cr2 = Ke386GetCr2();
+   Tf->DebugPointer = (PVOID)cr2;
+
+   if (ExceptionNr == 14 && Tf->Eflags & FLAG_IF)
+   {
+     Ke386EnableInterrupts();
+   }
 
    /*
     * If this was a V86 mode exception then handle it specially
     */
    if (Tf->Eflags & (1 << 17))
      {
-       return(KeV86Exception(ExceptionNr, Tf, cr2_));
+       return(KeV86Exception(ExceptionNr, Tf, cr2));
      }
 
    /*
@@ -574,18 +574,14 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
     */
    if (ExceptionNr == 14)
      {
-        if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2_ >= KERNEL_BASE)
+        if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2 >= KERNEL_BASE)
        {
            KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
        }
-        if (Tf->Eflags & FLAG_IF)
-       {
-         Ke386EnableInterrupts();
-       }
        Status = MmPageFault(Tf->Cs&0xffff,
                             &Tf->Eip,
                             &Tf->Eax,
-                            cr2_,
+                            cr2,
                             Tf->ErrorCode);
        if (NT_SUCCESS(Status))
          {
@@ -605,16 +601,28 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
        return(0);
      }
 
+   /*
+    * Try to handle device-not-present, math-fault and xmm-fault exceptions.
+    */
+   if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
+     {
+       Status = KiHandleFpuFault(Tf, ExceptionNr);
+       if (NT_SUCCESS(Status))
+         {
+           return(0);
+         }
+     }
+
    /*
     * Handle user exceptions differently
     */
    if ((Tf->Cs & 0xFFFF) == USER_CS)
      {
-       return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2_));
+       return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
      }
    else
     {
-      return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2_));
+      return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
     }
 }
 
@@ -651,13 +659,14 @@ KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
        }
        while ( MmIsAddressValid(Frame) && i++ < FrameCount )
        {
-               if (!KeRosPrintAddress((PVOID)Frame[1]))
+               ULONG Addr = Frame[1];
+               if (!KeRosPrintAddress((PVOID)Addr))
                {
-                       DbgPrint("<%X>", (PVOID)Frame[1]);
+                       DbgPrint("<%X>", Addr);
                }
-               if (Frame[1] == 0xdeadbeef)
+               if ( Addr == 0 || Addr == 0xDEADBEEF )
                {
-                   break;
+                       break;
                }
                Frame = (PULONG)Frame[0];
                DbgPrint(" ");
@@ -728,11 +737,14 @@ KeInitExceptions(VOID)
    set_interrupt_gate(14, (ULONG)KiTrap14);
    set_trap_gate(15, (ULONG)KiTrap15, 0);
    set_trap_gate(16, (ULONG)KiTrap16, 0);
+   set_trap_gate(17, (ULONG)KiTrap17, 0);
+   set_trap_gate(18, (ULONG)KiTrap18, 0);
+   set_trap_gate(19, (ULONG)KiTrap19, 0);
 
-   for (i=17;i<256;i++)
-        {
-          set_trap_gate(i,(int)KiTrapUnknown, 0);
-        }
+   for (i = 20; i < 256; i++)
+     {
+        set_trap_gate(i,(int)KiTrapUnknown, 0);
+     }
 
    set_system_call_gate(0x2d,(int)interrupt_handler2d);
    set_system_call_gate(0x2e,(int)interrupt_handler2e);
@@ -746,14 +758,14 @@ NTSTATUS STDCALL
 KeRaiseUserException(IN NTSTATUS ExceptionCode)
 {
    /* FIXME: This needs SEH */
-       ULONG OldEip;
-       PKTHREAD Thread = KeGetCurrentThread();
-
-       ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */
-       OldEip = Thread->TrapFrame->Eip;
-       Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
-       Thread->Teb->ExceptionCode = ExceptionCode;
-       return((NTSTATUS)OldEip);
+   ULONG OldEip;
+   PKTHREAD Thread = KeGetCurrentThread();
+
+   ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */
+   OldEip = Thread->TrapFrame->Eip;
+   Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
+   Thread->Teb->ExceptionCode = ExceptionCode;
+   return((NTSTATUS)OldEip);
 }
 
 VOID