- Implement Bus and I/O space read and write support.
- Implement support for AUTOENABLE, DISABLE and NOUMEX subparameters to /debug. Add the missing string scan and set and respect the related globals properly. Add support for disabling the debugger and suspending breakpoints.
- Add and implement KdIsThisAKdTrap to determine if the kernel debugger can't ignore a particular trap -- returns true for software breakpoints and debug service calls (DbgPrint for example). Called from KiDispatchException to determine whether to override NOUMEX (otherwise, DbgPrint and friends will kill user mode applications). Stub this for KDBG as it implements its own scheme for ignoring user mode.
- KiDispatchException: Clean up some goto and support NOUMEX. Also don't check if KiDebugRoutine is NULL -- it will never be.
- KdEnableDebuggerWithLock should initialize the debugger even if KdDisableCount is 0 (but only if called internally) as this means that the debugger was never initialized in the first place. Required for AUTOENABLE and for enabling the debugger during a bugcheck. Add the globals to kdbg too but don't set or respect them there as kdbg does not support it.
- Enable KdEnableDebugger and implement KdDisableDebugger for KD as KdDisableDebuggerWithLock is now implemented.
- Only build kdmemsup.c if KDBG is defined.
svn path=/trunk/; revision=43530
// NTSTATUS, Bugcheck Codes and Debug Codes
//
#ifdef __ASM__
+#define STATUS_SUCCESS 0x00000000
#define STATUS_ACCESS_VIOLATION 0xC0000005
#define STATUS_IN_PAGE_ERROR 0xC0000006
#define STATUS_GUARD_PAGE_VIOLATION 0x80000001
extern BOOLEAN _KdDebuggerNotPresent;
extern BOOLEAN KdBreakAfterSymbolLoad;
extern BOOLEAN KdPitchDebugger;
+extern BOOLEAN KdIgnoreUmExceptions;
BOOLEAN
NTAPI
PKTRAP_FRAME TrapFrame
);
+BOOLEAN
+NTAPI
+KdIsThisAKdTrap(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context,
+ IN KPROCESSOR_MODE PreviousMode
+);
+
/* INIT ROUTINES *************************************************************/
BOOLEAN
VOID
);
+//
+// Determines if the kernel debugger must handle a particular trap
+//
+BOOLEAN
+NTAPI
+KdIsThisAKdTrap(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context,
+ IN KPROCESSOR_MODE PreviousMode
+);
+
//
// Multi-Processor Switch Support
//
);
//
-// Debugger Enable, Enter and Exit
+// Debugger Enter, Exit, Enable and Disable
//
BOOLEAN
NTAPI
IN BOOLEAN NeedLock
);
+NTSTATUS
+NTAPI
+KdDisableDebuggerWithLock(
+ IN BOOLEAN NeedLock
+);
+
//
// Debug Event Handlers
//
//
// Breakpoint Support
//
-VOID
+ULONG
NTAPI
-KdpRestoreAllBreakpoints(
- VOID
+KdpAddBreakpoint(
+ IN PVOID Address
);
BOOLEAN
IN PVOID Limit
);
-ULONG
+VOID
NTAPI
-KdpAddBreakpoint(
- IN PVOID Address
+KdpSuspendBreakPoint(
+ IN ULONG BpEntry
+);
+
+VOID
+NTAPI
+KdpRestoreAllBreakpoints(
+ VOID
+);
+
+VOID
+NTAPI
+KdpSuspendAllBreakPoints(
+ VOID
);
//
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
- IN PVOID Buffer,
IN ULONG Offset,
+ IN PVOID Buffer,
IN ULONG Length,
OUT PULONG ActualLength
);
IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
- IN PVOID Buffer,
IN ULONG Offset,
+ IN PVOID Buffer,
IN ULONG Length,
OUT PULONG ActualLength
);
extern BOOLEAN _KdDebuggerNotPresent;
extern BOOLEAN _KdDebuggerEnabled;
extern BOOLEAN KdAutoEnableOnEvent;
+extern BOOLEAN KdBlockEnable;
+extern BOOLEAN KdIgnoreUmExceptions;
extern BOOLEAN KdPreviouslyEnabled;
extern BOOLEAN KdpDebuggerStructuresInitialized;
extern BOOLEAN KdEnteredDebugger;
BOOLEAN KdDebuggerNotPresent = TRUE;
BOOLEAN KiEnableTimerWatchdog = FALSE;
BOOLEAN KdBreakAfterSymbolLoad = FALSE;
-BOOLEAN KdpBreakPending;
+BOOLEAN KdpBreakPending = FALSE;
BOOLEAN KdPitchDebugger = TRUE;
+BOOLEAN KdIgnoreUmExceptions = FALSE;
VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads);
typedef struct
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 *********************************************************/
/*
KdpSysReadBusData(IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
- IN PVOID Buffer,
IN ULONG Offset,
+ IN PVOID Buffer,
IN ULONG Length,
OUT PULONG ActualLength)
{
KdpSysWriteBusData(IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
- IN PVOID Buffer,
IN ULONG Offset,
+ IN PVOID Buffer,
IN ULONG Length,
OUT PULONG ActualLength)
{
KdpSysReadBusData(IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
- IN PVOID Buffer,
IN ULONG Offset,
+ IN PVOID Buffer,
IN ULONG Length,
OUT PULONG ActualLength)
{
KdpSysWriteBusData(IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
- IN PVOID Buffer,
IN ULONG Offset,
+ IN PVOID Buffer,
IN ULONG Length,
OUT PULONG ActualLength)
{
#define NDEBUG
#include <debug.h>
-#undef UNIMPLEMENTED
-#define UNIMPLEMENTED KdpDprintf("%s is unimplemented\n", __FUNCTION__)
-
/* FUNCTIONS *****************************************************************/
VOID
KdpSysReadBusData(IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
- IN PVOID Buffer,
IN ULONG Offset,
+ IN PVOID Buffer,
IN ULONG Length,
OUT PULONG ActualLength)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_UNSUCCESSFUL;
+ /* Just forward to HAL */
+ *ActualLength = HalGetBusDataByOffset(BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length);
+
+ /* Return status */
+ return (*ActualLength != 0) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
NTSTATUS
KdpSysWriteBusData(IN ULONG BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
- IN PVOID Buffer,
IN ULONG Offset,
+ IN PVOID Buffer,
IN ULONG Length,
OUT PULONG ActualLength)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_UNSUCCESSFUL;
+ /* Just forward to HAL */
+ *ActualLength = HalSetBusDataByOffset(BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length);
+
+ /* Return status */
+ return (*ActualLength != 0) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
NTSTATUS
ULONG RealLength;
/* Make sure that this is a valid request */
- if (((ULONG)BaseAddress < sizeof(KPROCESSOR_STATE)) &&
+ if ((BaseAddress < sizeof(KPROCESSOR_STATE)) &&
(Processor < KeNumberProcessors))
{
/* Get the actual length */
PVOID ControlStart;
/* Make sure that this is a valid request */
- if ((((ULONG)BaseAddress + Length) <= sizeof(KPROCESSOR_STATE)) &&
+ if (((BaseAddress + Length) <= sizeof(KPROCESSOR_STATE)) &&
(Processor < KeNumberProcessors))
{
/* Set the proper address */
IN ULONG DataSize,
OUT PULONG ActualDataSize)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_UNSUCCESSFUL;
+ NTSTATUS Status;
+
+ /* Verify parameters */
+ if ((InterfaceType != Isa) ||
+ (BusNumber != 0) ||
+ (AddressSpace != 1))
+ {
+ /* Fail, we don't support this */
+ *ActualDataSize = 0;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Check the size */
+ switch (DataSize)
+ {
+ case sizeof(UCHAR):
+
+ /* Read 1 byte */
+ *(PUCHAR)DataValue =
+ READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)IoAddress);
+ *ActualDataSize = sizeof(UCHAR);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case sizeof(USHORT):
+
+ /* Make sure the address is aligned */
+ if ((IoAddress & (sizeof(USHORT) - 1)) != 0)
+ {
+ /* It isn't, bail out */
+ *ActualDataSize = 0;
+ Status = STATUS_DATATYPE_MISALIGNMENT;
+ break;
+ }
+
+ /* Read 2 bytes */
+ *(PUSHORT)DataValue =
+ READ_PORT_USHORT((PUSHORT)(ULONG_PTR)IoAddress);
+ *ActualDataSize = sizeof(USHORT);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case sizeof(ULONG):
+
+ /* Make sure the address is aligned */
+ if ((IoAddress & (sizeof(ULONG) - 1)) != 0)
+ {
+ /* It isn't, bail out */
+ *ActualDataSize = 0;
+ Status = STATUS_DATATYPE_MISALIGNMENT;
+ break;
+ }
+
+ /* Read 4 bytes */
+ *(PULONG)DataValue =
+ READ_PORT_ULONG((PULONG)(ULONG_PTR)IoAddress);
+ *ActualDataSize = sizeof(ULONG);
+ Status = STATUS_SUCCESS;
+ break;
+
+ default:
+
+ /* Invalid size, fail */
+ *ActualDataSize = 0;
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ /* Return status */
+ return Status;
}
NTSTATUS
IN ULONG DataSize,
OUT PULONG ActualDataSize)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_UNSUCCESSFUL;
+ NTSTATUS Status;
+
+ /* Verify parameters */
+ if ((InterfaceType != Isa) ||
+ (BusNumber != 0) ||
+ (AddressSpace != 1))
+ {
+ /* Fail, we don't support this */
+ *ActualDataSize = 0;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Check the size */
+ switch (DataSize)
+ {
+ case sizeof(UCHAR):
+
+ /* Write 1 byte */
+ WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)IoAddress,
+ *(PUCHAR)DataValue);
+ *ActualDataSize = sizeof(UCHAR);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case sizeof(USHORT):
+
+ /* Make sure the address is aligned */
+ if ((IoAddress & (sizeof(USHORT) - 1)) != 0)
+ {
+ /* It isn't, bail out */
+ *ActualDataSize = 0;
+ Status = STATUS_DATATYPE_MISALIGNMENT;
+ break;
+ }
+
+ /* Write 2 bytes */
+ WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)IoAddress,
+ *(PUSHORT)DataValue);
+ *ActualDataSize = sizeof(USHORT);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case sizeof(ULONG):
+
+ /* Make sure the address is aligned */
+ if ((IoAddress & (sizeof(ULONG) - 1)) != 0)
+ {
+ /* It isn't, bail out */
+ *ActualDataSize = 0;
+ Status = STATUS_DATATYPE_MISALIGNMENT;
+ break;
+ }
+
+ /* Write 4 bytes */
+ WRITE_PORT_ULONG((PULONG)(ULONG_PTR)IoAddress,
+ *(PULONG)DataValue);
+ *ActualDataSize = sizeof(ULONG);
+ Status = STATUS_SUCCESS;
+ break;
+
+ default:
+
+ /* Invalid size, fail */
+ *ActualDataSize = 0;
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ /* Return status */
+ return Status;
}
NTSTATUS
NTAPI
KdpSysCheckLowMemory(IN ULONG Flags)
{
- UNIMPLEMENTED;
- while (TRUE);
+ /* Stubbed as we don't support PAE */
return STATUS_UNSUCCESSFUL;
}
else
{
/* SMP not yet handled */
- KdpDprintf("SMP UNHANDLED\n");
+ KdpDprintf("KdpGetContext: SMP UNHANDLED\n");
ControlStart = NULL;
while (TRUE);
}
else
{
/* SMP not yet handled */
- KdpDprintf("SMP UNHANDLED\n");
+ KdpDprintf("KdpSetContext: SMP UNHANDLED\n");
ControlStart = NULL;
while (TRUE);
}
State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType,
GetBusData->BusNumber,
GetBusData->SlotNumber,
- Data->Buffer,
GetBusData->Offset,
+ Data->Buffer,
Length,
&Length);
State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType,
SetBusData->BusNumber,
SetBusData->SlotNumber,
- Data->Buffer,
SetBusData->Offset,
+ Data->Buffer,
SetBusData->Length,
&Length);
return KeQueryPerformanceCounter(NULL);
}
+NTSTATUS
+NTAPI
+KdpAllowDisable(VOID)
+{
+ /* Check if we are on MP */
+ if (KeNumberProcessors > 1)
+ {
+ /* TODO */
+ KdpDprintf("KdpAllowDisable: SMP UNHANDLED\n");
+ while (TRUE);
+ }
+
+ /* Allow disable */
+ return STATUS_SUCCESS;
+}
+
BOOLEAN
NTAPI
KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
OldIrql = PASSIVE_LEVEL;
#endif
+ /* Check if enabling the debugger is blocked */
+ if (KdBlockEnable)
+ {
+ /* It is, fail the enable */
+ return STATUS_ACCESS_DENIED;
+ }
+
/* Check if we need to acquire the lock */
if (NeedLock)
{
/* Do the unlock */
KeLowerIrql(OldIrql);
KdpPortUnlock();
- }
- /* Fail: We're already enabled */
- return STATUS_INVALID_PARAMETER;
+ /* Fail: We're already enabled */
+ return STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ /*
+ * This can only happen if we are called from a bugcheck
+ * and were never initialized, so initialize the debugger now.
+ */
+ KdInitSystem(0, NULL);
+
+ /* Return success since we initialized */
+ return STATUS_SUCCESS;
+ }
}
/* Decrease the disable count */
return STATUS_SUCCESS;
}
+NTSTATUS
+NTAPI
+KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)
+{
+ KIRQL OldIrql;
+ NTSTATUS Status;
+
+#if defined(__GNUC__)
+ /* Make gcc happy */
+ OldIrql = PASSIVE_LEVEL;
+#endif
+
+ /*
+ * If enabling the debugger is blocked
+ * then there is nothing to disable (duh)
+ */
+ if (KdBlockEnable)
+ {
+ /* Fail */
+ return STATUS_ACCESS_DENIED;
+ }
+
+ /* Check if we need to acquire the lock */
+ if (NeedLock)
+ {
+ /* Lock the port */
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ KdpPortLock();
+ }
+
+ /* Check if we're not disabled */
+ if (!KdDisableCount)
+ {
+ /* Check if the debugger was never actually initialized */
+ if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
+ {
+ /* It wasn't, so don't re-enable it later */
+ KdPreviouslyEnabled = FALSE;
+ }
+ else
+ {
+ /* It was, so we will re-enable it later */
+ KdPreviouslyEnabled = TRUE;
+ }
+
+ /* Check if we were called from the exported API and are enabled */
+ if ((NeedLock) && (KdPreviouslyEnabled))
+ {
+ /* Check if it is safe to disable the debugger */
+ Status = KdpAllowDisable();
+ if (!NT_SUCCESS(Status))
+ {
+ /* Release the lock and fail */
+ KeLowerIrql(OldIrql);
+ KdpPortUnlock();
+ return Status;
+ }
+ }
+
+ /* Only disable the debugger if it is enabled */
+ if (KdDebuggerEnabled)
+ {
+ /*
+ * Disable the debugger; suspend breakpoints
+ * and reset the debug stub
+ */
+ KdpSuspendAllBreakPoints();
+ KiDebugRoutine = KdpStub;
+
+ /* We are disabled now */
+ KdDebuggerEnabled = FALSE;
+#undef KdDebuggerEnabled
+ SharedUserData->KdDebuggerEnabled = FALSE;
+#define KdDebuggerEnabled _KdDebuggerEnabled
+ }
+ }
+
+ /* Increment the disable count */
+ KdDisableCount++;
+
+ /* Check if we had locked the port before */
+ if (NeedLock)
+ {
+ /* Yes, now unlock it */
+ KeLowerIrql(OldIrql);
+ KdpPortUnlock();
+ }
+
+ /* We're done */
+ return STATUS_SUCCESS;
+}
+
/* PUBLIC FUNCTIONS **********************************************************/
/*
KdEnableDebugger(VOID)
{
/* Use the internal routine */
- KdpDprintf("KdEnableDebugger called\n");
- while (TRUE);
return KdEnableDebuggerWithLock(TRUE);
}
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+KdDisableDebugger(VOID)
+{
+ /* Use the internal routine */
+ return KdDisableDebuggerWithLock(TRUE);
+}
+
/*
* @unimplemented
*/
return STATUS_SUCCESS;
}
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-KdDisableDebugger(VOID)
-{
- /* HACK */
- return STATUS_SUCCESS;
-}
-
/*
* @unimplemented
*/
/* HACK */
return STATUS_SUCCESS;
}
-
BreakpointsSuspended = FALSE;
/* Loop the breakpoints */
- for (BpIndex = 0; BpIndex < KD_BREAKPOINT_MAX; BpIndex++ )
+ for (BpIndex = 0; BpIndex < KD_BREAKPOINT_MAX; BpIndex++)
{
/* Check if they are valid, suspended breakpoints */
if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) &&
}
}
}
+
+VOID
+NTAPI
+KdpSuspendBreakPoint(IN ULONG BpEntry)
+{
+ ULONG BpIndex = BpEntry - 1;
+
+ /* Check if this is a valid, unsuspended breakpoint */
+ if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) &&
+ !(KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended))
+ {
+ /* Suspend it */
+ KdpBreakpointTable[BpIndex].Flags |= KdpBreakpointSuspended;
+ KdpLowWriteContent(BpIndex);
+ }
+}
+
+VOID
+NTAPI
+KdpSuspendAllBreakPoints(VOID)
+{
+ ULONG BpEntry;
+
+ /* Breakpoints are suspended */
+ BreakpointsSuspended = TRUE;
+
+ /* Loop every breakpoint */
+ for (BpEntry = 1; BpEntry <= KD_BREAKPOINT_MAX; BpEntry++)
+ {
+ /* Suspend it */
+ KdpSuspendBreakPoint(BpEntry);
+ }
+}
BOOLEAN _KdDebuggerNotPresent;
BOOLEAN _KdDebuggerEnabled;
BOOLEAN KdAutoEnableOnEvent;
+BOOLEAN KdBlockEnable;
+BOOLEAN KdIgnoreUmExceptions;
BOOLEAN KdPreviouslyEnabled;
BOOLEAN KdpDebuggerStructuresInitialized;
BOOLEAN KdEnteredDebugger;
BOOLEAN BreakpointsSuspended;
ULONG KdpNumInternalBreakpoints;
+//
+// Symbol Data
+//
ULONG KdpCurrentSymbolStart, KdpCurrentSymbolEnd;
//
KdInitSystem(IN ULONG BootPhase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
- BOOLEAN EnableKd;
- LPSTR CommandLine, DebugLine;
+ BOOLEAN EnableKd, DisableKdAfterInit = FALSE, BlockEnable;
+ LPSTR CommandLine, DebugLine, DebugOptionStart, DebugOptionEnd;
ANSI_STRING ImageName;
PLDR_DATA_TABLE_ENTRY LdrEntry;
PLIST_ENTRY NextEntry;
- ULONG i, j, Length;
+ ULONG i, j, Length, DebugOptionLength;
CHAR NameBuffer[256];
PWCHAR Name;
+#if defined(__GNUC__)
+ /* Make gcc happy */
+ BlockEnable = FALSE;
+#endif
+
/* Check if this is Phase 1 */
if (BootPhase)
{
/* Enable KD */
EnableKd = TRUE;
- /* Check if there was additional data */
+ /* Check if there are any options */
if (DebugLine[5] == '=')
{
- /* FIXME: Check for NOUMEX, DISABLE, AUTOENABLE */
+ /* Save pointers */
+ DebugOptionStart = DebugOptionEnd = &DebugLine[6];
+
+ /* Scan the string for debug options */
+ for (;;)
+ {
+ /* Loop until we reach the end of the string */
+ while (*DebugOptionEnd != ANSI_NULL)
+ {
+ /* Check if this is a comma, a space or a tab */
+ if ((*DebugOptionEnd == ',') ||
+ (*DebugOptionEnd == ' ') ||
+ (*DebugOptionEnd == ' '))
+ {
+ /*
+ * We reached the end of the option or
+ * the end of the string, break out
+ */
+ break;
+ }
+ else
+ {
+ /* Move on to the next character */
+ DebugOptionEnd++;
+ }
+ }
+
+ /* Calculate the length of the current option */
+ DebugOptionLength = ((ULONG_PTR)DebugOptionEnd -
+ (ULONG_PTR)DebugOptionStart);
+
+ /*
+ * Break out if we reached the last option
+ * or if there were no options at all
+ */
+ if (!DebugOptionLength) break;
+
+ /* Now check which option this is */
+ if ((DebugOptionLength == 10) &&
+ !(strncmp(DebugOptionStart, "AUTOENABLE", 10)))
+ {
+ /*
+ * Disable the debugger, but
+ * allow it to be reenabled
+ */
+ DisableKdAfterInit = TRUE;
+ BlockEnable = FALSE;
+ KdAutoEnableOnEvent = TRUE;
+ }
+ else if ((DebugOptionLength == 7) &&
+ !(strncmp(DebugOptionStart, "DISABLE", 7)))
+ {
+ /* Disable the debugger */
+ DisableKdAfterInit = TRUE;
+ BlockEnable = TRUE;
+ KdAutoEnableOnEvent = FALSE;
+ }
+ else if ((DebugOptionLength == 6) &&
+ !(strncmp(DebugOptionStart, "NOUMEX", 6)))
+ {
+ /* Ignore user mode exceptions */
+ KdIgnoreUmExceptions = TRUE;
+ }
+
+ /*
+ * If there are more options then
+ * the next character should be a comma
+ */
+ if (*DebugOptionEnd != ',')
+ {
+ /* It isn't, break out */
+ break;
+ }
+
+ /* Move on to the next option */
+ DebugOptionEnd++;
+ DebugOptionStart = DebugOptionEnd;
+ }
}
}
}
}
else
{
- /* Called from a bugcheck...Save the Kernel Base */
+ /* Called from a bugcheck or a re-enable. Save the Kernel Base */
KdVersionBlock.KernBase = (ULONG64)(LONG_PTR)PsNtosImageBase;
/* Unconditionally enable KD */
SharedUserData->KdDebuggerEnabled = TRUE;
#define KdDebuggerEnabled _KdDebuggerEnabled
+ /* Check if the debugger should be disabled initially */
+ if (DisableKdAfterInit)
+ {
+ /* Disable it */
+ KdDisableDebuggerWithLock(FALSE);
+
+ /*
+ * Save the enable block state and return initialized
+ * (the debugger is active but disabled).
+ */
+ KdBlockEnable = BlockEnable;
+ return TRUE;
+ }
+
/* Check if we have a loader block */
if (LoaderBlock)
{
return FALSE;
}
}
+
+BOOLEAN
+NTAPI
+KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context,
+ IN KPROCESSOR_MODE PreviousMode)
+{
+ /* Check if this is a breakpoint or a valid debug service */
+ if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
+ (ExceptionRecord->NumberParameters > 0) &&
+ (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK))
+ {
+ /* Then we have to handle it */
+ return TRUE;
+ }
+ else
+ {
+ /* We don't have to handle it */
+ return FALSE;
+ }
+}
/* User mode exception, was it first-chance? */
if (FirstChance)
{
- /* Make sure a debugger is present, and ignore user-mode if requested */
- if ((KiDebugRoutine) &&
- (!(PsGetCurrentProcess()->DebugPort)))
+ /*
+ * Break into the kernel debugger unless a user mode debugger
+ * is present or user mode exceptions are ignored, unless this is
+ * a breakpoint or a debug service in which case we have to
+ * handle it.
+ */
+ if ((!(PsGetCurrentProcess()->DebugPort) &&
+ !(KdIgnoreUmExceptions)) ||
+ (KdIsThisAKdTrap(ExceptionRecord,
+ &Context,
+ PreviousMode)))
{
- /* Call the debugger */
+ /* Call the kernel debugger */
if (KiDebugRoutine(TrapFrame,
ExceptionFrame,
ExceptionRecord,
}
/* Forward exception to user mode debugger */
- if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) goto Exit;
+ if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) return;
/* Set up the user-stack */
DispatchToUser:
if (DbgkForwardException(ExceptionRecord, TRUE, TRUE))
{
/* Handled, get out */
- goto Exit;
+ return;
}
else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE))
{
/* Handled, get out */
- goto Exit;
+ return;
}
/* 3rd strike, kill the process */
TrapFrame,
Context.ContextFlags,
PreviousMode);
-Exit:
return;
}
TRAP_PROLOG kit3_a, kit3_t
/* Set status code */
- mov eax, 0 //STATUS_SUCCESS
+ mov eax, STATUS_SUCCESS
/* Check for V86 */
PrepareInt3:
<file>pnproot.c</file>
</directory>
</directory>
- <directory name="kd">
- <if property="ARCH" value="i386">
- <directory name="i386">
- <file>kdmemsup.c</file>
- </directory>
- </if>
- </directory>
+ <if property="KDBG" value="1">
+ <directory name="kd">
+ <if property="ARCH" value="i386">
+ <directory name="i386">
+ <file>kdmemsup.c</file>
+ </directory>
+ </if>
+ </directory>
+ </if>
<if property="_WINKD_" value="0">
<directory name="kdbg">
<if property="ARCH" value="i386">