2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdinit.c
5 * PURPOSE: Kernel Debugger Initializtion
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
12 #include <internal/debug.h>
14 /* VARIABLES ***************************************************************/
16 BOOLEAN KdDebuggerEnabled
= FALSE
;
17 BOOLEAN KdEnteredDebugger
= FALSE
;
18 BOOLEAN KdDebuggerNotPresent
= TRUE
;
19 BOOLEAN KiEnableTimerWatchdog
= FALSE
;
20 BOOLEAN KdBreakAfterSymbolLoad
= FALSE
;
21 BOOLEAN KdpBreakPending
;
22 BOOLEAN KdPitchDebugger
= TRUE
;
23 VOID STDCALL
PspDumpThreads(BOOLEAN SystemThreads
);
30 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
31 KD_COMPONENT_DATA KdComponentTable
[MAX_KD_COMPONENT_TABLE_ENTRIES
];
32 ULONG KdComponentTableEntries
= 0;
34 /* PRIVATE FUNCTIONS *********************************************************/
38 KdpServiceDispatcher(ULONG Service
,
46 case BREAKPOINT_PRINT
: /* DbgPrint */
47 Result
= KdpPrintString(Buffer1
, Buffer1Length
);
51 case TAG('R', 'o', 's', ' '): /* ROS-INTERNAL */
53 switch ((ULONG
)Buffer1
)
55 case DumpNonPagedPool
:
56 MiDebugDumpNonPagedPool(FALSE
);
60 KEBUGCHECK(MANUALLY_INITIATED_CRASH
);
63 case DumpNonPagedPoolStats
:
64 MiDebugDumpNonPagedPoolStats(FALSE
);
67 case DumpNewNonPagedPool
:
68 MiDebugDumpNonPagedPool(TRUE
);
71 case DumpNewNonPagedPoolStats
:
72 MiDebugDumpNonPagedPoolStats(TRUE
);
80 PspDumpThreads(FALSE
);
93 HalDisplayString ("Invalid debug service call!\n");
102 KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame
,
103 IN PKEXCEPTION_FRAME ExceptionFrame
,
104 IN PEXCEPTION_RECORD ExceptionRecord
,
106 IN KPROCESSOR_MODE PreviousMode
,
107 IN BOOLEAN SecondChance
)
109 KD_CONTINUE_TYPE Return
;
110 ULONG ExceptionCommand
= ExceptionRecord
->ExceptionInformation
[0];
115 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
116 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
117 (ExceptionRecord
->NumberParameters
> 0) &&
118 ((ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
) ||
119 (ExceptionCommand
== BREAKPOINT_UNLOAD_SYMBOLS
) ||
120 (ExceptionCommand
== BREAKPOINT_COMMAND_STRING
) ||
121 (ExceptionCommand
== BREAKPOINT_PRINT
)))
123 /* Check if this is a debug print */
124 if (ExceptionCommand
== BREAKPOINT_PRINT
)
126 /* Print the string */
127 KdpServiceDispatcher(BREAKPOINT_PRINT
,
128 (PVOID
)ExceptionRecord
->ExceptionInformation
[1],
129 ExceptionRecord
->ExceptionInformation
[2]);
131 else if (ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
)
133 /* Load symbols. Currently implemented only for KDBG! */
134 KDB_SYMBOLFILE_HOOK((PANSI_STRING
)ExceptionRecord
->ExceptionInformation
[1],
135 (PKD_SYMBOLS_INFO
)ExceptionRecord
->ExceptionInformation
[2]);
138 /* This we can handle: simply bump EIP */
145 /* Get out of here if the Debugger isn't connected */
146 if (KdDebuggerNotPresent
) return FALSE
;
148 /* Save old EIP value */
150 EipOld
= Context
->Eip
;
153 /* Call KDBG if available */
154 Return
= KdbEnterDebuggerException(ExceptionRecord
,
160 /* Bump EIP over int 3 if debugger did not already change it */
161 if (ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
)
164 if (Context
->Eip
== EipOld
)
167 /* We simulate the original behaviour when KDBG is turned off.
168 Return var is set to kdHandleException, thus we always return FALSE */
170 Context
->Eip
= EipOld
;
175 /* Convert return to BOOLEAN */
176 if (Return
== kdContinue
) return TRUE
;
182 KdpCallGdb(IN PKTRAP_FRAME TrapFrame
,
183 IN PEXCEPTION_RECORD ExceptionRecord
,
186 KD_CONTINUE_TYPE Return
= kdDoNotHandleException
;
188 /* Get out of here if the Debugger isn't connected */
189 if (KdDebuggerNotPresent
) return FALSE
;
192 * Right now, the GDB wrapper seems to handle exceptions differntly
193 * from KDGB and both are called at different times, while the GDB
194 * one is only called once and that's it. I don't really have the knowledge
195 * to fix the GDB stub, so until then, we'll be using this hack
197 if (WrapperInitRoutine
)
199 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
204 /* Convert return to BOOLEAN */
205 if (Return
== kdContinue
) return TRUE
;
209 /* PUBLIC FUNCTIONS *********************************************************/
216 KdDisableDebugger(VOID
)
221 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
223 /* TODO: Disable any breakpoints */
225 /* Disable the Debugger */
226 KdDebuggerEnabled
= FALSE
;
229 KeLowerIrql(OldIrql
);
232 return STATUS_SUCCESS
;
240 KdEnableDebugger(VOID
)
245 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
247 /* TODO: Re-enable any breakpoints */
249 /* Enable the Debugger */
250 KdDebuggerEnabled
= TRUE
;
253 KeLowerIrql(OldIrql
);
256 return STATUS_SUCCESS
;
266 return KdpBreakPending
;
274 KdPowerTransition(ULONG PowerState
)
277 return STATUS_NOT_IMPLEMENTED
;
285 KdChangeOption(IN KD_OPTION Option
,
286 IN ULONG InBufferLength OPTIONAL
,
288 IN ULONG OutBufferLength OPTIONAL
,
290 OUT PULONG OutBufferRequiredLength OPTIONAL
)
293 return STATUS_NOT_IMPLEMENTED
;
299 NtQueryDebugFilterState(IN ULONG ComponentId
,
304 /* convert Level to mask if it isn't already one */
308 for ( i
= 0; i
< KdComponentTableEntries
; i
++ )
310 if ( ComponentId
== KdComponentTable
[i
].ComponentId
)
312 if ( Level
& KdComponentTable
[i
].Level
)
322 NtSetDebugFilterState(IN ULONG ComponentId
,
327 for ( i
= 0; i
< KdComponentTableEntries
; i
++ )
329 if ( ComponentId
== KdComponentTable
[i
].ComponentId
)
332 if ( i
== KdComponentTableEntries
)
334 if ( i
== MAX_KD_COMPONENT_TABLE_ENTRIES
)
335 return STATUS_INVALID_PARAMETER_1
;
336 ++KdComponentTableEntries
;
337 KdComponentTable
[i
].ComponentId
= ComponentId
;
338 KdComponentTable
[i
].Level
= 0;
341 /* Convert level to mask, if needed */
346 KdComponentTable
[i
].Level
|= Level
;
348 KdComponentTable
[i
].Level
&= ~Level
;
349 return STATUS_SUCCESS
;
357 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
358 IN PVOID InputBuffer
,
359 IN ULONG InputBufferLength
,
360 OUT PVOID OutputBuffer
,
361 IN ULONG OutputBufferLength
,
362 IN OUT PULONG ReturnLength
,
363 IN KPROCESSOR_MODE PreviousMode
)
366 return KdpServiceDispatcher(Command
, InputBuffer
, InputBufferLength
);
369 PKDEBUG_ROUTINE KiDebugRoutine
= KdpEnterDebuggerException
;