- Add kd64 folder for KD64 6.0 implementation.

- Implement KdEnterDebugger, KdExitDebugger, KdEnableDebuggerWithLock, KdEnableDebugger.
- Add KD Version Block, KD Component Masks, and KD Configuration Options.
- Implement KdInitSystem and KdRegisterDebuggerDataBlock.
- Implement KdPollBreakIn, KdpLockPort, KdpUnlockPort.
- Implement KdpStub and KdpReport. Implement logic of KdpTrap but not helper calls (KdpTrap is only enabled after KD connects).
- Implement KD Time Slip support, KdpSwitchProcessor, KdpQueryPerformanceCounter.

svn path=/branches/alex-kd-branch/; revision=25838
This commit is contained in:
Alex Ionescu
2007-02-18 20:51:30 +00:00
parent e126eb3077
commit 929844ef2a
8 changed files with 1271 additions and 50 deletions
+124 -9
View File
@@ -1,12 +1,3 @@
//
// Kernel Debugger Port Definition
//
extern BOOLEAN _KdDebuggerEnabled;
extern BOOLEAN _KdDebuggerNotPresent;
extern BOOLEAN KdBreakAfterSymbolLoad;
/* KD GLOBALS ***************************************************************/
typedef
BOOLEAN
(NTAPI *PKDEBUG_ROUTINE)(
@@ -18,4 +9,128 @@ BOOLEAN
IN BOOLEAN SecondChance
);
typedef
BOOLEAN
(NTAPI *PKDEBUG_SWITCH_ROUTINE)(
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN BOOLEAN SecondChance
);
BOOLEAN
NTAPI
KdpEnterDebuggerException(
IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN SecondChance
);
VOID
NTAPI
KdpTimeSlipWork(
IN PVOID Context
);
BOOLEAN
NTAPI
KdpSwitchProcessor(
IN PEXCEPTION_RECORD ExceptionRecord,
IN OUT PCONTEXT ContextRecord,
IN BOOLEAN SecondChanceException
);
VOID
NTAPI
KdpTimeSlipDpcRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
BOOLEAN
NTAPI
KdpStub(
IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN SecondChanceException
);
BOOLEAN
NTAPI
KdpTrap(
IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN SecondChanceException
);
VOID
NTAPI
KdpPortLock(
VOID
);
VOID
NTAPI
KdpPortUnlock(
VOID
);
BOOLEAN
NTAPI
KdEnterDebugger(
IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame
);
VOID
NTAPI
KdExitDebugger(
IN BOOLEAN Entered
);
NTSTATUS
NTAPI
KdEnableDebuggerWithLock(
IN BOOLEAN NeedLock
);
extern DBGKD_GET_VERSION64 KdVersionBlock;
extern KDDEBUGGER_DATA64 KdDebuggerDataBlock;
extern LIST_ENTRY KdpDebuggerDataListHead;
extern KSPIN_LOCK KdpDataSpinLock;
extern LARGE_INTEGER KdPerformanceCounterRate;
extern LARGE_INTEGER KdTimerStart;
extern ULONG KdDisableCount;
extern KD_CONTEXT KdpContext;
extern PKDEBUG_ROUTINE KiDebugRoutine;
extern PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine;
extern BOOLEAN KdBreakAfterSymbolLoad;
extern BOOLEAN KdPitchDebugger;
extern BOOLEAN _KdDebuggerNotPresent;
extern BOOLEAN _KdDebuggerEnabled;
extern BOOLEAN KdAutoEnableOnEvent;
extern BOOLEAN KdPreviouslyEnabled;
extern BOOLEAN KdpDebuggerStructuresInitialized;
extern BOOLEAN KdEnteredDebugger;
extern KDPC KdpTimeSlipDpc;
extern KTIMER KdpTimeSlipTimer;
extern WORK_QUEUE_ITEM KdpTimeSlipWorkItem;
extern LONG KdpTimeSlipPending;
extern PKEVENT KdpTimeSlipEvent;
extern KSPIN_LOCK KdpTimeSlipEventLock;
extern BOOLEAN KdpControlCPressed;
extern BOOLEAN KdpControlCWaiting;
extern BOOLEAN KdpPortLocked;
extern KSPIN_LOCK KdpDebuggerLock;
extern LARGE_INTEGER KdTimerStop, KdTimerStart, KdTimerDifference;
+261
View File
@@ -0,0 +1,261 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/kd64/kdapi.c
* PURPOSE: KD64 Public Routines and Internal Support
* PROGRAMMERS: Alex Ionescu ([email protected])
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
LONG OldSlip, NewSlip, PendingSlip;
/* Get the current pending slip */
PendingSlip = KdpTimeSlipPending;
do
{
/* Save the old value and either disable or enable it now. */
OldSlip = PendingSlip;
NewSlip = OldSlip > 1 ? 1 : 0;
/* Try to change the value */
} while (InterlockedCompareExchange(&KdpTimeSlipPending,
NewSlip,
OldSlip) != OldSlip);
/* If the New Slip value is 1, then do the Time Slipping */
if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
}
VOID
NTAPI
KdpTimeSlipWork(IN PVOID Context)
{
KIRQL OldIrql;
LARGE_INTEGER DueTime;
/* Update the System time from the CMOS */
ExAcquireTimeRefreshLock(FALSE);
ExUpdateSystemTimeFromCmos(FALSE, 0);
ExReleaseTimeRefreshLock();
/* Check if we have a registered Time Slip Event and signal it */
KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
/* Delay the DPC until it runs next time */
DueTime.QuadPart = -1800000000;
KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
}
BOOLEAN
NTAPI
KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
IN OUT PCONTEXT ContextRecord,
IN BOOLEAN SecondChanceException)
{
BOOLEAN Status;
/* Save the port data */
KdSave(FALSE);
/* Report a state change */
#if 0
Status = KdpReportExceptionStateChange(ExceptionRecord,
ContextRecord,
SecondChanceException);
#else
Status = FALSE;
#endif
/* Restore the port data and return */
KdRestore(FALSE);
return Status;
}
LARGE_INTEGER
NTAPI
KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
{
LARGE_INTEGER Null = {{0}};
/* Check if interrupts were disabled */
if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
{
/* Nothing to return */
return Null;
}
/* Otherwise, do the call */
return KeQueryPerformanceCounter(NULL);
}
BOOLEAN
NTAPI
KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame)
{
BOOLEAN Entered;
/* Check if we have a trap frame */
if (TrapFrame)
{
/* Calculate the time difference for the enter */
KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
KdTimerStart.QuadPart;
}
else
{
/* No trap frame, so can't calculate */
KdTimerStop.QuadPart = 0;
}
/* Save the current IRQL */
KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
/* Freeze all CPUs */
Entered = KeFreezeExecution(TrapFrame, ExceptionFrame);
/* Lock the port, save the state and set debugger entered */
KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
KdSave(FALSE);
KdEnteredDebugger = TRUE;
/* Check freeze flag */
if (KiFreezeFlag & 1)
{
/* Print out errror */
DbgPrint("FreezeLock was jammed! Backup SpinLock was used!\n");
}
/* Check processor state */
if (KiFreezeFlag & 2)
{
/* Print out errror */
DbgPrint("Some processors not frozen in debugger!\n");
}
/* Make sure we acquired the port */
if (!KdpPortLocked) DbgPrint("Port lock was not acquired!\n");
/* Return enter state */
return Entered;
}
VOID
NTAPI
KdExitDebugger(IN BOOLEAN Entered)
{
ULONG TimeSlip;
/* Restore the state and unlock the port */
KdRestore(FALSE);
if (KdpPortLocked) KdpPortUnlock();
/* Unfreeze the CPUs */
KeThawExecution(Entered);
/* Compare time with the one from KdEnterDebugger */
if (!KdTimerStop.QuadPart)
{
/* We didn't get a trap frame earlier in so never got the time */
KdTimerStart = KdTimerStop;
}
else
{
/* Query the timer */
KdTimerStart = KeQueryPerformanceCounter(NULL);
}
/* Check if a Time Slip was on queue */
TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
if (TimeSlip == 1)
{
/* Queue a DPC for the time slip */
InterlockedIncrement(&KdpTimeSlipPending);
KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
}
}
NTSTATUS
NTAPI
KdEnableDebuggerWithLock(BOOLEAN NeedLock)
{
KIRQL OldIrql;
/* 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 we had locked the port before */
if (NeedLock)
{
/* Do the unlock */
KeLowerIrql(OldIrql);
KdpPortUnlock();
}
/* Fail: We're already enabled */
return STATUS_INVALID_PARAMETER;
}
/* Decrease the disable count */
if (!(--KdDisableCount))
{
/* We're now enabled again! Were we enabled before, too? */
if (KdPreviouslyEnabled)
{
/* Reinitialize the Debugger */
KdInitSystem(0, NULL) ;
//KdpRestoreAllBreakpoints();
}
}
/* 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 **********************************************************/
/*
* @implemented
*/
NTSTATUS
NTAPI
KdEnableDebugger(VOID)
{
/* Use the internal routine */
while (TRUE);
return KdEnableDebuggerWithLock(TRUE);
}
+305
View File
@@ -0,0 +1,305 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/kd64/kddata.c
* PURPOSE: Contains all global variables and settings for KD64
* PROGRAMMERS: Alex Ionescu ([email protected])
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
//
// Debugger Version Block
//
DBGKD_GET_VERSION64 KdVersionBlock =
{
0,
0,
DBGKD_64BIT_PROTOCOL_VERSION2,
KD_SECONDARY_VERSION_DEFAULT,
DBGKD_VERS_FLAG_DATA,
IMAGE_FILE_MACHINE_I386,
PACKET_TYPE_MAX,
0,
0,
DBGKD_SIMULATION_NONE,
{0},
0,
0,
0
};
//
// Debugger Data
//
KDDEBUGGER_DATA64 KdDebuggerDataBlock;
LIST_ENTRY KdpDebuggerDataListHead;
KSPIN_LOCK KdpDataSpinLock;
//
// Debugger State
//
KD_CONTEXT KdpContext;
BOOLEAN KdpControlCPressed;
BOOLEAN KdpControlCWaiting;
BOOLEAN KdpPortLocked;
KSPIN_LOCK KdpDebuggerLock;
//
// Debug Trap Handlers
//
PKDEBUG_ROUTINE KiDebugRoutine = KdpStub;
PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine;
//
// Debugger Configuration Settings
//
BOOLEAN KdBreakAfterSymbolLoad;
BOOLEAN KdPitchDebugger;
BOOLEAN _KdDebuggerNotPresent = TRUE;
BOOLEAN _KdDebuggerEnabled;
BOOLEAN KdAutoEnableOnEvent;
BOOLEAN KdPreviouslyEnabled;
BOOLEAN KdpDebuggerStructuresInitialized;
BOOLEAN KdEnteredDebugger;
ULONG KdDisableCount;
LARGE_INTEGER KdPerformanceCounterRate;
//
// Time Slip Support
//
KDPC KdpTimeSlipDpc;
KTIMER KdpTimeSlipTimer;
WORK_QUEUE_ITEM KdpTimeSlipWorkItem;
LONG KdpTimeSlipPending;
PKEVENT KdpTimeSlipEvent;
KSPIN_LOCK KdpTimeSlipEventLock;
LARGE_INTEGER KdTimerStop, KdTimerStart, KdTimerDifference;
//
// Debug Filter Masks
//
ULONG Kd_WIN2000_Mask = 1;
ULONG Kd_SYSTEM_Mask;
ULONG Kd_SMSS_Mask;
ULONG Kd_SETUP_Mask;
ULONG Kd_NTFS_Mask;
ULONG Kd_FSTUB_Mask;
ULONG Kd_CRASHDUMP_Mask;
ULONG Kd_CDAUDIO_Mask;
ULONG Kd_CDROM_Mask;
ULONG Kd_CLASSPNP_Mask;
ULONG Kd_DISK_Mask;
ULONG Kd_REDBOOK_Mask;
ULONG Kd_STORPROP_Mask;
ULONG Kd_SCSIPORT_Mask;
ULONG Kd_SCSIMINIPORT_Mask;
ULONG Kd_CONFIG_Mask;
ULONG Kd_I8042PRT_Mask;
ULONG Kd_SERMOUSE_Mask;
ULONG Kd_LSERMOUS_Mask;
ULONG Kd_KBDHID_Mask;
ULONG Kd_MOUHID_Mask;
ULONG Kd_KBDCLASS_Mask;
ULONG Kd_MOUCLASS_Mask;
ULONG Kd_TWOTRACK_Mask;
ULONG Kd_WMILIB_Mask;
ULONG Kd_ACPI_Mask;
ULONG Kd_AMLI_Mask;
ULONG Kd_HALIA64_Mask;
ULONG Kd_VIDEO_Mask;
ULONG Kd_SVCHOST_Mask;
ULONG Kd_VIDEOPRT_Mask;
ULONG Kd_TCPIP_Mask;
ULONG Kd_DMSYNTH_Mask;
ULONG Kd_NTOSPNP_Mask;
ULONG Kd_FASTFAT_Mask;
ULONG Kd_SAMSS_Mask;
ULONG Kd_PNPMGR_Mask;
ULONG Kd_NETAPI_Mask;
ULONG Kd_SCSERVER_Mask;
ULONG Kd_SCCLIENT_Mask;
ULONG Kd_SERIAL_Mask;
ULONG Kd_SERENUM_Mask;
ULONG Kd_UHCD_Mask;
ULONG Kd_RPCPROXY_Mask;
ULONG Kd_AUTOCHK_Mask;
ULONG Kd_DCOMSS_Mask;
ULONG Kd_UNIMODEM_Mask;
ULONG Kd_SIS_Mask;
ULONG Kd_FLTMGR_Mask;
ULONG Kd_WMICORE_Mask;
ULONG Kd_BURNENG_Mask;
ULONG Kd_IMAPI_Mask;
ULONG Kd_SXS_Mask;
ULONG Kd_FUSION_Mask;
ULONG Kd_IDLETASK_Mask;
ULONG Kd_SOFTPCI_Mask;
ULONG Kd_TAPE_Mask;
ULONG Kd_MCHGR_Mask;
ULONG Kd_IDEP_Mask;
ULONG Kd_PCIIDE_Mask;
ULONG Kd_FLOPPY_Mask;
ULONG Kd_FDC_Mask;
ULONG Kd_TERMSRV_Mask;
ULONG Kd_W32TIME_Mask;
ULONG Kd_PREFETCHER_Mask;
ULONG Kd_RSFILTER_Mask;
ULONG Kd_FCPORT_Mask;
ULONG Kd_PCI_Mask;
ULONG Kd_DMIO_Mask;
ULONG Kd_DMCONFIG_Mask;
ULONG Kd_DMADMIN_Mask;
ULONG Kd_WSOCKTRANSPORT_Mask;
ULONG Kd_VSS_Mask;
ULONG Kd_PNPMEM_Mask;
ULONG Kd_PROCESSOR_Mask;
ULONG Kd_DMSERVER_Mask;
ULONG Kd_SR_Mask;
ULONG Kd_INFINIBAND_Mask;
ULONG Kd_IHVDRIVER_Mask;
ULONG Kd_IHVVIDEO_Mask;
ULONG Kd_IHVAUDIO_Mask;
ULONG Kd_IHVNETWORK_Mask;
ULONG Kd_IHVSTREAMING_Mask;
ULONG Kd_IHVBUS_Mask;
ULONG Kd_HPS_Mask;
ULONG Kd_RTLTHREADPOOL_Mask;
ULONG Kd_LDR_Mask;
ULONG Kd_TCPIP6_Mask;
ULONG Kd_ISAPNP_Mask;
ULONG Kd_SHPC_Mask;
ULONG Kd_STORPORT_Mask;
ULONG Kd_STORMINIPORT_Mask;
ULONG Kd_PRINTSPOOLER_Mask;
ULONG Kd_VSSDYNDISK_Mask;
ULONG Kd_VERIFIER_Mask;
ULONG Kd_VDS_Mask;
ULONG Kd_VDSBAS_Mask;
ULONG Kd_VDSDYNDR_Mask;
ULONG Kd_VDSUTIL_Mask;
ULONG Kd_DFRGIFC_Mask;
ULONG Kd_DEFAULT_Mask;
ULONG Kd_MM_Mask;
ULONG Kd_DFSC_Mask;
ULONG Kd_WOW64_Mask;
ULONG Kd_ENDOFTABLE_Mask;
//
// Debug Filter Component Table
//
PULONG KdComponentTable[104] =
{
&Kd_SYSTEM_Mask,
&Kd_SMSS_Mask,
&Kd_SETUP_Mask,
&Kd_NTFS_Mask,
&Kd_FSTUB_Mask,
&Kd_CRASHDUMP_Mask,
&Kd_CDAUDIO_Mask,
&Kd_CDROM_Mask,
&Kd_CLASSPNP_Mask,
&Kd_DISK_Mask,
&Kd_REDBOOK_Mask,
&Kd_STORPROP_Mask,
&Kd_SCSIPORT_Mask,
&Kd_SCSIMINIPORT_Mask,
&Kd_CONFIG_Mask,
&Kd_I8042PRT_Mask,
&Kd_SERMOUSE_Mask,
&Kd_LSERMOUS_Mask,
&Kd_KBDHID_Mask,
&Kd_MOUHID_Mask,
&Kd_KBDCLASS_Mask,
&Kd_MOUCLASS_Mask,
&Kd_TWOTRACK_Mask,
&Kd_WMILIB_Mask,
&Kd_ACPI_Mask,
&Kd_AMLI_Mask,
&Kd_HALIA64_Mask,
&Kd_VIDEO_Mask,
&Kd_SVCHOST_Mask,
&Kd_VIDEOPRT_Mask,
&Kd_TCPIP_Mask,
&Kd_DMSYNTH_Mask,
&Kd_NTOSPNP_Mask,
&Kd_FASTFAT_Mask,
&Kd_SAMSS_Mask,
&Kd_PNPMGR_Mask,
&Kd_NETAPI_Mask,
&Kd_SCSERVER_Mask,
&Kd_SCCLIENT_Mask,
&Kd_SERIAL_Mask,
&Kd_SERENUM_Mask,
&Kd_UHCD_Mask,
&Kd_RPCPROXY_Mask,
&Kd_AUTOCHK_Mask,
&Kd_DCOMSS_Mask,
&Kd_UNIMODEM_Mask,
&Kd_SIS_Mask,
&Kd_FLTMGR_Mask,
&Kd_WMICORE_Mask,
&Kd_BURNENG_Mask,
&Kd_IMAPI_Mask,
&Kd_SXS_Mask,
&Kd_FUSION_Mask,
&Kd_IDLETASK_Mask,
&Kd_SOFTPCI_Mask,
&Kd_TAPE_Mask,
&Kd_MCHGR_Mask,
&Kd_IDEP_Mask,
&Kd_PCIIDE_Mask,
&Kd_FLOPPY_Mask,
&Kd_FDC_Mask,
&Kd_TERMSRV_Mask,
&Kd_W32TIME_Mask,
&Kd_PREFETCHER_Mask,
&Kd_RSFILTER_Mask,
&Kd_FCPORT_Mask,
&Kd_PCI_Mask,
&Kd_DMIO_Mask,
&Kd_DMCONFIG_Mask,
&Kd_DMADMIN_Mask,
&Kd_WSOCKTRANSPORT_Mask,
&Kd_VSS_Mask,
&Kd_PNPMEM_Mask,
&Kd_PROCESSOR_Mask,
&Kd_DMSERVER_Mask,
&Kd_SR_Mask,
&Kd_INFINIBAND_Mask,
&Kd_IHVDRIVER_Mask,
&Kd_IHVVIDEO_Mask,
&Kd_IHVAUDIO_Mask,
&Kd_IHVNETWORK_Mask,
&Kd_IHVSTREAMING_Mask,
&Kd_IHVBUS_Mask,
&Kd_HPS_Mask,
&Kd_RTLTHREADPOOL_Mask,
&Kd_LDR_Mask,
&Kd_TCPIP6_Mask,
&Kd_ISAPNP_Mask,
&Kd_SHPC_Mask,
&Kd_STORPORT_Mask,
&Kd_STORMINIPORT_Mask,
&Kd_PRINTSPOOLER_Mask,
&Kd_VSSDYNDISK_Mask,
&Kd_VERIFIER_Mask,
&Kd_VDS_Mask,
&Kd_VDSBAS_Mask,
&Kd_VDSDYNDR_Mask,
&Kd_VDSUTIL_Mask,
&Kd_DFRGIFC_Mask,
&Kd_DEFAULT_Mask,
&Kd_MM_Mask,
&Kd_DFSC_Mask,
&Kd_WOW64_Mask,
&Kd_ENDOFTABLE_Mask,
};
ULONG KdComponentTableSize = sizeof(KdComponentTable);
+250
View File
@@ -0,0 +1,250 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/kd64/kdinit.c
* PURPOSE: KD64 Initialization Code
* PROGRAMMERS: Alex Ionescu ([email protected])
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
KdRegisterDebuggerDataBlock(IN ULONG Tag,
IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader,
IN ULONG Size)
{
KIRQL OldIrql;
PLIST_ENTRY NextEntry;
PDBGKD_DEBUG_DATA_HEADER64 CurrentHeader;
/* Acquire the Data Lock */
KeAcquireSpinLock(&KdpDataSpinLock, &OldIrql);
/* Loop the debugger data list */
NextEntry = KdpDebuggerDataListHead.Flink;
while (NextEntry != &KdpDebuggerDataListHead)
{
/* Get the header for this entry */
CurrentHeader = CONTAINING_RECORD(NextEntry,
DBGKD_DEBUG_DATA_HEADER64,
List);
/* Move to the next one */
NextEntry = NextEntry->Flink;
/* Check if we already have this data block */
if ((CurrentHeader == DataHeader) || (CurrentHeader->OwnerTag == Tag))
{
/* Release the lock and fail */
KeReleaseSpinLock(&KdpDataSpinLock, OldIrql);
return FALSE;
}
}
/* Setup the header */
DataHeader->OwnerTag = Tag;
DataHeader->Size = Size;
/* Insert it into the list and release the lock */
InsertTailList(&KdpDebuggerDataListHead, (PLIST_ENTRY)&DataHeader->List);
KeReleaseSpinLock(&KdpDataSpinLock, OldIrql);
return TRUE;
}
BOOLEAN
NTAPI
KdInitSystem(IN ULONG BootPhase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
BOOLEAN EnableKd;
LPSTR CommandLine, DebugLine;
ANSI_STRING ImageName;
PLDR_DATA_TABLE_ENTRY LdrEntry;
PLIST_ENTRY NextEntry;
ULONG i;
CHAR NameBuffer[256];
return TRUE;
/* Check if this is Phase 1 */
if (BootPhase)
{
/* Just query the performance counter */
KeQueryPerformanceCounter(&KdPerformanceCounterRate);
return TRUE;
}
/* Check if we already initialized once */
if (KdDebuggerEnabled) return TRUE;
/* Set the Debug Routine as the Stub for now */
KiDebugRoutine = KdpStub;
/* Disable break after symbol load for now */
KdBreakAfterSymbolLoad = FALSE;
/* Check if the Debugger Data Block was already initialized */
if (!KdpDebuggerDataListHead.Flink)
{
/* It wasn't...Initialize the KD Data Listhead */
InitializeListHead(&KdpDebuggerDataListHead);
/* Register the Debugger Data Block */
KdRegisterDebuggerDataBlock(KDBG_TAG,
&KdDebuggerDataBlock.Header,
sizeof(KdDebuggerDataBlock));
/* Fill out the KD Version Block */
KdVersionBlock.MajorVersion = (USHORT)(NtBuildNumber >> 28);
KdVersionBlock.MinorVersion = (USHORT)(NtBuildNumber & 0xFFFF);
#ifdef CONFIG_SMP
/* This is an MP Build */
KdVersionBlock.Flags |= DBGKD_VERS_FLAG_MP;
#endif
/* Save Pointers to Loaded Module List and Debugger Data */
KdVersionBlock.PsLoadedModuleList = (ULONG64)&PsLoadedModuleList;
KdVersionBlock.DebuggerDataList = (ULONG64)&KdpDebuggerDataListHead;
/* Set protocol limits */
KdVersionBlock.MaxStateChange = DbgKdMaximumStateChange -
DbgKdMinimumStateChange;
KdVersionBlock.MaxManipulate = DbgKdMaximumManipulate -
DbgKdMinimumManipulate;
KdVersionBlock.Unused[0] = 0;
/* Link us in the KPCR */
KeGetPcr()->KdVersionBlock = &KdVersionBlock;
}
/* Check if we have a loader block */
if (LoaderBlock)
{
/* Save the Kernel Base */
KdVersionBlock.KernBase = (ULONG64)LoaderBlock->KernelStack;
/* Check if we have a command line */
CommandLine = LoaderBlock->LoadOptions;
if (CommandLine)
{
/* Upcase it */
_strupr(CommandLine);
/* Assume we'll disable KD */
EnableKd = FALSE;
/* Check for CRASHDEBUG and NODEBUG */
if (strstr(CommandLine, "CRASHDEBUG")) KdPitchDebugger = FALSE;
if (strstr(CommandLine, "NODEBUG")) KdPitchDebugger = TRUE;
/* Check if DEBUG was on */
DebugLine = strstr(CommandLine, "DEBUG");
if (DebugLine)
{
/* Enable KD */
EnableKd = TRUE;
/* Check if there was additional data */
if (DebugLine[5] == '=')
{
/* FIXME: Check for NOUMEX, DISABLE, AUTOENABLE */
}
}
}
else
{
/* No command line options? Disable debugger by default */
KdPitchDebugger = TRUE;
EnableKd = FALSE;
}
}
else
{
/* Called from a bugcheck...Save the Kernel Base */
KdVersionBlock.KernBase = PsNtosImageBase;
/* Unconditionally enable KD */
EnableKd = TRUE;
}
/* Set the Kernel Base in the Data Block */
KdDebuggerDataBlock.KernBase = KdVersionBlock.KernBase;
/* Initialize the debugger if requested */
if ((EnableKd) && (NT_SUCCESS(KdDebuggerInitialize0(LoaderBlock))))
{
/* Now set our real KD routine */
KiDebugRoutine = KdpTrap;
/* Check if we've already initialized our structures */
if (!KdpDebuggerStructuresInitialized)
{
/* Set the Debug Switch Routine and Retries*/
KdpContext.KdpDefaultRetries = 20;
KiDebugSwitchRoutine = KdpSwitchProcessor;
/* Initialize the Time Slip DPC */
KeInitializeDpc(&KdpTimeSlipDpc, KdpTimeSlipDpcRoutine, NULL);
KeInitializeTimer(&KdpTimeSlipTimer);
ExInitializeWorkItem(&KdpTimeSlipWorkItem, KdpTimeSlipWork, NULL);
/* First-time initialization done! */
KdpDebuggerStructuresInitialized = TRUE;
}
/* Initialize the timer */
KdTimerStart.QuadPart = 0;
/* Officially enable KD */
KdPitchDebugger = FALSE;
KdDebuggerEnabled = TRUE;
/* Let user-mode know that it's enabled as well */
#undef KdDebuggerEnabled
SharedUserData->KdDebuggerEnabled = TRUE;
#define KdDebuggerEnabled _KdDebuggerEnabled
/* Check if we have a loader block */
if (LoaderBlock)
{
/* Loop boot images */
NextEntry = LoaderBlock->LoadOrderListHead.Flink;
i = 0;
while ((NextEntry != &LoaderBlock->LoadOrderListHead) && (i < 2))
{
/* Get the image entry */
LdrEntry = CONTAINING_RECORD(NextEntry,
LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
/* Generate the image name */
/* Load symbols for image */
RtlInitAnsiString(&ImageName, NameBuffer);
DbgLoadImageSymbols(&ImageName, LdrEntry->DllBase, -1);
/* Go to the next entry */
NextEntry = NextEntry->Flink;
i++;
}
}
/* Check for incoming breakin and break on symbol load if we have it*/
KdBreakAfterSymbolLoad = KdPollBreakIn();
}
else
{
/* Disable debugger */
KdDebuggerNotPresent = TRUE;
}
/* Return initialized */
return TRUE;
}
+90
View File
@@ -0,0 +1,90 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/kd64/kdlock.c
* PURPOSE: KD64 Port Lock and Breakin Support
* PROGRAMMERS: Alex Ionescu ([email protected])
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
KdpPortLock(VOID)
{
/* Acquire the lock */
KiAcquireSpinLock(&KdpDebuggerLock);
}
VOID
NTAPI
KdpPortUnlock(VOID)
{
/* Release the lock */
KiReleaseSpinLock(&KdpDebuggerLock);
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
BOOLEAN
NTAPI
KdPollBreakIn(VOID)
{
BOOLEAN DoBreak = FALSE;
ULONG Flags;
/* First make sure that KD is enabled */
if (KdDebuggerEnabled)
{
/* Disable interrupts */
Ke386SaveFlags(Flags);
//Flags = __getcallerseflags();
_disable();
/* Check if a CTRL-C is in the queue */
if (KdpControlCWaiting)
{
/* Set it and prepare for break */
KdpControlCPressed = TRUE;
DoBreak = TRUE;
KdpControlCWaiting = FALSE;
}
else
{
/* Try to acquire the lock */
if (KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock))
{
/* Now get a packet */
if (!KdReceivePacket(PACKET_TYPE_KD_POLL_BREAKIN,
NULL,
NULL,
NULL,
NULL))
{
/* Successful breakin */
DoBreak = TRUE;
KdpControlCPressed = TRUE;
}
/* Let go of the port */
KdpPortUnlock();
}
}
/* Re-enable interrupts if they were disabled */
if (Flags & EFLAGS_INTERRUPT_MASK) _enable();
}
/* Tell the caller to do a break */
return DoBreak;
}
+234
View File
@@ -0,0 +1,234 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/kd64/kdtrap.c
* PURPOSE: KD64 Trap Handlers
* PROGRAMMERS: Alex Ionescu ([email protected])
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
KdpReport(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN SecondChanceException)
{
BOOLEAN Entered, Status;
PKPRCB Prcb;
while (TRUE);
/*
* Only go ahead with this if this is an INT3 or an INT1, or if the global
* flag forces us to call up the debugger on exception, or if this is a
* second chance exception which means it hasn't been handled by now.
*/
if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) ||
(ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) ||
(NtGlobalFlag & FLG_STOP_ON_EXCEPTION) ||
(SecondChanceException))
{
/*
* Also, unless this is a second chance exception, then do not call up
* the debugger if the debug port is disconnected or the exception code
* indicates success.
*/
if (!(SecondChanceException) &&
((ExceptionRecord->ExceptionCode == STATUS_PORT_DISCONNECTED) ||
(NT_SUCCESS(ExceptionRecord->ExceptionCode))))
{
/* Return false to hide the exception */
return FALSE;
}
/* Enter the debugger */
Entered = KdEnterDebugger(TrapFrame, ExceptionFrame);
/*
* Get the KPRCB and save the CPU Control State manually instead of
* using KiSaveProcessorState, since we already have a valid CONTEXT.
*/
Prcb = KeGetCurrentPrcb();
KiSaveProcessorControlState(&Prcb->ProcessorState);
RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
ContextRecord,
sizeof(CONTEXT));
/* Report the new state */
#if 0
Status = KdpReportExceptionStateChange(ExceptionRecord,
&Prcb->ProcessorState.
ContextFrame,
SecondChanceException);
#else
Status = FALSE;
#endif
/* Now restore the processor state, manually again. */
RtlCopyMemory(ContextRecord,
&Prcb->ProcessorState.ContextFrame,
sizeof(CONTEXT));
KiRestoreProcessorControlState(&Prcb->ProcessorState);
/* Exit the debugger and clear the CTRL-C state */
KdExitDebugger(Entered);
KdpControlCPressed = FALSE;
return Status;
}
/* Fail if we got here */
return FALSE;
}
BOOLEAN
NTAPI
KdpTrap(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN SecondChanceException)
{
BOOLEAN Unload = FALSE;
ULONG Eip, Eax;
BOOLEAN Status = FALSE;
while (TRUE);
/*
* Check if we got a STATUS_BREAKPOINT with a SubID for Print, Prompt or
* Load/Unload symbols.
*/
if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
(ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK))
{
/* Save EIP */
Eip = ContextRecord->Eip;
/* Check what kind of operation was requested from us */
switch (ExceptionRecord->ExceptionInformation[0])
{
/* DbgPrint */
case BREAKPOINT_PRINT:
/* Call the worker routine */
Eax = 0;
/* Update the return value for the caller */
ContextRecord->Eax = Eax;
break;
/* DbgPrompt */
case BREAKPOINT_PROMPT:
/* Call the worker routine */
Eax = 0;
Status = TRUE;
/* Update the return value for the caller */
ContextRecord->Eax = Eax;
break;
/* DbgUnloadSymbols */
case BREAKPOINT_UNLOAD_SYMBOLS:
/* Drop into the load case below, with the unload parameter */
Unload = TRUE;
/* DbgLoadSymbols */
case BREAKPOINT_LOAD_SYMBOLS:
/* Call the worker routine */
Status = TRUE;
break;
/* DbgCommandString*/
case BREAKPOINT_COMMAND_STRING:
/* Call the worker routine */
Status = TRUE;
/* Anything else, do nothing */
default:
/* Get out */
break;
}
/*
* If EIP was not updated, we'll increment it ourselves so execution
* continues past the breakpoint.
*/
if (ContextRecord->Eip == Eip) ContextRecord->Eip++;
}
else
{
/* Call the worker routine */
Status = KdpReport(TrapFrame,
ExceptionFrame,
ExceptionRecord,
ContextRecord,
PreviousMode,
SecondChanceException);
}
/* Return TRUE or FALSE to caller */
return Status;
}
BOOLEAN
NTAPI
KdpStub(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN SecondChanceException)
{
ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
/* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
(ExceptionRecord->NumberParameters > 0) &&
((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
(ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
(ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
(ExceptionCommand == BREAKPOINT_PRINT)))
{
/* This we can handle: simply bump EIP */
ContextRecord->Eip++;
return TRUE;
}
else if (KdPitchDebugger)
{
/* There's no debugger, fail. */
return FALSE;
}
else if ((KdAutoEnableOnEvent) &&
(KdPreviouslyEnabled) &&
!(KdDebuggerEnabled) &&
(KdEnableDebugger()) &&
(KdDebuggerEnabled))
{
/* Debugging was Auto-Enabled. We can now send this to KD. */
return KdpTrap(TrapFrame,
ExceptionFrame,
ExceptionRecord,
ContextRecord,
PreviousMode,
SecondChanceException);
}
else
{
/* FIXME: All we can do in this case is trace this exception */
return FALSE;
}
}
-41
View File
@@ -16,47 +16,6 @@
/* GLOBALS *******************************************************************/
BOOLEAN
NTAPI
KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN SecondChance)
{
/* HACK (just like all this routine */
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
{
Context->Eip++;
return TRUE;
}
return FALSE;
}
BOOLEAN
NTAPI
KdInitSystem(IN ULONG BootPhase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
/* STUB */
return TRUE;
}
BOOLEAN
NTAPI
KdPollBreakIn(VOID)
{
/* STUB */
return FALSE;
}
BOOLEAN _KdDebuggerEnabled = FALSE;
BOOLEAN _KdDebuggerNotPresent = TRUE;
BOOLEAN KdBreakAfterSymbolLoad = FALSE;
PKDEBUG_ROUTINE KiDebugRoutine = KdpEnterDebuggerException;
/* DR Registers in the CONTEXT structure */
UCHAR KiDebugRegisterContextOffsets[9] =
{
+7
View File
@@ -193,6 +193,13 @@
<file>pnproot.c</file>
</directory>
</directory>
<directory name="kd64">
<file>kdapi.c</file>
<file>kddata.c</file>
<file>kdinit.c</file>
<file>kdlock.c</file>
<file>kdtrap.c</file>
</directory>
<directory name="ldr">
<file>loader.c</file>
<file>rtl.c</file>