#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
/* TYPES *********************************************************************/
/* 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 */
};
/* Exception descriptions */
-STATIC CONST CHAR *ExceptionNrToString[] =
+static const CHAR *ExceptionNrToString[] =
{
"Divide Error",
"Debug Trap",
/* FUNCTIONS *****************************************************************/
-STATIC VOID
+static VOID
KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFrame)
{
ULONG TrapCr0, TrapCr2, TrapCr3, TrapCr4;
/* 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*/
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
}
-STATIC VOID
+static VOID
KdbpKdbTrapFrameFromKernelStack(PVOID KernelStack,
PKDB_KTRAP_FRAME KdbTrapFrame)
{
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.SegDs = KGDT_R0_DATA;
KdbTrapFrame->Tf.SegEs = KGDT_R0_DATA;
KdbTrapFrame->Tf.SegGs = KGDT_R0_DATA;
+#endif
/* FIXME: what about the other registers??? */
}
*
* \returns NTSTATUS
*/
-STATIC NTSTATUS
+static NTSTATUS
KdbpOverwriteInstruction(
IN PEPROCESS Process,
IN ULONG_PTR Address,
}
/* 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%p\n", (ULONG_PTR)Idtr.Base + (IntVect * 8));*/
return FALSE;
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;
KdbpEnableBreakPoint(i, NULL);
/* Return the breakpoint number */
- if (BreakPointNumber != NULL)
- *BreakPointNumber = i;
+ if (BreakPointNr != NULL)
+ *BreakPointNr = i;
return STATUS_SUCCESS;
}
*
* \returns Breakpoint number, -1 on error.
*/
-STATIC LONG
+static LONG
KdbpIsBreakPointOurs(
IN NTSTATUS ExceptionCode,
IN PKTRAP_FRAME TrapFrame)
/* Get a pointer to the thread */
if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &Thread)))
{
- KdbpPrint("Invalid thread id: 0x%08x\n", (ULONG)ThreadId);
+ KdbpPrint("Invalid thread id: 0x%08x\n", (ULONG_PTR)ThreadId);
return FALSE;
}
Process = Thread->ThreadsProcess;
if (KeIsExecutingDpc() && Process != KdbCurrentProcess)
{
KdbpPrint("Cannot attach to thread within another process while executing a DPC.\n");
+ ObDereferenceObject(Thread);
return FALSE;
}
KdbCurrentProcess = Process;
}
+ ObDereferenceObject(Thread);
return TRUE;
}
/* Get a pointer to the process */
if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process)))
{
- KdbpPrint("Invalid process id: 0x%08x\n", (ULONG)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", (ULONG)ProcessId);
+ KdbpPrint("No threads in process 0x%p, cannot attach to process!\n", ProcessId);
return FALSE;
}
/*!\brief Calls the main loop ...
*/
-STATIC VOID
-KdbpCallMainLoop()
+static VOID
+KdbpCallMainLoop(VOID)
{
KdbpCliMainLoop(KdbEnteredOnSingleStep);
}
*
* Disables interrupts, releases display ownership, ...
*/
-STATIC VOID
+static VOID
KdbpInternalEnter()
{
PETHREAD Thread;
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;
KbdEnableMouse();
}
-STATIC ULONG
+static ULONG
KdbpGetExceptionNumberFromStatus(IN NTSTATUS ExceptionCode)
{
ULONG Ret;
*
* \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.
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)
{
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!
}
}
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.
if ((KdbSingleStepOver && !KdbpStepOverInstruction(TrapFrame->Eip)) ||
(!KdbSingleStepOver && !KdbpStepIntoInstruction(TrapFrame->Eip)))
{
- TrapFrame->EFlags |= X86_EFLAGS_TF;
+ Context->EFlags |= EFLAGS_TF;
}
goto continue_execution; /* return */
}
BreakPoint->Type == KdbBreakPointTemporary)
{
ASSERT(ExceptionCode == STATUS_BREAKPOINT);
- TrapFrame->EFlags |= X86_EFLAGS_TF;
+ Context->EFlags |= EFLAGS_TF;
KdbBreakPointToReenable = BreakPoint;
}
if (BreakPoint->Type == KdbBreakPointSoftware)
{
- DbgPrint("Entered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n",
+ 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" :
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 (ExceptionCode == STATUS_BREAKPOINT)
}
if (!EnterConditionMet)
{
- return ContinueType;
+ return kdHandleException;
}
- DbgPrint("Entered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
+ KdbpPrint("Entered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
TrapFrame->SegCs & 0xffff, TrapFrame->Eip - 1);
}
else
{
- CONST CHAR *ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
+ const CHAR *ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
(ExceptionNrToString[ExpNr]) :
("Unknown/User defined exception");
return ContinueType;
}
- DbgPrint("Entered debugger on %s-chance exception (Exception Code: 0x%x) (%s)\n",
+ 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)
#endif
Err = TrapFrame->ErrCode;
- DbgPrint("Memory at 0x%p could not be %s: ", TrapCr2, (Err & (1 << 1)) ? "written" : "read");
+ 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");
}
}
}
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;
}
}
/* 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 (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT) /* 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;
}
VOID
-STDCALL
+NTAPI
KdbpGetCommandLineSettings(PCHAR p1)
{
PCHAR p2;
- while (p1 && (p2 = strchr(p1, '/')))
+ while (p1 && (p2 = strchr(p1, ' ')))
{
p2++;
IN PVOID Src,
IN ULONG Bytes)
{
- NTSTATUS Status = STATUS_SUCCESS;
+ BOOLEAN Result = TRUE;
- _SEH_TRY
- {
- RtlCopyMemory(Dest,
- Src,
- Bytes);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
+ 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 Status;
+ return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
}
NTSTATUS
IN PVOID Src,
IN ULONG Bytes)
{
- NTSTATUS Status = STATUS_SUCCESS;
-
- _SEH_TRY
- {
- RtlCopyMemory(Dest,
- Src,
- Bytes);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- return Status;
+ 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;
}