Sync to trunk head (r42241)
[reactos.git] / reactos / ntoskrnl / kdbg / kdb.c
index 972d4b4..3c1fd71 100644 (file)
@@ -6,19 +6,15 @@
  *
  * PROGRAMMERS:     Gregor Anich
  */
-      
+
 /* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 /* TYPES *********************************************************************/
 
-/* FIXME: NDK headers */
-#define TempEsp TempEip
-#define TempSegSs TempCs
-
 /* DEFINES *******************************************************************/
 
 #define KDB_STACK_SIZE                   (4096*3)
 
 /* GLOBALS *******************************************************************/
 
-STATIC LONG KdbEntryCount = 0;
-STATIC CHAR KdbStack[KDB_STACK_SIZE];
+static LONG KdbEntryCount = 0;
+static CHAR KdbStack[KDB_STACK_SIZE];
 
-STATIC ULONG KdbBreakPointCount = 0;  /* Number of used breakpoints in the array */
-STATIC KDB_BREAKPOINT KdbBreakPoints[KDB_MAXIMUM_BREAKPOINT_COUNT] = {{0}};  /* Breakpoint array */
-STATIC ULONG KdbSwBreakPointCount = 0;  /* Number of enabled software breakpoints */
-STATIC ULONG KdbHwBreakPointCount = 0;  /* Number of enabled hardware breakpoints */
-STATIC PKDB_BREAKPOINT KdbSwBreakPoints[KDB_MAXIMUM_SW_BREAKPOINT_COUNT]; /* Enabled software breakpoints, orderless */
-STATIC PKDB_BREAKPOINT KdbHwBreakPoints[KDB_MAXIMUM_HW_BREAKPOINT_COUNT]; /* Enabled hardware breakpoints, orderless */
-STATIC PKDB_BREAKPOINT KdbBreakPointToReenable = NULL; /* Set to a breakpoint struct when single stepping after
+static ULONG KdbBreakPointCount = 0;  /* Number of used breakpoints in the array */
+static KDB_BREAKPOINT KdbBreakPoints[KDB_MAXIMUM_BREAKPOINT_COUNT] = {{0}};  /* Breakpoint array */
+static ULONG KdbSwBreakPointCount = 0;  /* Number of enabled software breakpoints */
+static ULONG KdbHwBreakPointCount = 0;  /* Number of enabled hardware breakpoints */
+static PKDB_BREAKPOINT KdbSwBreakPoints[KDB_MAXIMUM_SW_BREAKPOINT_COUNT]; /* Enabled software breakpoints, orderless */
+static PKDB_BREAKPOINT KdbHwBreakPoints[KDB_MAXIMUM_HW_BREAKPOINT_COUNT]; /* Enabled hardware breakpoints, orderless */
+static PKDB_BREAKPOINT KdbBreakPointToReenable = NULL; /* Set to a breakpoint struct when single stepping after
                                                           a software breakpoint was hit, to reenable it */
 LONG KdbLastBreakPointNr = -1;  /* Index of the breakpoint which cause KDB to be entered */
 ULONG KdbNumSingleSteps = 0; /* How many single steps to do */
 BOOLEAN KdbSingleStepOver = FALSE; /* Whether to step over calls/reps. */
 ULONG KdbDebugState = 0; /* KDBG Settings (NOECHO, KDSERIAL) */
-STATIC BOOLEAN KdbEnteredOnSingleStep = FALSE; /* Set to true when KDB was entered because of single step */
+static BOOLEAN KdbEnteredOnSingleStep = FALSE; /* Set to true when KDB was entered because of single step */
 PEPROCESS KdbCurrentProcess = NULL;  /* The current process context in which KDB runs */
 PEPROCESS KdbOriginalProcess = NULL; /* The process in whichs context KDB was intered */
 PETHREAD KdbCurrentThread = NULL;  /* The current thread context in which KDB runs */
 PETHREAD KdbOriginalThread = NULL; /* The thread in whichs context KDB was entered */
 PKDB_KTRAP_FRAME KdbCurrentTrapFrame = NULL; /* Pointer to the current trapframe */
-STATIC KDB_KTRAP_FRAME KdbTrapFrame = { { 0 } };  /* The trapframe which was passed to KdbEnterDebuggerException */
-STATIC KDB_KTRAP_FRAME KdbThreadTrapFrame = { { 0 } }; /* The trapframe of the current thread (KdbCurrentThread) */
-STATIC KAPC_STATE KdbApcState;
+static KDB_KTRAP_FRAME KdbTrapFrame = { { 0 } };  /* The trapframe which was passed to KdbEnterDebuggerException */
+static KDB_KTRAP_FRAME KdbThreadTrapFrame = { { 0 } }; /* The trapframe of the current thread (KdbCurrentThread) */
+static KAPC_STATE KdbApcState;
+extern BOOLEAN KdbpBugCheckRequested;
 
 /* Array of conditions when to enter KDB */
-STATIC KDB_ENTER_CONDITION KdbEnterConditions[][2] =
+static KDB_ENTER_CONDITION KdbEnterConditions[][2] =
 {
    /* First chance       Last chance */
    { KdbDoNotEnter,      KdbEnterFromKmode },   /* Zero devide */
-   { KdbEnterAlways,     KdbDoNotEnter },       /* Debug trap */
+   { KdbEnterFromKmode,  KdbDoNotEnter },       /* Debug trap */
    { KdbDoNotEnter,      KdbEnterAlways },      /* NMI */
    { KdbEnterFromKmode,  KdbDoNotEnter },       /* INT3 */
    { KdbDoNotEnter,      KdbEnterFromKmode },   /* Overflow */
@@ -84,7 +81,7 @@ STATIC KDB_ENTER_CONDITION KdbEnterConditions[][2] =
 };
 
 /* Exception descriptions */
-STATIC CONST PCHAR ExceptionNrToString[] =
+static const CHAR *ExceptionNrToString[] =
 {
    "Divide Error",
    "Debug Trap",
@@ -108,67 +105,120 @@ STATIC CONST PCHAR ExceptionNrToString[] =
    "SIMD Fault"
 };
 
+ULONG
+NTAPI
+KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame);
+
+ULONG
+NTAPI
+KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame);
+
+VOID
+NTAPI
+KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                IN ULONG Ss);
+
+VOID
+NTAPI
+KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                 IN ULONG Esp);
+
+/* ROS Internal. Please deprecate */
+NTHALAPI
+VOID
+NTAPI
+HalReleaseDisplayOwnership(
+    VOID
+);
+
 /* FUNCTIONS *****************************************************************/
 
-STATIC VOID
+static VOID
 KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFrame)
 {
+   ULONG TrapCr0, TrapCr2, TrapCr3, TrapCr4;
+
    /* Copy the TrapFrame only up to Eflags and zero the rest*/
-   RtlCopyMemory(&KdbTrapFrame->Tf, TrapFrame, FIELD_OFFSET(KTRAP_FRAME, Esp));
-   RtlZeroMemory((PVOID)((ULONG_PTR)&KdbTrapFrame->Tf + FIELD_OFFSET(KTRAP_FRAME, Esp)),
-                 sizeof (KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, Esp));
+   RtlCopyMemory(&KdbTrapFrame->Tf, TrapFrame, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
+   RtlZeroMemory((PVOID)((ULONG_PTR)&KdbTrapFrame->Tf + FIELD_OFFSET(KTRAP_FRAME, HardwareEsp)),
+                 sizeof (KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
+
+#ifndef _MSC_VER
    asm volatile(
       "movl %%cr0, %0"    "\n\t"
       "movl %%cr2, %1"    "\n\t"
       "movl %%cr3, %2"    "\n\t"
       "movl %%cr4, %3"    "\n\t"
-      : "=r"(KdbTrapFrame->Cr0), "=r"(KdbTrapFrame->Cr2),
-        "=r"(KdbTrapFrame->Cr3), "=r"(KdbTrapFrame->Cr4));
-   
-   if (TrapFrame->PreviousMode == KernelMode)
-   {
-      /* If the trapframe is a kmode one use the temp ss:esp */
-      KdbTrapFrame->Tf.Esp = (ULONG)TrapFrame->TempEsp;
-      KdbTrapFrame->Tf.Ss = (USHORT)((ULONG)TrapFrame->TempSegSs & 0xFFFF);
-   }
-   else
+      : "=r"(TrapCr0), "=r"(TrapCr2),
+        "=r"(TrapCr3), "=r"(TrapCr4));
+#else
+   __asm
    {
-      /* Otherwise use ss:esp pushed by the CPU */
-      /* FIXME: maybe change all trapframes to always put ss:esp into tempss:tempesp so we
-       *        can handle umode and kmode the same way */
-      KdbTrapFrame->Tf.Esp = TrapFrame->Esp;
-      KdbTrapFrame->Tf.Ss = TrapFrame->Ss;
+       mov eax, cr0;
+       mov TrapCr0, eax;
+
+       mov eax, cr2;
+       mov TrapCr2, eax;
+
+       mov eax, cr3;
+       mov TrapCr3, eax;
+/* FIXME: What's the problem with cr4? */
+       //mov eax, cr4;
+       //mov TrapCr4, eax;
    }
-   
+#endif
+
+    KdbTrapFrame->Cr0 = TrapCr0;
+    KdbTrapFrame->Cr2 = TrapCr2;
+    KdbTrapFrame->Cr3 = TrapCr3;
+    KdbTrapFrame->Cr4 = TrapCr4;
+
+    KdbTrapFrame->Tf.HardwareEsp = KiEspFromTrapFrame(TrapFrame);
+    KdbTrapFrame->Tf.HardwareSegSs = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
+
+
    /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
 }
 
-STATIC VOID
+static VOID
 KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFrame)
 {
    /* Copy the TrapFrame only up to Eflags and zero the rest*/
-   RtlCopyMemory(TrapFrame, &KdbTrapFrame->Tf, FIELD_OFFSET(KTRAP_FRAME, Esp));
-   
+   RtlCopyMemory(TrapFrame, &KdbTrapFrame->Tf, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
+
    /* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
-   
-   if (TrapFrame->PreviousMode == KernelMode)
-   {
-      /* If the trapframe is a kmode one write to the temp ss:esp */
-      TrapFrame->TempEsp = (PVOID)KdbTrapFrame->Tf.Esp;
-      TrapFrame->TempSegSs = (PVOID)(((ULONG)TrapFrame->TempSegSs & ~0xffff) | KdbTrapFrame->Tf.Ss);
-   }
-   else
-   {
-      /* Otherwise write to ss:esp pushed by the CPU */
-      /* FIXME: maybe change all trap-epilogs to always put temp ss:esp into ss:esp so we
-       *        can handle umode and kmode the same way */
-      TrapFrame->Esp = KdbTrapFrame->Tf.Esp;
-      TrapFrame->Ss = KdbTrapFrame->Tf.Ss;
-   }
-   
+
+    KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.HardwareSegSs);
+    KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.HardwareEsp);
+
    /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
 }
 
+static VOID
+KdbpKdbTrapFrameFromKernelStack(PVOID KernelStack,
+                                PKDB_KTRAP_FRAME KdbTrapFrame)
+{
+   ULONG_PTR *StackPtr;
+
+   RtlZeroMemory(KdbTrapFrame, sizeof(KDB_KTRAP_FRAME));
+   StackPtr = (ULONG_PTR *) KernelStack;
+#if _M_X86_
+   KdbTrapFrame->Tf.Ebp = StackPtr[3];
+   KdbTrapFrame->Tf.Edi = StackPtr[4];
+   KdbTrapFrame->Tf.Esi = StackPtr[5];
+   KdbTrapFrame->Tf.Ebx = StackPtr[6];
+   KdbTrapFrame->Tf.Eip = StackPtr[7];
+   KdbTrapFrame->Tf.HardwareEsp = (ULONG) (StackPtr + 8);
+   KdbTrapFrame->Tf.HardwareSegSs = KGDT_R0_DATA;
+   KdbTrapFrame->Tf.SegCs = KGDT_R0_CODE;
+   KdbTrapFrame->Tf.SegDs = KGDT_R0_DATA;
+   KdbTrapFrame->Tf.SegEs = KGDT_R0_DATA;
+   KdbTrapFrame->Tf.SegGs = KGDT_R0_DATA;
+#endif
+
+   /* FIXME: what about the other registers??? */
+}
+
 /*!\brief Overwrites the instruction at \a Address with \a NewInst and stores
  *        the old instruction in *OldInst.
  *
@@ -179,7 +229,7 @@ KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFram
  *
  * \returns NTSTATUS
  */
-STATIC NTSTATUS
+static NTSTATUS
 KdbpOverwriteInstruction(
    IN  PEPROCESS Process,
    IN  ULONG_PTR Address,
@@ -203,7 +253,7 @@ KdbpOverwriteInstruction(
    /* Attach to the process */
    if (CurrentProcess != Process)
    {
-      KeStackAttachProcess(EPROCESS_TO_KPROCESS(Process), &ApcState);
+      KeStackAttachProcess(&Process->Pcb, &ApcState);
    }
 
    /* Make the page writeable if it is read only. */
@@ -260,11 +310,11 @@ BOOLEAN
 KdbpShouldStepOverInstruction(ULONG_PTR Eip)
 {
    UCHAR Mem[3];
-   INT i = 0;
+   ULONG i = 0;
 
    if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
    {
-      KdbpPrint("Couldn't access memory at 0x%x\n", (UINT)Eip);
+      KdbpPrint("Couldn't access memory at 0x%p\n", Eip);
       return FALSE;
    }
 
@@ -320,10 +370,7 @@ KdbpStepOverInstruction(ULONG_PTR Eip)
 BOOLEAN
 KdbpStepIntoInstruction(ULONG_PTR Eip)
 {
-   struct __attribute__((packed)) {
-      USHORT Limit;
-      ULONG Base;
-   } Idtr;
+    KDESCRIPTOR Idtr = {0};
    UCHAR Mem[2];
    INT IntVect;
    ULONG IntDesc[2];
@@ -332,7 +379,7 @@ KdbpStepIntoInstruction(ULONG_PTR Eip)
    /* Read memory */
    if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
    {
-      /*KdbpPrint("Couldn't access memory at 0x%x\n", (UINT)Eip);*/
+      /*KdbpPrint("Couldn't access memory at 0x%p\n", Eip);*/
       return FALSE;
    }
 
@@ -342,7 +389,7 @@ KdbpStepIntoInstruction(ULONG_PTR Eip)
       IntVect = 3;
    else if (Mem[0] == 0xcd)
       IntVect = Mem[1];
-   else if (Mem[0] == 0xce && KdbCurrentTrapFrame->Tf.Eflags & (1<<11)) /* 1 << 11 is the overflow flag */
+   else if (Mem[0] == 0xce && KdbCurrentTrapFrame->Tf.EFlags & (1<<11)) /* 1 << 11 is the overflow flag */
       IntVect = 4;
    else
       return FALSE;
@@ -353,7 +400,7 @@ KdbpStepIntoInstruction(ULONG_PTR Eip)
    }
 
    /* Read the interrupt descriptor table register  */
-   asm volatile("sidt %0" : : "m"(Idtr));
+   Ke386GetInterruptDescriptorTable(*(PKDESCRIPTOR)&Idtr.Limit);
    if (IntVect >= (Idtr.Limit + 1) / 8)
    {
       /*KdbpPrint("IDT does not contain interrupt vector %d\n.", IntVect);*/
@@ -361,9 +408,9 @@ KdbpStepIntoInstruction(ULONG_PTR Eip)
    }
 
    /* Get the interrupt descriptor */
-   if (!NT_SUCCESS(KdbpSafeReadMemory(IntDesc, (PVOID)(Idtr.Base + (IntVect * 8)), sizeof (IntDesc))))
+   if (!NT_SUCCESS(KdbpSafeReadMemory(IntDesc, (PVOID)(ULONG_PTR)(Idtr.Base + (IntVect * 8)), sizeof (IntDesc))))
    {
-      /*KdbpPrint("Couldn't access memory at 0x%x\n", (UINT)Idtr.Base + (IntVect * 8));*/
+      /*KdbpPrint("Couldn't access memory at 0x%p\n", (ULONG_PTR)Idtr.Base + (IntVect * 8));*/
       return FALSE;
    }
 
@@ -496,7 +543,7 @@ KdbpInsertBreakPoint(
    IN  KDB_ACCESS_TYPE AccessType  OPTIONAL,
    IN  PCHAR ConditionExpression  OPTIONAL,
    IN  BOOLEAN Global,
-   OUT PULONG BreakPointNumber  OPTIONAL)
+   OUT PLONG BreakPointNr  OPTIONAL)
 {
    LONG i;
    PVOID Condition;
@@ -510,7 +557,7 @@ KdbpInsertBreakPoint(
    {
       if ((Address % Size) != 0)
       {
-         KdbpPrint("Address (0x%x) must be aligned to a multiple of the size (%d)\n", Address, Size);
+         KdbpPrint("Address (0x%p) must be aligned to a multiple of the size (%d)\n", Address, Size);
          return STATUS_UNSUCCESSFUL;
       }
       if (AccessType == KdbAccessExec && Size != 1)
@@ -560,13 +607,13 @@ KdbpInsertBreakPoint(
    }
    else
    {
-      for (i = 0; i < RTL_NUMBER_OF(KdbBreakPoints); i++)
+      for (i = 0; i < (LONG)RTL_NUMBER_OF(KdbBreakPoints); i++)
       {
          if (KdbBreakPoints[i].Type == KdbBreakPointNone)
             break;
       }
    }
-   ASSERT(i < RTL_NUMBER_OF(KdbBreakPoints));
+   ASSERT(i < (LONG)RTL_NUMBER_OF(KdbBreakPoints));
 
    /* Set the breakpoint */
    ASSERT(KdbCurrentProcess != NULL);
@@ -592,8 +639,8 @@ KdbpInsertBreakPoint(
    KdbpEnableBreakPoint(i, NULL);
 
    /* Return the breakpoint number */
-   if (BreakPointNumber != NULL)
-      *BreakPointNumber = i;
+   if (BreakPointNr != NULL)
+      *BreakPointNr = i;
 
    return STATUS_SUCCESS;
 }
@@ -653,15 +700,15 @@ KdbpDeleteBreakPoint(
  *
  * \returns Breakpoint number, -1 on error.
  */
-STATIC LONG
+static LONG
 KdbpIsBreakPointOurs(
-   IN ULONG ExpNr,
+   IN NTSTATUS ExceptionCode,
    IN PKTRAP_FRAME TrapFrame)
 {
-   INT i;
-   ASSERT(ExpNr == 1 || ExpNr == 3);
+   ULONG i;
+   ASSERT(ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT);
 
-   if (ExpNr == 3) /* Software interrupt */
+   if (ExceptionCode == STATUS_BREAKPOINT) /* Software interrupt */
    {
       ULONG_PTR BpEip = (ULONG_PTR)TrapFrame->Eip - 1; /* Get EIP of INT3 instruction */
       for (i = 0; i < KdbSwBreakPointCount; i++)
@@ -675,7 +722,7 @@ KdbpIsBreakPointOurs(
          }
       }
    }
-   else if (ExpNr == 1) /* Hardware interrupt */
+   else if (ExceptionCode == STATUS_SINGLE_STEP) /* Hardware interrupt */
    {
       UCHAR DebugReg;
       for (i = 0; i < KdbHwBreakPointCount; i++)
@@ -752,7 +799,7 @@ KdbpEnableBreakPoint(
                                         0xCC, &BreakPoint->Data.SavedInstruction);
       if (!NT_SUCCESS(Status))
       {
-         KdbpPrint("Couldn't access memory at 0x%x\n", BreakPoint->Address);
+         KdbpPrint("Couldn't access memory at 0x%p\n", BreakPoint->Address);
          return FALSE;
       }
       KdbSwBreakPoints[KdbSwBreakPointCount++] = BreakPoint;
@@ -864,7 +911,7 @@ KdbpDisableBreakPoint(
    IN LONG BreakPointNr  OPTIONAL,
    IN OUT PKDB_BREAKPOINT BreakPoint  OPTIONAL)
 {
-   INT i;
+   ULONG i;
    NTSTATUS Status;
 
    if (BreakPointNr < 0)
@@ -914,7 +961,7 @@ KdbpDisableBreakPoint(
             break;
          }
       }
-      if (i != -1) /* not found */
+      if (i != (ULONG)-1) /* not found */
          ASSERT(0);
    }
    else
@@ -940,7 +987,7 @@ KdbpDisableBreakPoint(
             break;
          }
       }
-      if (i != -1) /* not found */
+      if (i != (ULONG)-1) /* not found */
          ASSERT(0);
    }
 
@@ -965,7 +1012,7 @@ KdbpGetEnterCondition(
    IN BOOLEAN FirstChance,
    OUT KDB_ENTER_CONDITION *Condition)
 {
-   if (ExceptionNr >= RTL_NUMBER_OF(KdbEnterConditions))
+   if (ExceptionNr >= (LONG)RTL_NUMBER_OF(KdbEnterConditions))
       return FALSE;
 
    *Condition = KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1];
@@ -989,7 +1036,7 @@ KdbpSetEnterCondition(
 {
    if (ExceptionNr < 0)
    {
-      for (ExceptionNr = 0; ExceptionNr < RTL_NUMBER_OF(KdbEnterConditions); ExceptionNr++)
+      for (ExceptionNr = 0; ExceptionNr < (LONG)RTL_NUMBER_OF(KdbEnterConditions); ExceptionNr++)
       {
          if (ExceptionNr == 1 || ExceptionNr == 8 ||
              ExceptionNr == 9 || ExceptionNr == 15) /* Reserved exceptions */
@@ -1001,7 +1048,7 @@ KdbpSetEnterCondition(
    }
    else
    {
-      if (ExceptionNr >= RTL_NUMBER_OF(KdbEnterConditions) ||
+      if (ExceptionNr >= (LONG)RTL_NUMBER_OF(KdbEnterConditions) ||
           ExceptionNr == 1 || ExceptionNr == 8 || /* Do not allow changing of the debug */
           ExceptionNr == 9 || ExceptionNr == 15)  /* trap or reserved exceptions */
       {
@@ -1029,7 +1076,7 @@ KdbpAttachToThread(
    /* Get a pointer to the thread */
    if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &Thread)))
    {
-      KdbpPrint("Invalid thread id: 0x%08x\n", (UINT)ThreadId);
+      KdbpPrint("Invalid thread id: 0x%08x\n", (ULONG_PTR)ThreadId);
       return FALSE;
    }
    Process = Thread->ThreadsProcess;
@@ -1037,6 +1084,7 @@ KdbpAttachToThread(
    if (KeIsExecutingDpc() && Process != KdbCurrentProcess)
    {
       KdbpPrint("Cannot attach to thread within another process while executing a DPC.\n");
+      ObDereferenceObject(Thread);
       return FALSE;
    }
 
@@ -1044,7 +1092,8 @@ KdbpAttachToThread(
    if (KdbCurrentThread != KdbOriginalThread)
    {
       ASSERT(KdbCurrentTrapFrame == &KdbThreadTrapFrame);
-      KdbpKdbTrapFrameToTrapFrame(KdbCurrentTrapFrame, KdbCurrentThread->Tcb.TrapFrame);
+      /* Actually, we can't save the context, there's no guarantee that there
+       * was a trap frame */
    }
    else
    {
@@ -1054,12 +1103,13 @@ KdbpAttachToThread(
    /* Switch to the thread's context */
    if (Thread != KdbOriginalThread)
    {
-      if (Thread->Tcb.TrapFrame == NULL)
-      {
-         KdbpPrint("Threads TrapFrame is NULL! Cannot attach.\n");
-         return FALSE;
-      }
-      KdbpTrapFrameToKdbTrapFrame(Thread->Tcb.TrapFrame, &KdbThreadTrapFrame);
+      /* The thread we're attaching to isn't the thread on which we entered
+       * kdb and so the thread we're attaching to is not running. There
+       * is no guarantee that it actually has a trap frame. So we have to
+       * peek directly at the registers which were saved on the stack when the
+       * thread was preempted in the scheduler */
+      KdbpKdbTrapFrameFromKernelStack(Thread->Tcb.KernelStack,
+                                      &KdbThreadTrapFrame);
       KdbCurrentTrapFrame = &KdbThreadTrapFrame;
    }
    else /* Switching back to original thread */
@@ -1078,11 +1128,12 @@ KdbpAttachToThread(
       }
       if (KdbOriginalProcess != Process)
       {
-         KeStackAttachProcess(EPROCESS_TO_KPROCESS(Process), &KdbApcState);
+         KeStackAttachProcess(&Process->Pcb, &KdbApcState);
       }
       KdbCurrentProcess = Process;
    }
 
+   ObDereferenceObject(Thread);
    return TRUE;
 }
 
@@ -1106,14 +1157,15 @@ KdbpAttachToProcess(
    /* Get a pointer to the process */
    if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process)))
    {
-      KdbpPrint("Invalid process id: 0x%08x\n", (UINT)ProcessId);
+      KdbpPrint("Invalid process id: 0x%08x\n", (ULONG_PTR)ProcessId);
       return FALSE;
    }
 
    Entry = Process->ThreadListHead.Flink;
+   ObDereferenceObject(Process);
    if (Entry == &KdbCurrentProcess->ThreadListHead)
    {
-      KdbpPrint("No threads in process 0x%08x, cannot attach to process!\n", (UINT)ProcessId);
+      KdbpPrint("No threads in process 0x%p, cannot attach to process!\n", ProcessId);
       return FALSE;
    }
 
@@ -1124,8 +1176,8 @@ KdbpAttachToProcess(
 
 /*!\brief Calls the main loop ...
  */
-STATIC VOID
-KdbpCallMainLoop()
+static VOID
+KdbpCallMainLoop(VOID)
 {
    KdbpCliMainLoop(KdbEnteredOnSingleStep);
 }
@@ -1134,7 +1186,7 @@ KdbpCallMainLoop()
  *
  * Disables interrupts, releases display ownership, ...
  */
-STATIC VOID
+static VOID
 KdbpInternalEnter()
 {
    PETHREAD Thread;
@@ -1144,7 +1196,7 @@ KdbpInternalEnter()
    KbdDisableMouse();
    if (KdpDebugMode.Screen)
    {
-      HalReleaseDisplayOwnership();
+      InbvAcquireDisplayOwnership();
    }
 
    /* Call the interface's main loop on a different stack */
@@ -1154,12 +1206,12 @@ KdbpInternalEnter()
    SavedStackLimit = Thread->Tcb.StackLimit;
    SavedKernelStack = Thread->Tcb.KernelStack;
    Thread->Tcb.InitialStack = Thread->Tcb.StackBase = (char*)KdbStack + KDB_STACK_SIZE;
-   Thread->Tcb.StackLimit = (ULONG)KdbStack;
+   Thread->Tcb.StackLimit = (ULONG_PTR)KdbStack;
    Thread->Tcb.KernelStack = (char*)KdbStack + KDB_STACK_SIZE;
 
-   /*KdbpPrint("Switching to KDB stack 0x%08x-0x%08x\n", Thread->Tcb.StackLimit, Thread->Tcb.StackBase);*/
+   /*KdbpPrint("Switching to KDB stack 0x%08x-0x%08x (Current Stack is 0x%08x)\n", Thread->Tcb.StackLimit, Thread->Tcb.StackBase, Esp);*/
 
-   KdbpStackSwitchAndCall(Thread->Tcb.KernelStack, KdbpCallMainLoop);
+   KdbpStackSwitchAndCall(KdbStack + KDB_STACK_SIZE - sizeof(ULONG), KdbpCallMainLoop);
 
    Thread->Tcb.InitialStack = SavedInitialStack;
    Thread->Tcb.StackBase = SavedStackBase;
@@ -1168,13 +1220,62 @@ KdbpInternalEnter()
    KbdEnableMouse();
 }
 
+static ULONG
+KdbpGetExceptionNumberFromStatus(IN NTSTATUS ExceptionCode)
+{
+    ULONG Ret;
+
+    switch (ExceptionCode)
+    {
+        case STATUS_INTEGER_DIVIDE_BY_ZERO:
+            Ret = 0;
+            break;
+        case STATUS_SINGLE_STEP:
+            Ret = 1;
+            break;
+        case STATUS_BREAKPOINT:
+            Ret = 3;
+            break;
+        case STATUS_INTEGER_OVERFLOW:
+            Ret = 4;
+            break;
+        case STATUS_ARRAY_BOUNDS_EXCEEDED:
+            Ret = 5;
+            break;
+        case STATUS_ILLEGAL_INSTRUCTION:
+            Ret = 6;
+            break;
+        case STATUS_FLOAT_INVALID_OPERATION:
+            Ret = 7;
+            break;
+        case STATUS_STACK_OVERFLOW:
+            Ret = 12;
+            break;
+        case STATUS_ACCESS_VIOLATION:
+            Ret = 14;
+            break;
+        case STATUS_DATATYPE_MISALIGNMENT:
+            Ret = 17;
+            break;
+        case STATUS_FLOAT_MULTIPLE_TRAPS:
+            Ret = 18;
+            break;
+
+        default:
+            Ret = RTL_NUMBER_OF(KdbEnterConditions) - 1;
+            break;
+    }
+
+    return Ret;
+}
+
 /*!\brief KDB Exception filter
  *
  * Called by the exception dispatcher.
  *
  * \param ExceptionRecord  Unused.
  * \param PreviousMode     UserMode if the exception was raised from umode, otherwise KernelMode.
- * \param Context          Unused.
+ * \param Context          Context, IN/OUT parameter.
  * \param TrapFrame        Exception TrapFrame.
  * \param FirstChance      TRUE when called before exception frames were serached,
  *                         FALSE for the second call.
@@ -1185,31 +1286,34 @@ KD_CONTINUE_TYPE
 KdbEnterDebuggerException(
    IN PEXCEPTION_RECORD ExceptionRecord  OPTIONAL,
    IN KPROCESSOR_MODE PreviousMode,
-   IN PCONTEXT Context  OPTIONAL,
+   IN PCONTEXT Context,
    IN OUT PKTRAP_FRAME TrapFrame,
    IN BOOLEAN FirstChance)
 {
-   ULONG ExpNr = (ULONG)TrapFrame->DebugArgMark;
    KDB_ENTER_CONDITION EnterCondition;
    KD_CONTINUE_TYPE ContinueType = kdHandleException;
    PKDB_BREAKPOINT BreakPoint;
-   ULONG ul;
+   ULONG ExpNr;
    ULONGLONG ull;
    BOOLEAN Resume = FALSE;
    BOOLEAN EnterConditionMet = TRUE;
    ULONG OldEflags;
+   NTSTATUS ExceptionCode;
+
+   ExceptionCode = (ExceptionRecord != NULL ? ExceptionRecord->ExceptionCode : STATUS_BREAKPOINT);
 
    KdbCurrentProcess = PsGetCurrentProcess();
 
    /* Set continue type to kdContinue for single steps and breakpoints */
-   if (ExpNr == 1 || ExpNr == 3)
+   if (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT)
       ContinueType = kdContinue;
 
    /* Check if we should handle the exception. */
-   ul = min(ExpNr, RTL_NUMBER_OF(KdbEnterConditions) - 1);
-   EnterCondition = KdbEnterConditions[ul][FirstChance ? 0 : 1];
+   /* FIXME - won't get all exceptions here :( */
+   ExpNr = KdbpGetExceptionNumberFromStatus(ExceptionCode);
+   EnterCondition = KdbEnterConditions[ExpNr][FirstChance ? 0 : 1];
    if (EnterCondition == KdbDoNotEnter ||
-       (EnterCondition == KdbEnterFromUmode && PreviousMode != UserMode) ||
+       (EnterCondition == KdbEnterFromUmode && PreviousMode == KernelMode) ||
        (EnterCondition == KdbEnterFromKmode && PreviousMode != KernelMode))
    {
       EnterConditionMet = FALSE;
@@ -1219,27 +1323,21 @@ KdbEnterDebuggerException(
    KdbLastBreakPointNr = -1;
    KdbEnteredOnSingleStep = FALSE;
 
-   if (FirstChance && (ExpNr == 1 || ExpNr == 3) &&
-       (KdbLastBreakPointNr = KdbpIsBreakPointOurs(ExpNr, TrapFrame)) >= 0)
+   if (FirstChance && (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT) &&
+       (KdbLastBreakPointNr = KdbpIsBreakPointOurs(ExceptionCode, TrapFrame)) >= 0)
    {
       BreakPoint = KdbBreakPoints + KdbLastBreakPointNr;
 
-      if (ExpNr == 3)
+      if (ExceptionCode == STATUS_BREAKPOINT)
       {
-         /*
-          * The breakpoint will point to the next instruction by default so
-          * point it back to the start of original instruction.
-          */
-         TrapFrame->Eip--;
-
          /*
           * ... and restore the original instruction.
           */
          if (!NT_SUCCESS(KdbpOverwriteInstruction(KdbCurrentProcess, BreakPoint->Address,
                                                   BreakPoint->Data.SavedInstruction, NULL)))
          {
-            DbgPrint("Couldn't restore original instruction after INT3! Cannot continue execution.\n");
-            KEBUGCHECK(0);
+            KdbpPrint("Couldn't restore original instruction after INT3! Cannot continue execution.\n");
+            KeBugCheck(0); // FIXME: Proper bugcode!
          }
       }
 
@@ -1257,7 +1355,7 @@ KdbEnterDebuggerException(
       else if (BreakPoint->Type == KdbBreakPointTemporary &&
                BreakPoint->Process == KdbCurrentProcess)
       {
-         ASSERT((TrapFrame->Eflags & X86_EFLAGS_TF) == 0);
+         ASSERT((TrapFrame->EFlags & EFLAGS_TF) == 0);
 
          /*
           * Delete the temporary breakpoint which was used to step over or into the instruction.
@@ -1269,7 +1367,7 @@ KdbEnterDebuggerException(
             if ((KdbSingleStepOver && !KdbpStepOverInstruction(TrapFrame->Eip)) ||
                 (!KdbSingleStepOver && !KdbpStepIntoInstruction(TrapFrame->Eip)))
             {
-               TrapFrame->Eflags |= X86_EFLAGS_TF;
+               Context->EFlags |= EFLAGS_TF;
             }
             goto continue_execution; /* return */
          }
@@ -1284,8 +1382,8 @@ KdbEnterDebuggerException(
       else if (BreakPoint->Type == KdbBreakPointSoftware ||
                BreakPoint->Type == KdbBreakPointTemporary)
       {
-         ASSERT(ExpNr == 3);
-         TrapFrame->Eflags |= X86_EFLAGS_TF;
+         ASSERT(ExceptionCode == STATUS_BREAKPOINT);
+         Context->EFlags |= EFLAGS_TF;
          KdbBreakPointToReenable = BreakPoint;
       }
 
@@ -1318,12 +1416,12 @@ KdbEnterDebuggerException(
 
       if (BreakPoint->Type == KdbBreakPointSoftware)
       {
-         DbgPrint("Entered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n",
-                  KdbLastBreakPointNr, TrapFrame->Cs & 0xffff, TrapFrame->Eip);
+         KdbpPrint("Entered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n",
+                  KdbLastBreakPointNr, TrapFrame->SegCs & 0xffff, TrapFrame->Eip);
       }
       else if (BreakPoint->Type == KdbBreakPointHardware)
       {
-         DbgPrint("Entered debugger on breakpoint #%d: %s 0x%08x\n",
+         KdbpPrint("Entered debugger on breakpoint #%d: %s 0x%08x\n",
                   KdbLastBreakPointNr,
                   (BreakPoint->Data.Hw.AccessType == KdbAccessRead) ? "READ" :
                   ((BreakPoint->Data.Hw.AccessType == KdbAccessWrite) ? "WRITE" :
@@ -1334,7 +1432,7 @@ KdbEnterDebuggerException(
 
       }
    }
-   else if (ExpNr == 1)
+   else if (ExceptionCode == STATUS_SINGLE_STEP)
    {
       /* Silently ignore a debugger initiated single step. */
       if ((TrapFrame->Dr6 & 0xf) == 0 && KdbBreakPointToReenable != NULL)
@@ -1352,47 +1450,49 @@ KdbEnterDebuggerException(
          if (!NT_SUCCESS(KdbpOverwriteInstruction(KdbCurrentProcess, BreakPoint->Address, 0xCC,
                                                   &BreakPoint->Data.SavedInstruction)))
          {
-            DbgPrint("Warning: Couldn't reenable breakpoint %d\n",
+            KdbpPrint("Warning: Couldn't reenable breakpoint %d\n",
                      BreakPoint - KdbBreakPoints);
          }
 
          /* Unset TF if we are no longer single stepping. */
          if (KdbNumSingleSteps == 0)
-            TrapFrame->Eflags &= ~X86_EFLAGS_TF;
+            Context->EFlags &= ~EFLAGS_TF;
          goto continue_execution; /* return */
       }
 
       /* Check if we expect a single step */
       if ((TrapFrame->Dr6 & 0xf) == 0 && KdbNumSingleSteps > 0)
       {
-         /*ASSERT((TrapFrame->Eflags & X86_EFLAGS_TF) != 0);*/
+         /*ASSERT((Context->Eflags & EFLAGS_TF) != 0);*/
          if (--KdbNumSingleSteps > 0)
          {
             if ((KdbSingleStepOver && KdbpStepOverInstruction(TrapFrame->Eip)) ||
                 (!KdbSingleStepOver && KdbpStepIntoInstruction(TrapFrame->Eip)))
             {
-               TrapFrame->Eflags &= ~X86_EFLAGS_TF;
+               Context->EFlags &= ~EFLAGS_TF;
             }
             else
             {
-               TrapFrame->Eflags |= X86_EFLAGS_TF;
+               Context->EFlags |= EFLAGS_TF;
             }
-            goto continue_execution; /* return */
+                       goto continue_execution; /* return */
          }
-
-         TrapFrame->Eflags &= ~X86_EFLAGS_TF;
-         KdbEnteredOnSingleStep = TRUE;
+                else 
+                {
+                        Context->EFlags &= ~EFLAGS_TF;
+                        KdbEnteredOnSingleStep = TRUE;
+                }
       }
       else
       {
          if (!EnterConditionMet)
          {
-            return ContinueType;
+            return kdHandleException;
          }
-         DbgPrint("Entered debugger on unexpected debug trap!\n");
+         KdbpPrint("Entered debugger on unexpected debug trap!\n");
       }
    }
-   else if (ExpNr == 3)
+   else if (ExceptionCode == STATUS_BREAKPOINT)
    {
       if (KdbInitFileBuffer != NULL)
       {
@@ -1401,15 +1501,15 @@ KdbEnterDebuggerException(
       }
       if (!EnterConditionMet)
       {
-         return ContinueType;
+         return kdHandleException;
       }
 
-      DbgPrint("Entered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
-               TrapFrame->Cs & 0xffff, TrapFrame->Eip - 1);
+      KdbpPrint("Entered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
+               TrapFrame->SegCs & 0xffff, TrapFrame->Eip - 1);
    }
    else
    {
-      CONST PCHAR ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
+      const CHAR *ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
                                     (ExceptionNrToString[ExpNr]) :
                                     ("Unknown/User defined exception");
 
@@ -1418,23 +1518,33 @@ KdbEnterDebuggerException(
          return ContinueType;
       }
 
-      DbgPrint("Entered debugger on %s-chance exception number %d (%s)\n",
-               FirstChance ? "first" : "last", ExpNr, ExceptionString);
-      if (ExpNr == 14)
+      KdbpPrint("Entered debugger on %s-chance exception (Exception Code: 0x%x) (%s)\n",
+               FirstChance ? "first" : "last", ExceptionCode, ExceptionString);
+      if (ExceptionCode == STATUS_ACCESS_VIOLATION &&
+          ExceptionRecord != NULL && ExceptionRecord->NumberParameters != 0)
       {
          /* FIXME: Add noexec memory stuff */
-         ULONG Cr2, Err;
-         asm volatile("movl %%cr2, %0" : "=r"(Cr2));
-         Err = TrapFrame->ErrorCode;
-         DbgPrint("Memory at 0x%x could not be %s: ", Cr2, (Err & (1 << 1)) ? "written" : "read");
+         ULONG_PTR TrapCr2;
+         ULONG Err;
+#ifdef __GNUC__
+         asm volatile("movl %%cr2, %0" : "=r"(TrapCr2));
+#elif _MSC_VER
+         __asm mov eax, cr2;
+         __asm mov TrapCr2, eax;
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+         Err = TrapFrame->ErrCode;
+         KdbpPrint("Memory at 0x%p could not be %s: ", TrapCr2, (Err & (1 << 1)) ? "written" : "read");
          if ((Err & (1 << 0)) == 0)
-            DbgPrint("Page not present.\n");
+            KdbpPrint("Page not present.\n");
          else
          {
             if ((Err & (1 << 3)) != 0)
-               DbgPrint("Reserved bits in page directory set.\n");
+               KdbpPrint("Reserved bits in page directory set.\n");
             else
-               DbgPrint("Page protection violation.\n");
+               KdbpPrint("Page protection violation.\n");
          }
       }
    }
@@ -1452,7 +1562,7 @@ KdbEnterDebuggerException(
 
    /* Enter critical section */
    Ke386SaveFlags(OldEflags);
-   Ke386DisableInterrupts();
+   _disable();
 
    /* Exception inside the debugger? Game over. */
    if (InterlockedIncrement(&KdbEntryCount) > 1)
@@ -1470,20 +1580,17 @@ KdbEnterDebuggerException(
       if ((KdbSingleStepOver && KdbpStepOverInstruction(KdbCurrentTrapFrame->Tf.Eip)) ||
           (!KdbSingleStepOver && KdbpStepIntoInstruction(KdbCurrentTrapFrame->Tf.Eip)))
       {
-         ASSERT((KdbCurrentTrapFrame->Tf.Eflags & X86_EFLAGS_TF) == 0);
-         /*KdbCurrentTrapFrame->Tf.Eflags &= ~X86_EFLAGS_TF;*/
+         ASSERT((KdbCurrentTrapFrame->Tf.EFlags & EFLAGS_TF) == 0);
+         /*KdbCurrentTrapFrame->Tf.EFlags &= ~EFLAGS_TF;*/
       }
       else
       {
-         KdbCurrentTrapFrame->Tf.Eflags |= X86_EFLAGS_TF;
+         Context->EFlags |= EFLAGS_TF;
       }
    }
 
-   /* Save the current thread's trapframe */
-   if (KdbCurrentTrapFrame == &KdbThreadTrapFrame)
-   {
-      KdbpKdbTrapFrameToTrapFrame(KdbCurrentTrapFrame, KdbCurrentThread->Tcb.TrapFrame);
-   }
+   /* We can't update the current thread's trapframe 'cause it might not
+      have one */
 
    /* Detach from attached process */
    if (KdbCurrentProcess != KdbOriginalProcess)
@@ -1500,19 +1607,29 @@ KdbEnterDebuggerException(
    /* Leave critical section */
    Ke386RestoreFlags(OldEflags);
 
+   /* Check if user requested a bugcheck */
+   if (KdbpBugCheckRequested)
+   {
+       /* Clear the flag and bugcheck the system */
+       KdbpBugCheckRequested = FALSE;
+       KeBugCheck(MANUALLY_INITIATED_CRASH);
+   }
+
 continue_execution:
    /* Clear debug status */
-   if (ExpNr == 1 || ExpNr == 3) /* FIXME: Why clear DR6 on INT3? */
+   if (ExceptionCode == STATUS_BREAKPOINT) /* FIXME: Why clear DR6 on INT3? */
    {
       /* Set the RF flag so we don't trigger the same breakpoint again. */
       if (Resume)
       {
-         TrapFrame->Eflags |= X86_EFLAGS_RF;
+         TrapFrame->EFlags |= EFLAGS_RF;
       }
 
       /* Clear dr6 status flags. */
       TrapFrame->Dr6 &= ~0x0000e00f;
 
+      /* Skip the current instruction */
+      Context->Eip++;
    }
 
    return ContinueType;
@@ -1527,12 +1644,12 @@ KdbDeleteProcessHook(IN PEPROCESS Process)
 }
 
 VOID
-STDCALL
+NTAPI
 KdbpGetCommandLineSettings(PCHAR p1)
 {
     PCHAR p2;
 
-    while (p1 && (p2 = strchr(p1, '/')))
+    while (p1 && (p2 = strchr(p1, ' ')))
     {
         p2++;
 
@@ -1551,3 +1668,54 @@ KdbpGetCommandLineSettings(PCHAR p1)
         p1 = p2;
     }
 }
+
+NTSTATUS
+KdbpSafeReadMemory(OUT PVOID Dest,
+                   IN PVOID Src,
+                   IN ULONG Bytes)
+{
+    BOOLEAN Result = TRUE;
+
+    switch (Bytes)
+    {
+    case 1:
+    case 2:
+    case 4:
+    case 8:
+        Result = KdpSafeReadMemory((ULONG_PTR)Src, Bytes, Dest);
+        break;
+    default:
+    {
+        ULONG_PTR Start, End, Write;
+        for (Start = (ULONG_PTR)Src, 
+                 End = Start + Bytes, 
+                 Write = (ULONG_PTR)Dest; 
+             Result && (Start < End); 
+             Start++, Write++)
+            if (!KdpSafeReadMemory(Start, 1, (PVOID)Write))
+                Result = FALSE;
+        break;
+    }
+    }
+
+    return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
+}
+
+NTSTATUS
+KdbpSafeWriteMemory(OUT PVOID Dest,
+                    IN PVOID Src,
+                    IN ULONG Bytes)
+{
+    BOOLEAN Result = TRUE;
+    ULONG_PTR Start, End, Write;
+
+    for (Start = (ULONG_PTR)Src, 
+             End = Start + Bytes, 
+             Write = (ULONG_PTR)Dest; 
+         Result && (Start < End); 
+         Start++, Write++)
+        if (!KdpSafeWriteMemory(Write, 1, *((PCHAR)Start)))
+            Result = FALSE;
+
+    return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
+}