Merge trunk head (r43756)
[reactos.git] / reactos / ntoskrnl / kd / kdmain.c
index 012d8a6..4a17c74 100644 (file)
@@ -2,24 +2,25 @@
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS Kernel
  * FILE:            ntoskrnl/kd/kdinit.c
- * PURPOSE:         Kernel Debugger Initializtion
+ * PURPOSE:         Kernel Debugger Initialization
  *
  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  */
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 /* VARIABLES ***************************************************************/
 
 BOOLEAN KdDebuggerEnabled = FALSE;
 BOOLEAN KdEnteredDebugger = FALSE;
 BOOLEAN KdDebuggerNotPresent = TRUE;
-BOOLEAN KiEnableTimerWatchdog = FALSE;
 BOOLEAN KdBreakAfterSymbolLoad = FALSE;
-BOOLEAN KdpBreakPending;
-VOID STDCALL PspDumpThreads(BOOLEAN SystemThreads);
+BOOLEAN KdpBreakPending = FALSE;
+BOOLEAN KdPitchDebugger = TRUE;
+BOOLEAN KdIgnoreUmExceptions = FALSE;
+VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads);
 
 typedef struct
 {
@@ -30,10 +31,12 @@ typedef struct
 KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES];
 ULONG KdComponentTableEntries = 0;
 
+ULONG Kd_DEFAULT_MASK = 1 << DPFLTR_ERROR_LEVEL;
+
 /* PRIVATE FUNCTIONS *********************************************************/
 
 ULONG
-STDCALL
+NTAPI
 KdpServiceDispatcher(ULONG Service,
                      PVOID Buffer1,
                      ULONG Buffer1Length)
@@ -46,29 +49,13 @@ KdpServiceDispatcher(ULONG Service,
             Result = KdpPrintString(Buffer1, Buffer1Length);
             break;
 
-#ifdef DBG
-        case TAG('R', 'o', 's', ' '): /* ROS-INTERNAL */
+#if DBG
+        case ' soR': /* ROS-INTERNAL */
         {
-            switch ((ULONG)Buffer1)
+            switch ((ULONG_PTR)Buffer1)
             {
-                case DumpNonPagedPool:
-                    MiDebugDumpNonPagedPool(FALSE);
-                    break;
-
                 case ManualBugCheck:
-                    KEBUGCHECK(MANUALLY_INITIATED_CRASH);
-                    break;
-
-                case DumpNonPagedPoolStats:
-                    MiDebugDumpNonPagedPoolStats(FALSE);
-                    break;
-
-                case DumpNewNonPagedPool:
-                    MiDebugDumpNonPagedPool(TRUE);
-                    break;
-
-                case DumpNewNonPagedPoolStats:
-                    MiDebugDumpNonPagedPoolStats(TRUE);
+                    KeBugCheck(MANUALLY_INITIATED_CRASH);
                     break;
 
                 case DumpAllThreads:
@@ -82,10 +69,22 @@ KdpServiceDispatcher(ULONG Service,
                 case EnterDebugger:
                     DbgBreakPoint();
                     break;
+                    
+                case ThatsWhatSheSaid:
+                    MmDumpPfnDatabase();
+                    break;
 
                 default:
                     break;
             }
+            break;
+        }
+
+        /* Special  case for stack frame dumps */
+        case 'DsoR':
+        {
+            KeRosDumpStackFrames((PULONG)Buffer1, Buffer1Length);
+            break;
         }
 #endif
         default:
@@ -105,7 +104,7 @@ KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
                           IN KPROCESSOR_MODE PreviousMode,
                           IN BOOLEAN SecondChance)
 {
-    KD_CONTINUE_TYPE Return;
+    KD_CONTINUE_TYPE Return = kdHandleException;
     ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
 
     /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
@@ -114,7 +113,8 @@ KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
         ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
          (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
          (ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
-         (ExceptionCommand == BREAKPOINT_PRINT)))
+         (ExceptionCommand == BREAKPOINT_PRINT) ||
+         (ExceptionCommand == BREAKPOINT_PROMPT)))
     {
         /* Check if this is a debug print */
         if (ExceptionCommand == BREAKPOINT_PRINT)
@@ -123,26 +123,86 @@ KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
             KdpServiceDispatcher(BREAKPOINT_PRINT,
                                  (PVOID)ExceptionRecord->ExceptionInformation[1],
                                  ExceptionRecord->ExceptionInformation[2]);
+
+            /* Return success */
+            KeSetContextReturnRegister(Context, STATUS_SUCCESS);
+        }
+#ifdef KDBG
+        else if (ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS)
+        {
+            PLDR_DATA_TABLE_ENTRY LdrEntry;
+
+            /* Load symbols. Currently implemented only for KDBG! */
+            if(KdbpSymFindModule(((PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2])->BaseOfDll, NULL, -1, &LdrEntry))
+                KdbSymProcessSymbols(LdrEntry);
+        }
+        else if (ExceptionCommand == BREAKPOINT_PROMPT)
+        {
+            ULONG ReturnValue;
+            LPSTR OutString;
+            USHORT OutStringLength;
+
+            /* Get the response string  and length */
+            OutString = (LPSTR)Context->Ebx;
+            OutStringLength = (USHORT)Context->Edi;
+
+            /* Call KDBG */
+            ReturnValue = KdpPrompt((LPSTR)ExceptionRecord->
+                                    ExceptionInformation[1],
+                                    (USHORT)ExceptionRecord->
+                                    ExceptionInformation[2],
+                                    OutString,
+                                    OutStringLength);
+
+            /* Return the number of characters that we received */
+            Context->Eax = ReturnValue;
         }
+#endif
 
-        /* This we can handle: simply bump EIP */
-        Context->Eip++;
+        /* This we can handle: simply bump the Program Counter */
+        KeSetContextPc(Context, KeGetContextPc(Context) + KD_BREAKPOINT_SIZE);
         return TRUE;
     }
 
+#ifdef KDBG
+    /* Check if this is an assertion failure */
+    if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE)
+    {
+        /* Warn about it */
+        DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n",
+                 (PVOID)Context->Eip);
+
+        /* Bump EIP to the instruction following the int 2C and return */
+        Context->Eip += 2;
+        return TRUE;
+    }
+#endif
+
     /* Get out of here if the Debugger isn't connected */
     if (KdDebuggerNotPresent) return FALSE;
 
+#ifdef KDBG
     /* Call KDBG if available */
     Return = KdbEnterDebuggerException(ExceptionRecord,
                                        PreviousMode,
                                        Context,
                                        TrapFrame,
                                        !SecondChance);
+#else /* not KDBG */
+    if (WrapperInitRoutine)
+    {
+        /* Call GDB */
+        Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord,
+                                                  Context,
+                                                  TrapFrame);
+    }
+#endif /* not KDBG */
 
-    /* Convert return to BOOLEAN */
-    if (Return == kdContinue) return TRUE;
-    return FALSE;
+    /* Debugger didn't handle it, please handle! */
+    if (Return == kdHandleException) return FALSE;
+
+    /* Debugger handled it */
+    return TRUE;
 }
 
 BOOLEAN
@@ -169,18 +229,43 @@ KdpCallGdb(IN PKTRAP_FRAME TrapFrame,
                                                   TrapFrame);
     }
 
-    /* Convert return to BOOLEAN */
-    if (Return == kdContinue) return TRUE;
+    /* Debugger didn't handle it, please handle! */
+    if (Return == kdHandleException) return FALSE;
+
+    /* Debugger handled it */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord,
+                IN PCONTEXT Context,
+                IN KPROCESSOR_MODE PreviousMode)
+{
+    /* KDBG has its own mechanism for ignoring user mode exceptions */
     return FALSE;
 }
 
 /* PUBLIC FUNCTIONS *********************************************************/
 
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+KdRefreshDebuggerNotPresent(VOID)
+{
+    UNIMPLEMENTED;
+
+    /* Just return whatever was set previously -- FIXME! */
+    return KdDebuggerNotPresent;
+}
+
 /*
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 KdDisableDebugger(VOID)
 {
     KIRQL OldIrql;
@@ -204,7 +289,7 @@ KdDisableDebugger(VOID)
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 KdEnableDebugger(VOID)
 {
     KIRQL OldIrql;
@@ -228,33 +313,17 @@ KdEnableDebugger(VOID)
  * @implemented
  */
 BOOLEAN
-STDCALL
+NTAPI
 KdPollBreakIn(VOID)
 {
     return KdpBreakPending;
 }
 
-/*
- * @implemented
- */
-VOID
-STDCALL
-KeEnterKernelDebugger(VOID)
-{
-    HalDisplayString("\n\n *** Entered kernel debugger ***\n");
-
-    /* Set the Variable */
-    KdEnteredDebugger = TRUE;
-
-    /* Halt the CPU */
-    for (;;) Ke386HaltProcessor();
-}
-
 /*
  * @unimplemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 KdPowerTransition(ULONG PowerState)
 {
     UNIMPLEMENTED;
@@ -279,55 +348,92 @@ KdChangeOption(IN KD_OPTION Option,
 
 
 NTSTATUS
-STDCALL
+NTAPI
 NtQueryDebugFilterState(IN ULONG ComponentId,
                         IN ULONG Level)
 {
-       unsigned int i;
-
-       /* convert Level to mask if it isn't already one */
-       if ( Level < 32 )
-               Level = 1 << Level;
-
-       for ( i = 0; i < KdComponentTableEntries; i++ )
-       {
-               if ( ComponentId == KdComponentTable[i].ComponentId )
-               {
-                       if ( Level & KdComponentTable[i].Level )
-                               return TRUE;
-                       break;
-               }
-       }
-       return FALSE;
+    ULONG i;
+
+    /* Convert Level to mask if it isn't already one */
+    if (Level < 32)
+        Level = 1 << Level;
+
+    /* Check if it is not the default component */
+    if (ComponentId != DPFLTR_DEFAULT_ID)
+    {
+        /* No, search for an existing entry in the table */
+        for (i = 0; i < KdComponentTableEntries; i++)
+        {
+            /* Check if it is the right component */
+            if (ComponentId == KdComponentTable[i].ComponentId)
+            {
+                /* Check if mask are matching */
+                return (Level & KdComponentTable[i].Level) ? TRUE : FALSE;
+            }
+        }
+    }
+
+    /* Entry not found in the table, use default mask */
+    return (Level & Kd_DEFAULT_MASK) ? TRUE : FALSE;
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 NtSetDebugFilterState(IN ULONG ComponentId,
                       IN ULONG Level,
                       IN BOOLEAN State)
 {
-       unsigned int i;
-       for ( i = 0; i < KdComponentTableEntries; i++ )
-       {
-               if ( ComponentId == KdComponentTable[i].ComponentId )
-                       break;
-       }
-       if ( i == KdComponentTableEntries )
-       {
-               if ( i == MAX_KD_COMPONENT_TABLE_ENTRIES )
-                       return STATUS_INVALID_PARAMETER_1;
-               ++KdComponentTableEntries;
-               KdComponentTable[i].ComponentId = ComponentId;
-               KdComponentTable[i].Level = 0;
-       }
-       if ( State )
-               KdComponentTable[i].Level |= Level;
-       else
-               KdComponentTable[i].Level &= ~Level;
-       return STATUS_SUCCESS;
+    ULONG i;
+
+    /* Convert Level to mask if it isn't already one */
+    if (Level < 32)
+        Level = 1 << Level;
+    Level &= ~DPFLTR_MASK;
+
+    /* Check if it is the default component */
+    if (ComponentId == DPFLTR_DEFAULT_ID)
+    {
+        /* Yes, modify the default mask */
+        if (State)
+            Kd_DEFAULT_MASK |= Level;
+        else
+            Kd_DEFAULT_MASK &= ~Level;
+
+        return STATUS_SUCCESS;
+    }
+
+    /* Search for an existing entry */
+    for (i = 0; i < KdComponentTableEntries; i++ )
+    {
+        if (ComponentId == KdComponentTable[i].ComponentId)
+            break;
+    }
+
+    /* Check if we have found an existing entry */
+    if (i == KdComponentTableEntries)
+    {
+        /* Check if we have enough space in the table */
+        if (i == MAX_KD_COMPONENT_TABLE_ENTRIES)
+            return STATUS_INVALID_PARAMETER_1;
+
+        /* Add a new entry */
+        ++KdComponentTableEntries;
+        KdComponentTable[i].ComponentId = ComponentId;
+        KdComponentTable[i].Level = Kd_DEFAULT_MASK;
+    }
+
+    /* Update entry table */
+    if (State)
+        KdComponentTable[i].Level |= Level;
+    else
+        KdComponentTable[i].Level &= ~Level;
+
+    return STATUS_SUCCESS;
 }
 
+/*
+ * @unimplemented
+ */
 NTSTATUS
 NTAPI
 KdSystemDebugControl(IN SYSDBG_COMMAND Command,