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)
9 /* INCLUDES ******************************************************************/
15 /* FUNCTIONS *****************************************************************/
19 KdpReport(IN PKTRAP_FRAME TrapFrame
,
20 IN PKEXCEPTION_FRAME ExceptionFrame
,
21 IN PEXCEPTION_RECORD ExceptionRecord
,
22 IN PCONTEXT ContextRecord
,
23 IN KPROCESSOR_MODE PreviousMode
,
24 IN BOOLEAN SecondChanceException
)
26 BOOLEAN Entered
, Status
;
31 * Only go ahead with this if this is an INT3 or an INT1, or if the global
32 * flag forces us to call up the debugger on exception, or if this is a
33 * second chance exception which means it hasn't been handled by now.
35 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) ||
36 (ExceptionRecord
->ExceptionCode
== STATUS_SINGLE_STEP
) ||
37 (NtGlobalFlag
& FLG_STOP_ON_EXCEPTION
) ||
38 (SecondChanceException
))
41 * Also, unless this is a second chance exception, then do not call up
42 * the debugger if the debug port is disconnected or the exception code
45 if (!(SecondChanceException
) &&
46 ((ExceptionRecord
->ExceptionCode
== STATUS_PORT_DISCONNECTED
) ||
47 (NT_SUCCESS(ExceptionRecord
->ExceptionCode
))))
49 /* Return false to hide the exception */
53 /* Enter the debugger */
54 Entered
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
57 * Get the KPRCB and save the CPU Control State manually instead of
58 * using KiSaveProcessorState, since we already have a valid CONTEXT.
60 Prcb
= KeGetCurrentPrcb();
61 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
62 RtlCopyMemory(&Prcb
->ProcessorState
.ContextFrame
,
66 /* Report the new state */
68 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
69 &Prcb
->ProcessorState
.
71 SecondChanceException
);
76 /* Now restore the processor state, manually again. */
77 RtlCopyMemory(ContextRecord
,
78 &Prcb
->ProcessorState
.ContextFrame
,
80 KiRestoreProcessorControlState(&Prcb
->ProcessorState
);
82 /* Exit the debugger and clear the CTRL-C state */
83 KdExitDebugger(Entered
);
84 KdpControlCPressed
= FALSE
;
88 /* Fail if we got here */
94 KdpTrap(IN PKTRAP_FRAME TrapFrame
,
95 IN PKEXCEPTION_FRAME ExceptionFrame
,
96 IN PEXCEPTION_RECORD ExceptionRecord
,
97 IN PCONTEXT ContextRecord
,
98 IN KPROCESSOR_MODE PreviousMode
,
99 IN BOOLEAN SecondChanceException
)
101 BOOLEAN Unload
= FALSE
;
103 BOOLEAN Status
= FALSE
;
106 * Check if we got a STATUS_BREAKPOINT with a SubID for Print, Prompt or
107 * Load/Unload symbols.
109 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
110 (ExceptionRecord
->ExceptionInformation
[0] != BREAKPOINT_BREAK
))
113 Eip
= ContextRecord
->Eip
;
115 /* Check what kind of operation was requested from us */
116 switch (ExceptionRecord
->ExceptionInformation
[0])
119 case BREAKPOINT_PRINT
:
121 /* Call the worker routine */
122 Eax
= KdpPrint(ContextRecord
->Ebx
,
124 (LPSTR
)ExceptionRecord
->ExceptionInformation
[1],
125 (ULONG
)ExceptionRecord
->ExceptionInformation
[2],
131 /* Update the return value for the caller */
132 ContextRecord
->Eax
= Eax
;
136 case BREAKPOINT_PROMPT
:
138 /* Call the worker routine */
143 /* Update the return value for the caller */
144 ContextRecord
->Eax
= Eax
;
147 /* DbgUnloadSymbols */
148 case BREAKPOINT_UNLOAD_SYMBOLS
:
150 /* Drop into the load case below, with the unload parameter */
154 case BREAKPOINT_LOAD_SYMBOLS
:
156 /* Call the worker routine */
157 KdpSymbol(UlongToPtr(ExceptionRecord
->ExceptionInformation
[1]),
158 (ULONG
)ExceptionRecord
->ExceptionInformation
[2],
167 /* DbgCommandString*/
168 case BREAKPOINT_COMMAND_STRING
:
170 /* Call the worker routine */
174 /* Anything else, do nothing */
182 * If EIP was not updated, we'll increment it ourselves so execution
183 * continues past the breakpoint.
185 if (ContextRecord
->Eip
== Eip
) ContextRecord
->Eip
++;
189 /* Call the worker routine */
190 Status
= KdpReport(TrapFrame
,
195 SecondChanceException
);
198 /* Return TRUE or FALSE to caller */
204 KdpStub(IN PKTRAP_FRAME TrapFrame
,
205 IN PKEXCEPTION_FRAME ExceptionFrame
,
206 IN PEXCEPTION_RECORD ExceptionRecord
,
207 IN PCONTEXT ContextRecord
,
208 IN KPROCESSOR_MODE PreviousMode
,
209 IN BOOLEAN SecondChanceException
)
211 ULONG ExceptionCommand
= ExceptionRecord
->ExceptionInformation
[0];
213 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
214 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
215 (ExceptionRecord
->NumberParameters
> 0) &&
216 ((ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
) ||
217 (ExceptionCommand
== BREAKPOINT_UNLOAD_SYMBOLS
) ||
218 (ExceptionCommand
== BREAKPOINT_COMMAND_STRING
) ||
219 (ExceptionCommand
== BREAKPOINT_PRINT
)))
221 /* This we can handle: simply bump EIP */
222 ContextRecord
->Eip
++;
225 else if (KdPitchDebugger
)
227 /* There's no debugger, fail. */
230 else if ((KdAutoEnableOnEvent
) &&
231 (KdPreviouslyEnabled
) &&
232 !(KdDebuggerEnabled
) &&
233 (KdEnableDebugger()) &&
236 /* Debugging was Auto-Enabled. We can now send this to KD. */
237 return KdpTrap(TrapFrame
,
242 SecondChanceException
);
246 /* FIXME: All we can do in this case is trace this exception */