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 KdBreakAfterSymbolLoad
= FALSE
;
20 BOOLEAN KdpBreakPending
= FALSE
;
21 BOOLEAN KdPitchDebugger
= TRUE
;
22 BOOLEAN KdIgnoreUmExceptions
= FALSE
;
23 KD_CONTEXT KdpContext
;
24 ULONG Kd_WIN2000_Mask
;
25 VOID NTAPI
PspDumpThreads(BOOLEAN SystemThreads
);
32 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
33 KD_COMPONENT_DATA KdComponentTable
[MAX_KD_COMPONENT_TABLE_ENTRIES
];
34 ULONG KdComponentTableEntries
= 0;
36 ULONG Kd_DEFAULT_MASK
= 1 << DPFLTR_ERROR_LEVEL
;
38 /* PRIVATE FUNCTIONS *********************************************************/
42 KdpServiceDispatcher(ULONG Service
,
50 case BREAKPOINT_PRINT
: /* DbgPrint */
51 Result
= KdpPrintString(Buffer1
, Buffer1Length
);
55 case ' soR': /* ROS-INTERNAL */
57 switch ((ULONG_PTR
)Buffer1
)
60 KeBugCheck(MANUALLY_INITIATED_CRASH
);
68 PspDumpThreads(FALSE
);
75 case ThatsWhatSheSaid
:
85 /* Special case for stack frame dumps */
88 KeRosDumpStackFrames((PULONG_PTR
)Buffer1
, Buffer1Length
);
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
= kdHandleException
;
110 ULONG ExceptionCommand
= ExceptionRecord
->ExceptionInformation
[0];
112 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
113 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
114 (ExceptionRecord
->NumberParameters
> 0) &&
115 ((ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
) ||
116 (ExceptionCommand
== BREAKPOINT_UNLOAD_SYMBOLS
) ||
117 (ExceptionCommand
== BREAKPOINT_COMMAND_STRING
) ||
118 (ExceptionCommand
== BREAKPOINT_PRINT
) ||
119 (ExceptionCommand
== BREAKPOINT_PROMPT
)))
121 /* Check if this is a debug print */
122 if (ExceptionCommand
== BREAKPOINT_PRINT
)
124 /* Print the string */
125 KdpServiceDispatcher(BREAKPOINT_PRINT
,
126 (PVOID
)ExceptionRecord
->ExceptionInformation
[1],
127 ExceptionRecord
->ExceptionInformation
[2]);
130 KeSetContextReturnRegister(Context
, STATUS_SUCCESS
);
133 else if (ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
)
135 PLDR_DATA_TABLE_ENTRY LdrEntry
;
137 /* Load symbols. Currently implemented only for KDBG! */
138 if(KdbpSymFindModule(((PKD_SYMBOLS_INFO
)ExceptionRecord
->ExceptionInformation
[2])->BaseOfDll
, NULL
, -1, &LdrEntry
))
139 KdbSymProcessSymbols(LdrEntry
);
141 else if (ExceptionCommand
== BREAKPOINT_PROMPT
)
145 USHORT OutStringLength
;
147 /* Get the response string and length */
149 OutString
= (LPSTR
)Context
->Ebx
;
150 OutStringLength
= (USHORT
)Context
->Edi
;
152 OutString
= (LPSTR
)Context
->Rbx
;
153 OutStringLength
= (USHORT
)Context
->Rdi
;
155 #error Unknown Architecture
159 ReturnValue
= KdpPrompt((LPSTR
)ExceptionRecord
->
160 ExceptionInformation
[1],
161 (USHORT
)ExceptionRecord
->
162 ExceptionInformation
[2],
166 /* Return the number of characters that we received */
168 Context
->Eax
= ReturnValue
;
170 Context
->Rax
= ReturnValue
;
172 #error Unknown Architecture
177 /* This we can handle: simply bump the Program Counter */
178 KeSetContextPc(Context
, KeGetContextPc(Context
) + KD_BREAKPOINT_SIZE
);
183 /* Check if this is an assertion failure */
184 if (ExceptionRecord
->ExceptionCode
== STATUS_ASSERTION_FAILURE
)
188 DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n",
189 (PVOID
)Context
->Eip
);
191 /* Bump EIP to the instruction following the int 2C and return */
196 DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n",
197 (PVOID
)Context
->Rip
);
199 /* Bump RIP to the instruction following the int 2C and return */
202 #error Unknown Architecture
208 /* Get out of here if the Debugger isn't connected */
209 if (KdDebuggerNotPresent
) return FALSE
;
212 /* Call KDBG if available */
213 Return
= KdbEnterDebuggerException(ExceptionRecord
,
219 if (WrapperInitRoutine
)
222 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
226 #endif /* not KDBG */
228 /* Debugger didn't handle it, please handle! */
229 if (Return
== kdHandleException
) return FALSE
;
231 /* Debugger handled it */
237 KdpCallGdb(IN PKTRAP_FRAME TrapFrame
,
238 IN PEXCEPTION_RECORD ExceptionRecord
,
241 KD_CONTINUE_TYPE Return
= kdDoNotHandleException
;
243 /* Get out of here if the Debugger isn't connected */
244 if (KdDebuggerNotPresent
) return FALSE
;
247 * Right now, the GDB wrapper seems to handle exceptions differntly
248 * from KDGB and both are called at different times, while the GDB
249 * one is only called once and that's it. I don't really have the knowledge
250 * to fix the GDB stub, so until then, we'll be using this hack
252 if (WrapperInitRoutine
)
254 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
259 /* Debugger didn't handle it, please handle! */
260 if (Return
== kdHandleException
) return FALSE
;
262 /* Debugger handled it */
268 KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord
,
270 IN KPROCESSOR_MODE PreviousMode
)
272 /* KDBG has its own mechanism for ignoring user mode exceptions */
276 /* PUBLIC FUNCTIONS *********************************************************/
283 KdRefreshDebuggerNotPresent(VOID
)
287 /* Just return whatever was set previously -- FIXME! */
288 return KdDebuggerNotPresent
;
296 KdDisableDebugger(VOID
)
301 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
303 /* TODO: Disable any breakpoints */
305 /* Disable the Debugger */
306 KdDebuggerEnabled
= FALSE
;
309 KeLowerIrql(OldIrql
);
312 return STATUS_SUCCESS
;
320 KdEnableDebugger(VOID
)
325 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
327 /* TODO: Re-enable any breakpoints */
329 /* Enable the Debugger */
330 KdDebuggerEnabled
= TRUE
;
333 KeLowerIrql(OldIrql
);
336 return STATUS_SUCCESS
;
346 return KdpBreakPending
;
354 KdPowerTransition(ULONG PowerState
)
357 return STATUS_NOT_IMPLEMENTED
;
365 KdChangeOption(IN KD_OPTION Option
,
366 IN ULONG InBufferLength OPTIONAL
,
368 IN ULONG OutBufferLength OPTIONAL
,
370 OUT PULONG OutBufferRequiredLength OPTIONAL
)
373 return STATUS_NOT_IMPLEMENTED
;
379 NtQueryDebugFilterState(IN ULONG ComponentId
,
384 /* Convert Level to mask if it isn't already one */
388 /* Check if it is not the default component */
389 if (ComponentId
!= DPFLTR_DEFAULT_ID
)
391 /* No, search for an existing entry in the table */
392 for (i
= 0; i
< KdComponentTableEntries
; i
++)
394 /* Check if it is the right component */
395 if (ComponentId
== KdComponentTable
[i
].ComponentId
)
397 /* Check if mask are matching */
398 return (Level
& KdComponentTable
[i
].Level
) ? TRUE
: FALSE
;
403 /* Entry not found in the table, use default mask */
404 return (Level
& Kd_DEFAULT_MASK
) ? TRUE
: FALSE
;
409 NtSetDebugFilterState(IN ULONG ComponentId
,
415 /* Convert Level to mask if it isn't already one */
418 Level
&= ~DPFLTR_MASK
;
420 /* Check if it is the default component */
421 if (ComponentId
== DPFLTR_DEFAULT_ID
)
423 /* Yes, modify the default mask */
425 Kd_DEFAULT_MASK
|= Level
;
427 Kd_DEFAULT_MASK
&= ~Level
;
429 return STATUS_SUCCESS
;
432 /* Search for an existing entry */
433 for (i
= 0; i
< KdComponentTableEntries
; i
++ )
435 if (ComponentId
== KdComponentTable
[i
].ComponentId
)
439 /* Check if we have found an existing entry */
440 if (i
== KdComponentTableEntries
)
442 /* Check if we have enough space in the table */
443 if (i
== MAX_KD_COMPONENT_TABLE_ENTRIES
)
444 return STATUS_INVALID_PARAMETER_1
;
446 /* Add a new entry */
447 ++KdComponentTableEntries
;
448 KdComponentTable
[i
].ComponentId
= ComponentId
;
449 KdComponentTable
[i
].Level
= Kd_DEFAULT_MASK
;
452 /* Update entry table */
454 KdComponentTable
[i
].Level
|= Level
;
456 KdComponentTable
[i
].Level
&= ~Level
;
458 return STATUS_SUCCESS
;
466 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
467 IN PVOID InputBuffer
,
468 IN ULONG InputBufferLength
,
469 OUT PVOID OutputBuffer
,
470 IN ULONG OutputBufferLength
,
471 IN OUT PULONG ReturnLength
,
472 IN KPROCESSOR_MODE PreviousMode
)
475 return KdpServiceDispatcher(Command
, InputBuffer
, InputBufferLength
);
478 PKDEBUG_ROUTINE KiDebugRoutine
= KdpEnterDebuggerException
;