ReactOS 0.4.15-dev-8241-g63935f8
kdtrap.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdtrap.c
5 * PURPOSE: KD64 Trap Handlers
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
8 */
9
10/* INCLUDES ******************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
16//
17// Retrieves the ComponentId and Level for BREAKPOINT_PRINT
18// and OutputString and OutputStringLength for BREAKPOINT_PROMPT.
19//
20#if defined(_X86_)
21
22//
23// EBX/EDI on x86
24//
25#define KdpGetParameterThree(Context) ((Context)->Ebx)
26#define KdpGetParameterFour(Context) ((Context)->Edi)
27
28#elif defined(_AMD64_)
29
30//
31// R8/R9 on AMD64
32//
33#define KdpGetParameterThree(Context) ((Context)->R8)
34#define KdpGetParameterFour(Context) ((Context)->R9)
35
36#elif defined(_ARM_)
37
38//
39// R3/R4 on ARM
40//
41#define KdpGetParameterThree(Context) ((Context)->R3)
42#define KdpGetParameterFour(Context) ((Context)->R4)
43
44#else
45#error Unsupported Architecture
46#endif
47
48/* FUNCTIONS *****************************************************************/
49
53 IN PKEXCEPTION_FRAME ExceptionFrame,
54 IN PEXCEPTION_RECORD ExceptionRecord,
57 IN BOOLEAN SecondChanceException)
58{
60 PKPRCB Prcb;
62
63 /*
64 * Determine whether to pass the exception to the debugger.
65 * First, check if this is a "debug exception", meaning breakpoint
66 * (including debug service), single step and assertion failure exceptions.
67 */
68 ExceptionCode = ExceptionRecord->ExceptionCode;
72 {
73 /* This is a debug exception; we always pass them to the debugger */
74 }
76 {
77 /*
78 * Not a debug exception, but the stop-on-exception flag is set,
79 * meaning the debugger requests that we pass it first chance
80 * exceptions. However, some exceptions are always passed to the
81 * exception handler first, namely exceptions with a code that isn't
82 * an error or warning code, and also exceptions with the special
83 * STATUS_PORT_DISCONNECTED code (an error code).
84 */
85 if ((SecondChanceException == FALSE) &&
88 {
89 /* Let the exception handler, if any, try to handle it */
90 return FALSE;
91 }
92 }
93 else if (SecondChanceException == FALSE)
94 {
95 /*
96 * This isn't a debug exception and the stop-on-exception flag isn't set,
97 * so don't bother handling it
98 */
99 return FALSE;
100 }
101
102 /* Enter the debugger */
103 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
104
105 /*
106 * Get the KPRCB and save the CPU Control State manually instead of
107 * using KiSaveProcessorState, since we already have a valid CONTEXT.
108 */
109 Prcb = KeGetCurrentPrcb();
113 sizeof(CONTEXT));
114
115 /* Report the new state */
116 Handled = KdpReportExceptionStateChange(ExceptionRecord,
117 &Prcb->ProcessorState.
118 ContextFrame,
119 SecondChanceException);
120
121 /* Now restore the processor state, manually again. */
124 sizeof(CONTEXT));
126
127 /* Exit the debugger and clear the CTRL-C state */
130 return Handled;
131}
132
134NTAPI
136 IN PKEXCEPTION_FRAME ExceptionFrame,
137 IN PEXCEPTION_RECORD ExceptionRecord,
140 IN BOOLEAN SecondChanceException)
141{
143 ULONG_PTR ProgramCounter;
145 NTSTATUS ReturnStatus;
147
148 /*
149 * Check if we got a STATUS_BREAKPOINT with a SubID for Print, Prompt or
150 * Load/Unload symbols. Make sure it isn't a software breakpoints as those
151 * are handled by KdpReport.
152 */
153 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
154 (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK))
155 {
156 /* Save Program Counter */
157 ProgramCounter = KeGetContextPc(ContextRecord);
158
159 /* Check what kind of operation was requested from us */
160 Unload = FALSE;
161 switch (ExceptionRecord->ExceptionInformation[0])
162 {
163 /* DbgPrint */
164 case BREAKPOINT_PRINT:
165
166 /* Call the worker routine */
167 ReturnStatus = KdpPrint((ULONG)KdpGetParameterThree(ContextRecord),
168 (ULONG)KdpGetParameterFour(ContextRecord),
169 (PCHAR)ExceptionRecord->ExceptionInformation[1],
170 (USHORT)ExceptionRecord->ExceptionInformation[2],
172 TrapFrame,
173 ExceptionFrame,
174 &Handled);
175
176 /* Update the return value for the caller */
178 break;
179
180 /* DbgPrompt */
182
183 /* Call the worker routine */
184 ReturnLength = KdpPrompt((PCHAR)ExceptionRecord->ExceptionInformation[1],
185 (USHORT)ExceptionRecord->ExceptionInformation[2],
186 (PCHAR)KdpGetParameterThree(ContextRecord),
187 (USHORT)KdpGetParameterFour(ContextRecord),
189 TrapFrame,
190 ExceptionFrame);
191 Handled = TRUE;
192
193 /* Update the return value for the caller */
195 break;
196
197 /* DbgUnLoadImageSymbols */
199
200 /* Drop into the load case below, with the unload parameter */
201 Unload = TRUE;
202
203 /* DbgLoadImageSymbols */
205
206 /* Call the worker routine */
207 KdpSymbol((PSTRING)ExceptionRecord->ExceptionInformation[1],
208 (PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2],
209 Unload,
212 TrapFrame,
213 ExceptionFrame);
214 Handled = TRUE;
215 break;
216
217 /* DbgCommandString */
219
220 /* Call the worker routine */
221 KdpCommandString((PSTRING)ExceptionRecord->ExceptionInformation[1],
222 (PSTRING)ExceptionRecord->ExceptionInformation[2],
225 TrapFrame,
226 ExceptionFrame);
227 Handled = TRUE;
228 break;
229
230 /* Anything else, do nothing */
231 default:
232
233 /* Invalid debug service! Don't handle this! */
234 Handled = FALSE;
235 break;
236 }
237
238 /*
239 * If the PC was not updated, we'll increment it ourselves so execution
240 * continues past the breakpoint.
241 */
242 if (ProgramCounter == KeGetContextPc(ContextRecord))
243 {
244 /* Update it */
246 ProgramCounter + KD_BREAKPOINT_SIZE);
247 }
248 }
249 else
250 {
251 /* Call the worker routine */
252 Handled = KdpReport(TrapFrame,
253 ExceptionFrame,
254 ExceptionRecord,
257 SecondChanceException);
258 }
259
260 /* Return TRUE or FALSE to caller */
261 return Handled;
262}
263
265NTAPI
267 IN PKEXCEPTION_FRAME ExceptionFrame,
268 IN PEXCEPTION_RECORD ExceptionRecord,
271 IN BOOLEAN SecondChanceException)
272{
273 ULONG_PTR ExceptionCommand;
274
275 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
276 ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
277 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
278 (ExceptionRecord->NumberParameters > 0) &&
279 ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
280 (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
281 (ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
282 (ExceptionCommand == BREAKPOINT_PRINT)))
283 {
284 /* This we can handle: simply bump the Program Counter */
287 return TRUE;
288 }
289 else if (KdPitchDebugger)
290 {
291 /* There's no debugger, fail. */
292 return FALSE;
293 }
294 else if ((KdAutoEnableOnEvent) &&
299 {
300 /* Debugging was Auto-Enabled. We can now send this to KD. */
301 return KdpTrap(TrapFrame,
302 ExceptionFrame,
303 ExceptionRecord,
306 SecondChanceException);
307 }
308 else
309 {
310 /* FIXME: All we can do in this case is trace this exception */
311 return FALSE;
312 }
313}
314
316NTAPI
320{
321#ifdef _WINKD_
322 /*
323 * Determine if this is a valid debug service call and make sure that
324 * it isn't a software breakpoint
325 */
326 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
327 (ExceptionRecord->NumberParameters > 0) &&
328 (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK))
329 {
330 /* Then we have to handle it */
331 return TRUE;
332 }
333 else
334 {
335 /* We don't have to handle it */
336 return FALSE;
337 }
338#else
339 /* KDBG has its own mechanism for ignoring user mode exceptions */
340 return FALSE;
341#endif
342}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1774
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
Definition: floppy.c:377
#define FLG_STOP_ON_EXCEPTION
Definition: pstypes.h:56
VOID NTAPI KdpCommandString(IN PSTRING NameString, IN PSTRING CommandString, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdprint.c:224
BOOLEAN KdPreviouslyEnabled
Definition: kddata.c:86
BOOLEAN KdPitchDebugger
Definition: kddata.c:80
BOOLEAN NTAPI KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord, IN OUT PCONTEXT Context, IN BOOLEAN SecondChanceException)
Definition: kdapi.c:1755
NTSTATUS NTAPI KdpPrint(_In_ ULONG ComponentId, _In_ ULONG Level, _In_reads_bytes_(Length) PCHAR String, _In_ USHORT Length, _In_ KPROCESSOR_MODE PreviousMode, _In_ PKTRAP_FRAME TrapFrame, _In_ PKEXCEPTION_FRAME ExceptionFrame, _Out_ PBOOLEAN Handled)
Definition: kdprint.c:445
VOID NTAPI KdpSymbol(IN PSTRING DllPath, IN PKD_SYMBOLS_INFO SymbolInfo, IN BOOLEAN Unload, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdprint.c:263
BOOLEAN NTAPI KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdapi.c:1902
VOID NTAPI KdExitDebugger(IN BOOLEAN Enable)
Definition: kdapi.c:1955
BOOLEAN KdpControlCPressed
Definition: kddata.c:68
VOID NTAPI KdpMoveMemory(_In_ PVOID Destination, _In_ PVOID Source, _In_ SIZE_T Length)
Definition: kdapi.c:27
USHORT NTAPI KdpPrompt(_In_reads_bytes_(PromptLength) PCHAR PromptString, _In_ USHORT PromptLength, _Out_writes_bytes_(MaximumResponseLength) PCHAR ResponseString, _In_ USHORT MaximumResponseLength, _In_ KPROCESSOR_MODE PreviousMode, _In_ PKTRAP_FRAME TrapFrame, _In_ PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdprint.c:304
BOOLEAN KdAutoEnableOnEvent
Definition: kddata.c:83
NTSTATUS NTAPI KdEnableDebugger(VOID)
Definition: kdapi.c:2161
BOOLEAN KdDebuggerEnabled
Definition: kddata.c:82
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)
Definition: kdtrap.c:135
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)
Definition: kdtrap.c:266
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)
Definition: kdtrap.c:52
BOOLEAN NTAPI KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode)
Definition: kdtrap.c:317
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
#define BREAKPOINT_PRINT
Definition: kdtypes.h:51
#define BREAKPOINT_COMMAND_STRING
Definition: kdtypes.h:55
#define BREAKPOINT_LOAD_SYMBOLS
Definition: kdtypes.h:53
#define BREAKPOINT_BREAK
Definition: kdtypes.h:50
#define BREAKPOINT_UNLOAD_SYMBOLS
Definition: kdtypes.h:54
#define BREAKPOINT_PROMPT
Definition: kdtypes.h:52
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:654
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
ULONG NtGlobalFlag
Definition: init.c:54
#define KD_BREAKPOINT_SIZE
Definition: ke.h:122
#define KeSetContextReturnRegister(Context, ReturnValue)
Definition: ke.h:43
#define KeSetContextPc(Context, ProgramCounter)
Definition: ke.h:34
#define KeGetContextPc(Context)
Definition: ke.h:31
VOID NTAPI KiRestoreProcessorControlState(IN PKPROCESSOR_STATE ProcessorState)
VOID NTAPI KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:576
#define STATUS_ASSERTION_FAILURE
Definition: ntstatus.h:960
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:185
#define STATUS_BREAKPOINT
Definition: ntstatus.h:184
#define STATUS_PORT_DISCONNECTED
Definition: ntstatus.h:291
unsigned short USHORT
Definition: pedump.c:61
KPROCESSOR_STATE ProcessorState
Definition: ketypes.h:663
CONTEXT ContextFrame
Definition: ketypes.h:616
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ BOOLEAN Handled
Definition: ketypes.h:349
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103