2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdinit.c
5 * PURPOSE: Kernel Debugger Initialization
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
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
= FALSE
;
22 BOOLEAN KdPitchDebugger
= TRUE
;
23 BOOLEAN KdIgnoreUmExceptions
= FALSE
;
24 VOID NTAPI
PspDumpThreads(BOOLEAN SystemThreads
);
31 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
32 KD_COMPONENT_DATA KdComponentTable
[MAX_KD_COMPONENT_TABLE_ENTRIES
];
33 ULONG KdComponentTableEntries
= 0;
35 ULONG Kd_DEFAULT_MASK
= 1 << DPFLTR_ERROR_LEVEL
;
37 /* PRIVATE FUNCTIONS *********************************************************/
41 KdpServiceDispatcher(ULONG Service
,
49 case BREAKPOINT_PRINT
: /* DbgPrint */
50 Result
= KdpPrintString(Buffer1
, Buffer1Length
);
54 case ' soR': /* ROS-INTERNAL */
56 switch ((ULONG_PTR
)Buffer1
)
59 KeBugCheck(MANUALLY_INITIATED_CRASH
);
67 PspDumpThreads(FALSE
);
74 case ThatsWhatSheSaid
:
84 /* Special case for stack frame dumps */
87 KeRosDumpStackFrames((PULONG
)Buffer1
, Buffer1Length
);
92 HalDisplayString ("Invalid debug service call!\n");
101 KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame
,
102 IN PKEXCEPTION_FRAME ExceptionFrame
,
103 IN PEXCEPTION_RECORD ExceptionRecord
,
105 IN KPROCESSOR_MODE PreviousMode
,
106 IN BOOLEAN SecondChance
)
108 KD_CONTINUE_TYPE Return
= kdHandleException
;
109 ULONG ExceptionCommand
= ExceptionRecord
->ExceptionInformation
[0];
111 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
112 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
113 (ExceptionRecord
->NumberParameters
> 0) &&
114 ((ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
) ||
115 (ExceptionCommand
== BREAKPOINT_UNLOAD_SYMBOLS
) ||
116 (ExceptionCommand
== BREAKPOINT_COMMAND_STRING
) ||
117 (ExceptionCommand
== BREAKPOINT_PRINT
)))
119 /* Check if this is a debug print */
120 if (ExceptionCommand
== BREAKPOINT_PRINT
)
122 /* Print the string */
123 KdpServiceDispatcher(BREAKPOINT_PRINT
,
124 (PVOID
)ExceptionRecord
->ExceptionInformation
[1],
125 ExceptionRecord
->ExceptionInformation
[2]);
128 KeSetContextReturnRegister(Context
, STATUS_SUCCESS
);
130 else if (ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
)
133 PLDR_DATA_TABLE_ENTRY LdrEntry
;
135 /* Load symbols. Currently implemented only for KDBG! */
136 if(KdbpSymFindModule(((PKD_SYMBOLS_INFO
)ExceptionRecord
->ExceptionInformation
[2])->BaseOfDll
, NULL
, -1, &LdrEntry
))
137 KdbSymProcessSymbols(LdrEntry
);
141 /* This we can handle: simply bump the Program Counter */
142 KeSetContextPc(Context
, KeGetContextPc(Context
) + KD_BREAKPOINT_SIZE
);
146 /* Get out of here if the Debugger isn't connected */
147 if (KdDebuggerNotPresent
) return FALSE
;
150 /* Call KDBG if available */
151 Return
= KdbEnterDebuggerException(ExceptionRecord
,
157 if (WrapperInitRoutine
)
160 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
164 #endif /* not KDBG */
166 /* Debugger didn't handle it, please handle! */
167 if (Return
== kdHandleException
) return FALSE
;
169 /* Debugger handled it */
175 KdpCallGdb(IN PKTRAP_FRAME TrapFrame
,
176 IN PEXCEPTION_RECORD ExceptionRecord
,
179 KD_CONTINUE_TYPE Return
= kdDoNotHandleException
;
181 /* Get out of here if the Debugger isn't connected */
182 if (KdDebuggerNotPresent
) return FALSE
;
185 * Right now, the GDB wrapper seems to handle exceptions differntly
186 * from KDGB and both are called at different times, while the GDB
187 * one is only called once and that's it. I don't really have the knowledge
188 * to fix the GDB stub, so until then, we'll be using this hack
190 if (WrapperInitRoutine
)
192 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
197 /* Debugger didn't handle it, please handle! */
198 if (Return
== kdHandleException
) return FALSE
;
200 /* Debugger handled it */
206 KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord
,
208 IN KPROCESSOR_MODE PreviousMode
)
210 /* KDBG has its own mechanism for ignoring user mode exceptions */
214 /* PUBLIC FUNCTIONS *********************************************************/
221 KdRefreshDebuggerNotPresent(VOID
)
225 /* Just return whatever was set previously -- FIXME! */
226 return KdDebuggerNotPresent
;
234 KdDisableDebugger(VOID
)
239 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
241 /* TODO: Disable any breakpoints */
243 /* Disable the Debugger */
244 KdDebuggerEnabled
= FALSE
;
247 KeLowerIrql(OldIrql
);
250 return STATUS_SUCCESS
;
258 KdEnableDebugger(VOID
)
263 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
265 /* TODO: Re-enable any breakpoints */
267 /* Enable the Debugger */
268 KdDebuggerEnabled
= TRUE
;
271 KeLowerIrql(OldIrql
);
274 return STATUS_SUCCESS
;
284 return KdpBreakPending
;
292 KdPowerTransition(ULONG PowerState
)
295 return STATUS_NOT_IMPLEMENTED
;
303 KdChangeOption(IN KD_OPTION Option
,
304 IN ULONG InBufferLength OPTIONAL
,
306 IN ULONG OutBufferLength OPTIONAL
,
308 OUT PULONG OutBufferRequiredLength OPTIONAL
)
311 return STATUS_NOT_IMPLEMENTED
;
317 NtQueryDebugFilterState(IN ULONG ComponentId
,
322 /* Convert Level to mask if it isn't already one */
326 /* Check if it is not the default component */
327 if (ComponentId
!= DPFLTR_DEFAULT_ID
)
329 /* No, search for an existing entry in the table */
330 for (i
= 0; i
< KdComponentTableEntries
; i
++)
332 /* Check if it is the right component */
333 if (ComponentId
== KdComponentTable
[i
].ComponentId
)
335 /* Check if mask are matching */
336 return (Level
& KdComponentTable
[i
].Level
) != 0;
341 /* Entry not found in the table, use default mask */
342 return (Level
& Kd_DEFAULT_MASK
) != 0;
347 NtSetDebugFilterState(IN ULONG ComponentId
,
353 /* Convert Level to mask if it isn't already one */
356 Level
&= ~DPFLTR_MASK
;
358 /* Check if it is the default component */
359 if (ComponentId
== DPFLTR_DEFAULT_ID
)
361 /* Yes, modify the default mask */
363 Kd_DEFAULT_MASK
|= Level
;
365 Kd_DEFAULT_MASK
&= ~Level
;
367 return STATUS_SUCCESS
;
370 /* Search for an existing entry */
371 for (i
= 0; i
< KdComponentTableEntries
; i
++ )
373 if (ComponentId
== KdComponentTable
[i
].ComponentId
)
377 /* Check if we have found an existing entry */
378 if (i
== KdComponentTableEntries
)
380 /* Check if we have enough space in the table */
381 if (i
== MAX_KD_COMPONENT_TABLE_ENTRIES
)
382 return STATUS_INVALID_PARAMETER_1
;
384 /* Add a new entry */
385 ++KdComponentTableEntries
;
386 KdComponentTable
[i
].ComponentId
= ComponentId
;
387 KdComponentTable
[i
].Level
= Kd_DEFAULT_MASK
;
390 /* Update entry table */
392 KdComponentTable
[i
].Level
|= Level
;
394 KdComponentTable
[i
].Level
&= ~Level
;
396 return STATUS_SUCCESS
;
404 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
405 IN PVOID InputBuffer
,
406 IN ULONG InputBufferLength
,
407 OUT PVOID OutputBuffer
,
408 IN ULONG OutputBufferLength
,
409 IN OUT PULONG ReturnLength
,
410 IN KPROCESSOR_MODE PreviousMode
)
413 return KdpServiceDispatcher(Command
, InputBuffer
, InputBufferLength
);
416 PKDEBUG_ROUTINE KiDebugRoutine
= KdpEnterDebuggerException
;