/*++ Copyright (c) 1990-2001 Microsoft Corporation Module Name: kdp.h Abstract: Private include file for the Kernel Debugger subcomponent of the NTOS project Author: Mike O'Leary (mikeol) 29-June-1989 Revision History: --*/ #include "ntos.h" #include "ki.h" #define NOEXTAPI #include "wdbgexts.h" #include "ntdbg.h" #include "string.h" #include "stdlib.h" #include "kddll.h" #if defined(_ALPHA_) #include "alphaops.h" // // Define KD private PCR routines. // // Using the following private KD routines allows the kernel debugger to // step over breakpoints in modules that call the standard PCR routines. // PKPCR KdpGetPcr(); ULONG KdpReadInternalProcessorState(PVOID, ULONG); ULONG KdpReadInternalProcessorCounters(PVOID, ULONG); struct _KPRCB * KdpGetCurrentPrcb(); struct _KTHREAD * KdpGetCurrentThread(); // // Redefine the standard PCR routines // #undef KiPcr #define KiPcr KdpGetPcr() #undef KeGetPcr #undef KeGetCurrentPrcb #undef KeGetCurrentThread #undef KeIsExecutingDpc #define KeGetPcr() KdpGetPcr() #define KeGetCurrentPrcb() KdpGetCurrentPrcb() #define KeGetCurrentThread() KdpGetCurrentThread() // // Define TYPES // #define KDP_BREAKPOINT_TYPE ULONG #define KDP_BREAKPOINT_BUFFER sizeof(ULONG) // longword aligned #define KDP_BREAKPOINT_ALIGN 3 #define KDP_BREAKPOINT_INSTR_ALIGN 3 // actual instruction is "call_pal kbpt" #define KDP_BREAKPOINT_VALUE KBPT_FUNC #elif defined(_IA64_) // IA64 instruction is in a 128-bit bundle. Each bundle consists of 3 instruction slots. // Each instruction slot is 41-bit long. // // // 127 87 86 46 45 5 4 1 0 // ------------------------------------------------------------ // | slot 2 | slot 1 | slot 0 |template|S| // ------------------------------------------------------------ // // 127 96 95 64 63 32 31 0 // ------------------------------------------------------------ // | byte 3 | byte 2 | byte 1 | byte 0 | // ------------------------------------------------------------ // // This presents two incompatibilities with conventional processors: // 1. The IA64 IP address is at the bundle bundary. The instruction slot number is // stored in ISR.ei at the time of exception. // 2. The 41-bit instruction format is not byte-aligned. // // Break instruction insertion must be done with proper bit-shifting to align with the selected // instruction slot. Further, to insert break instruction insertion at a specific slot, we must // be able to specify instruction slot as part of the address. We therefore define an EM address as // bundle address + slot number with the least significant two bit always zero: // // 31 4 3 2 1 0 // -------------------------------- // | bundle address |slot#|0 0| // -------------------------------- // // The EM address as defined is the byte-aligned address that is closest to the actual instruction slot. // i.e., The EM instruction address of slot #0 is equal to bundle address. // slot #1 is equal to bundle address + 4. // slot #2 is equal to bundle address + 8. // // Upon exception, the bundle address is kept in IIP, and the instruction slot which caused // the exception is in ISR.ei. Kernel exception handler will construct the flat address and // export it in ExceptionRecord.ExceptionAddress. #define KDP_BREAKPOINT_TYPE ULONGLONG // 64-bit ULONGLONG type is needed to cover 41-bit EM break instruction. #define KDP_BREAKPOINT_BUFFER (2 * sizeof(ULONGLONG)) #define KDP_BREAKPOINT_ALIGN 0x3 // An EM address consists of bundle and slot number and is 32-bit aligned. #define KDP_BREAKPOINT_INSTR_ALIGN 0xf #define KDP_BREAKPOINT_VALUE (BREAK_INSTR | (BREAKPOINT_STOP << 6)) #elif defined(_X86_) || defined(_AMD64_) #define KDP_BREAKPOINT_TYPE UCHAR #define KDP_BREAKPOINT_BUFFER sizeof(UCHAR) #define KDP_BREAKPOINT_ALIGN 0 #define KDP_BREAKPOINT_INSTR_ALIGN 0 #define KDP_BREAKPOINT_VALUE 0xcc #endif // // Define constants. // // // Addresses above GLOBAL_BREAKPOINT_LIMIT are either in system space // or part of dynlink, so we treat them as global. // #define GLOBAL_BREAKPOINT_LIMIT 1610612736L // 1.5gigabytes // // Define breakpoint table entry structure. // #define KD_BREAKPOINT_IN_USE 0x00000001 #define KD_BREAKPOINT_NEEDS_WRITE 0x00000002 #define KD_BREAKPOINT_SUSPENDED 0x00000004 #define KD_BREAKPOINT_NEEDS_REPLACE 0x00000008 // IA64 specific defines #define KD_BREAKPOINT_STATE_MASK 0x0000000f #define KD_BREAKPOINT_IA64_MASK 0x000f0000 #define KD_BREAKPOINT_IA64_MODE 0x00010000 // IA64 mode #define KD_BREAKPOINT_IA64_MOVL 0x00020000 // MOVL instruction displaced typedef struct _BREAKPOINT_ENTRY { ULONG Flags; ULONG_PTR DirectoryTableBase; PVOID Address; KDP_BREAKPOINT_TYPE Content; } BREAKPOINT_ENTRY, *PBREAKPOINT_ENTRY; // // Misc defines // #define MAXIMUM_RETRIES 20 #define DBGKD_MAX_SPECIAL_CALLS 10 typedef struct _TRACE_DATA_SYM { ULONG SymMin; ULONG SymMax; } TRACE_DATA_SYM, *PTRACE_DATA_SYM; #define KD_MAX_REMOTE_FILES 16 typedef struct _KD_REMOTE_FILE { ULONG64 RemoteHandle; } KD_REMOTE_FILE, *PKD_REMOTE_FILE; // // Define function prototypes. // NTSTATUS KdpPrint( IN ULONG ComponentId, IN ULONG Level, IN PCHAR Message, IN USHORT Length, IN KPROCESSOR_MODE PreviousMode, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, OUT PBOOLEAN Completion ); BOOLEAN KdpPrintString ( IN PSTRING Output ); USHORT KdpPrompt( IN PCHAR Message, IN USHORT MessageLength, IN OUT PCHAR Reply, IN USHORT ReplyLength, IN KPROCESSOR_MODE PreviousMode, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ); BOOLEAN KdpPromptString ( IN PSTRING Output, IN OUT PSTRING Input ); BOOLEAN KdpReport( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChance ); VOID KdpSymbol( IN PSTRING String, IN PKD_SYMBOLS_INFO Symbol, IN BOOLEAN Unload, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ); VOID KdpCommandString( IN PSTRING Name, IN PSTRING Command, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ); ULONG KdpAddBreakpoint ( IN PVOID Address ); BOOLEAN KdpDeleteBreakpoint ( IN ULONG Handle ); BOOLEAN KdpDeleteBreakpointRange ( IN PVOID Lower, IN PVOID Upper ); #if defined(_IA64_) BOOLEAN KdpSuspendBreakpointRange ( IN PVOID Lower, IN PVOID Upper ); BOOLEAN KdpRestoreBreakpointRange ( IN PVOID Lower, IN PVOID Upper ); #endif #if i386 BOOLEAN KdpCheckTracePoint( IN PEXCEPTION_RECORD ExceptionRecord, IN OUT PCONTEXT ContextRecord ); NTSTATUS KdGetTraceInformation ( OUT PVOID TraceInformation, IN ULONG TraceInformationLength, OUT PULONG RequiredLength ); VOID KdSetInternalBreakpoint ( IN PDBGKD_MANIPULATE_STATE64 m ); #endif NTSTATUS KdQuerySpecialCalls ( IN PDBGKD_MANIPULATE_STATE64 m, IN ULONG Length, OUT PULONG RequiredLength ); VOID KdSetSpecialCall ( IN PDBGKD_MANIPULATE_STATE64 m, IN PCONTEXT ContextRecord ); VOID KdClearSpecialCalls ( VOID ); VOID KdpQuickMoveMemory ( IN PCHAR Destination, IN PCHAR Source, IN ULONG Length ); NTSTATUS KdpCopyMemoryChunks( ULONG64 Address, PVOID Buffer, ULONG TotalSize, ULONG ChunkSize, ULONG Flags, PULONG ActualSize OPTIONAL ); // // KdpCopyMemoryChunks always copies between an untrusted address // and a trusted buffer. The following two macros express a read // form of this and a write form in a way similar to RtlCopyMemory // for convenient replacement of RtlCopyMemory calls. // // Read memory from an untrusted pointer into a trusted buffer. #define KdpCopyFromPtr(Dst, Src, Size, Done) \ KdpCopyMemoryChunks((ULONG_PTR)(Src), Dst, Size, 0, \ MMDBG_COPY_UNSAFE, Done) // Write memory from a trusted buffer through an untrusted pointer. #define KdpCopyToPtr(Dst, Src, Size, Done) \ KdpCopyMemoryChunks((ULONG_PTR)(Dst), Src, Size, 0, \ MMDBG_COPY_WRITE | MMDBG_COPY_UNSAFE, Done) ULONG KdpReceivePacket ( IN ULONG ExpectedPacketType, OUT PSTRING MessageHeader, OUT PSTRING MessageData, OUT PULONG DataLength ); VOID KdpSetContextState( IN OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange, IN PCONTEXT ContextRecord ); VOID KdpSetStateChange( IN OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN BOOLEAN SecondChance ); VOID KdpGetStateChange( IN PDBGKD_MANIPULATE_STATE64 ManipulateState, IN PCONTEXT ContextRecord ); VOID KdpSendPacket ( IN ULONG PacketType, IN PSTRING MessageHeader, IN PSTRING MessageData OPTIONAL ); BOOLEAN KdpStub ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChance ); BOOLEAN KdpTrap ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord64, IN PCONTEXT ContextRecord, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChance ); BOOLEAN KdpSwitchProcessor ( IN PEXCEPTION_RECORD ExceptionRecord, IN OUT PCONTEXT ContextRecord, IN BOOLEAN SecondChance ); BOOLEAN KdpReportExceptionStateChange ( IN PEXCEPTION_RECORD ExceptionRecord, IN OUT PCONTEXT ContextRecord, IN BOOLEAN SecondChance ); BOOLEAN KdpReportLoadSymbolsStateChange ( IN PSTRING PathName, IN PKD_SYMBOLS_INFO SymbolInfo, IN BOOLEAN UnloadSymbols, IN OUT PCONTEXT ContextRecord ); VOID KdpReportCommandStringStateChange ( IN PSTRING Name, IN PSTRING Command, IN OUT PCONTEXT ContextRecord ); KCONTINUE_STATUS KdpSendWaitContinue( IN ULONG PacketType, IN PSTRING MessageHeader, IN PSTRING MessageData OPTIONAL, IN OUT PCONTEXT ContextRecord ); VOID KdpReadVirtualMemory( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); #if 0 VOID KdpReadVirtualMemory64( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); #endif VOID KdpWriteVirtualMemory( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); #if 0 VOID KdpWriteVirtualMemory64( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); #endif VOID KdpReadPhysicalMemory( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpWritePhysicalMemory( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpCheckLowMemory( IN PDBGKD_MANIPULATE_STATE64 m ); VOID KdpGetContext( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpSetContext( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpWriteBreakpoint( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpRestoreBreakpoint( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpReadControlSpace( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpWriteControlSpace( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpReadIoSpace( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpWriteIoSpace( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpReadIoSpaceExtended ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpWriteIoSpaceExtended ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpReadMachineSpecificRegister( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpWriteMachineSpecificRegister( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpGetBusData ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpSetBusData ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ); VOID KdpSendTraceData( PSTRING Data ); VOID KdpSuspendBreakpoint ( ULONG Handle ); VOID KdpSuspendAllBreakpoints ( VOID ); VOID KdpRestoreAllBreakpoints ( VOID ); VOID KdpTimeSlipDpcRoutine ( PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2 ); VOID KdpTimeSlipWork ( IN PVOID Context ); // // Routines shared between the debugger and // NtSystemDebugControl. // VOID KdpSysGetVersion( PDBGKD_GET_VERSION64 Version ); NTSTATUS KdpSysReadControlSpace( ULONG Processor, ULONG64 Address, PVOID Buffer, ULONG Request, PULONG Actual ); NTSTATUS KdpSysWriteControlSpace( ULONG Processor, ULONG64 Address, PVOID Buffer, ULONG Request, PULONG Actual ); NTSTATUS KdpSysReadIoSpace( INTERFACE_TYPE InterfaceType, ULONG BusNumber, ULONG AddressSpace, ULONG64 Address, PVOID Buffer, ULONG Request, PULONG Actual ); NTSTATUS KdpSysWriteIoSpace( INTERFACE_TYPE InterfaceType, ULONG BusNumber, ULONG AddressSpace, ULONG64 Address, PVOID Buffer, ULONG Request, PULONG Actual ); NTSTATUS KdpSysReadMsr( ULONG Msr, PULONG64 Data ); NTSTATUS KdpSysWriteMsr( ULONG Msr, PULONG64 Data ); NTSTATUS KdpSysReadBusData( BUS_DATA_TYPE BusDataType, ULONG BusNumber, ULONG SlotNumber, ULONG Address, PVOID Buffer, ULONG Request, PULONG Actual ); NTSTATUS KdpSysWriteBusData( BUS_DATA_TYPE BusDataType, ULONG BusNumber, ULONG SlotNumber, ULONG Address, PVOID Buffer, ULONG Request, PULONG Actual ); NTSTATUS KdpSysCheckLowMemory( VOID ); // // Define dummy prototype so the address of the standard breakpoint instruction // can be captured. // // N.B. This function is NEVER called. // VOID RtlpBreakWithStatusInstruction ( VOID ); // // Define external references. // #define KDP_MESSAGE_BUFFER_SIZE 4096 extern BREAKPOINT_ENTRY KdpBreakpointTable[BREAKPOINT_TABLE_SIZE]; extern KD_REMOTE_FILE KdpRemoteFiles[KD_MAX_REMOTE_FILES]; extern KSPIN_LOCK KdpDebuggerLock; extern PKDEBUG_ROUTINE KiDebugRoutine; extern PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine; extern KDP_BREAKPOINT_TYPE KdpBreakpointInstruction; extern UCHAR DECLSPEC_ALIGN(8) KdpMessageBuffer[KDP_MESSAGE_BUFFER_SIZE]; extern UCHAR KdpPathBuffer[KDP_MESSAGE_BUFFER_SIZE]; extern BOOLEAN KdpOweBreakpoint; extern LARGE_INTEGER KdPerformanceCounterRate; extern LARGE_INTEGER KdTimerStart; extern LARGE_INTEGER KdTimerStop; extern LARGE_INTEGER KdTimerDifference; extern ULONG KdComponentTableSize; extern PULONG KdComponentTable[]; extern BOOLEAN BreakpointsSuspended; extern LIST_ENTRY KdpDebuggerDataListHead; typedef struct { ULONG64 Addr; // pc address of breakpoint ULONG Flags; // Flags bits ULONG Calls; // # of times traced routine called ULONG CallsLastCheck; // # of calls at last periodic (1s) check ULONG MaxCallsPerPeriod; ULONG MinInstructions; // largest number of instructions for 1 call ULONG MaxInstructions; // smallest # of instructions for 1 call ULONG TotalInstructions; // total instructions for all calls ULONG Handle; // handle in (regular) bpt table PVOID Thread; // Thread that's skipping this BP ULONG64 ReturnAddress; // return address (if not COUNTONLY) } DBGKD_INTERNAL_BREAKPOINT, *PDBGKD_INTERNAL_BREAKPOINT; extern DBGKD_INTERNAL_BREAKPOINT KdpInternalBPs[DBGKD_MAX_INTERNAL_BREAKPOINTS]; extern ULONG_PTR KdpCurrentSymbolStart; extern ULONG_PTR KdpCurrentSymbolEnd; extern LONG KdpNextCallLevelChange; extern ULONG_PTR KdSpecialCalls[]; extern ULONG KdNumberOfSpecialCalls; extern ULONG_PTR InitialSP; extern ULONG KdpNumInternalBreakpoints; extern KTIMER InternalBreakpointTimer; extern KDPC InternalBreakpointCheckDpc; extern BOOLEAN KdpPortLocked; extern LARGE_INTEGER KdpTimeEntered; extern DBGKD_TRACE_DATA TraceDataBuffer[]; extern ULONG TraceDataBufferPosition; extern TRACE_DATA_SYM TraceDataSyms[]; extern UCHAR NextTraceDataSym; extern UCHAR NumTraceDataSyms; extern ULONG IntBPsSkipping; extern BOOLEAN WatchStepOver; extern BOOLEAN BreakPointTimerStarted; extern PVOID WSOThread; extern ULONG_PTR WSOEsp; extern ULONG WatchStepOverHandle; extern ULONG_PTR WatchStepOverBreakAddr; extern BOOLEAN WatchStepOverSuspended; extern ULONG InstructionsTraced; extern BOOLEAN SymbolRecorded; extern LONG CallLevelChange; extern LONG_PTR oldpc; extern BOOLEAN InstrCountInternal; extern BOOLEAN BreakpointsSuspended; extern BOOLEAN KdpControlCPressed; extern KD_CONTEXT KdpContext; extern KDP_BREAKPOINT_TYPE KdpBreakpointInstruction; extern UCHAR KdPrintCircularBuffer[KDPRINTBUFFERSIZE]; extern PUCHAR KdPrintWritePointer; extern ULONG KdPrintRolloverCount; extern KSPIN_LOCK KdpPrintSpinLock; extern KSPIN_LOCK KdpDataSpinLock; extern LIST_ENTRY KdpDebuggerDataListHead; extern DBGKD_GET_VERSION64 KdVersionBlock; extern KDDEBUGGER_DATA64 KdDebuggerDataBlock; extern KDPC KdpTimeSlipDpc; extern WORK_QUEUE_ITEM KdpTimeSlipWorkItem; extern KTIMER KdpTimeSlipTimer; extern ULONG KdpTimeSlipPending; extern KSPIN_LOCK KdpTimeSlipEventLock; extern PVOID KdpTimeSlipEvent; extern BOOLEAN KdpDebuggerStructuresInitialized; extern ULONG KdEnteredDebugger; // // !search support (page hit database) // // // Hit database where search results are stored (kddata.c). // The debugger extensions know how to extract the information // from here. // // Note that the size of the hit database is large enough to // accomodate any searches because the !search extension works // in batches of pages < PAGE_SIZE and for every page we register only // one hit. // #define SEARCH_PAGE_HIT_DATABASE_SIZE PAGE_SIZE extern PFN_NUMBER KdpSearchPageHits[SEARCH_PAGE_HIT_DATABASE_SIZE]; extern ULONG KdpSearchPageHitOffsets[SEARCH_PAGE_HIT_DATABASE_SIZE]; extern ULONG KdpSearchPageHitIndex; // // Set to true while a physical memory search is in progress. // Reset at the end of the search. This is done in the debugger // extension and it is a flag used by KdpCheckLowMemory to get // onto a different code path. // extern LOGICAL KdpSearchInProgress; // // These variables store the current state of the search operation. // They can be used to restore an interrupted search. // extern PFN_NUMBER KdpSearchStartPageFrame; extern PFN_NUMBER KdpSearchEndPageFrame; extern ULONG_PTR KdpSearchAddressRangeStart; extern ULONG_PTR KdpSearchAddressRangeEnd; extern PFN_NUMBER KdpSearchPfnValue; // // Checkpoint variable used to test if we have the right // debugging symbols. // #define KDP_SEARCH_SYMBOL_CHECK 0xABCDDCBA extern ULONG KdpSearchCheckPoint; // // Page search flags // #define KDP_SEARCH_ALL_OFFSETS_IN_PAGE 0x0001 // // Private procedure prototypes // BOOLEAN KdpAcquireBreakpoint( IN ULONG Number ); VOID KdpInitCom( VOID ); VOID KdpPortLock( VOID ); VOID KdpPortUnlock( VOID ); BOOLEAN KdpPollBreakInWithPortLock( VOID ); USHORT KdpReceivePacketLeader ( IN ULONG PacketType, OUT PULONG PacketLeader ); #if DBG #include #define DPRINT(s) KdpDprintf s VOID KdpDprintf( IN PCHAR f, ... ); #else #define DPRINT(s) #endif