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
;
28 NTSTATUS ExceptionCode
= ExceptionRecord
->ExceptionCode
;
30 /* Check if this is INT1 or 3, or if we're forced to handle it */
31 if ((ExceptionCode
== STATUS_BREAKPOINT
) ||
32 (ExceptionCode
== STATUS_SINGLE_STEP
) ||
33 //(ExceptionCode == STATUS_ASSERTION_FAILURE) ||
34 (NtGlobalFlag
& FLG_STOP_ON_EXCEPTION
))
36 /* Check if we can't really handle this */
37 if ((SecondChanceException
) ||
38 (ExceptionCode
== STATUS_PORT_DISCONNECTED
) ||
39 (NT_SUCCESS(ExceptionCode
)))
41 /* Return false to have someone else take care of the exception */
45 else if (SecondChanceException
)
47 /* We won't bother unless this is first chance */
51 /* Enter the debugger */
52 Entered
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
55 * Get the KPRCB and save the CPU Control State manually instead of
56 * using KiSaveProcessorState, since we already have a valid CONTEXT.
58 Prcb
= KeGetCurrentPrcb();
59 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
60 RtlCopyMemory(&Prcb
->ProcessorState
.ContextFrame
,
64 /* Report the new state */
65 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
66 &Prcb
->ProcessorState
.
68 SecondChanceException
);
70 /* Now restore the processor state, manually again. */
71 RtlCopyMemory(ContextRecord
,
72 &Prcb
->ProcessorState
.ContextFrame
,
74 KiRestoreProcessorControlState(&Prcb
->ProcessorState
);
76 /* Exit the debugger and clear the CTRL-C state */
77 KdExitDebugger(Entered
);
78 KdpControlCPressed
= FALSE
;
84 KdpTrap(IN PKTRAP_FRAME TrapFrame
,
85 IN PKEXCEPTION_FRAME ExceptionFrame
,
86 IN PEXCEPTION_RECORD ExceptionRecord
,
87 IN PCONTEXT ContextRecord
,
88 IN KPROCESSOR_MODE PreviousMode
,
89 IN BOOLEAN SecondChanceException
)
91 BOOLEAN Unload
= FALSE
;
92 ULONG_PTR ProgramCounter
, ReturnValue
;
93 BOOLEAN Status
= FALSE
;
96 * Check if we got a STATUS_BREAKPOINT with a SubID for Print, Prompt or
97 * Load/Unload symbols.
99 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
100 (ExceptionRecord
->ExceptionInformation
[0] != BREAKPOINT_BREAK
))
102 /* Save Program Counter */
103 ProgramCounter
= KeGetContextPc(ContextRecord
);
105 /* Check what kind of operation was requested from us */
106 switch (ExceptionRecord
->ExceptionInformation
[0])
109 case BREAKPOINT_PRINT
:
111 /* Call the worker routine */
112 ReturnValue
= KdpPrint((ULONG
)ContextRecord
->Ebx
,
113 (ULONG
)ContextRecord
->Edi
,
114 (LPSTR
)ExceptionRecord
->
115 ExceptionInformation
[1],
116 (USHORT
)ExceptionRecord
->
117 ExceptionInformation
[2],
123 /* Update the return value for the caller */
124 KeSetContextReturnRegister(ContextRecord
, ReturnValue
);
128 case BREAKPOINT_PROMPT
:
130 /* Call the worker routine */
131 ReturnValue
= KdpPrompt((LPSTR
)ExceptionRecord
->
132 ExceptionInformation
[1],
133 (USHORT
)ExceptionRecord
->
134 ExceptionInformation
[2],
135 (LPSTR
)ContextRecord
->Ebx
,
136 (USHORT
)ContextRecord
->Edi
,
142 /* Update the return value for the caller */
143 KeSetContextReturnRegister(ContextRecord
, ReturnValue
);
146 /* DbgUnloadImageSymbols */
147 case BREAKPOINT_UNLOAD_SYMBOLS
:
149 /* Drop into the load case below, with the unload parameter */
152 /* DbgLoadImageSymbols */
153 case BREAKPOINT_LOAD_SYMBOLS
:
155 /* Call the worker routine */
156 KdpSymbol((PSTRING
)ExceptionRecord
->
157 ExceptionInformation
[1],
158 (PKD_SYMBOLS_INFO
)ExceptionRecord
->
159 ExceptionInformation
[2],
168 /* DbgCommandString */
169 case BREAKPOINT_COMMAND_STRING
:
171 /* Call the worker routine */
172 KdpCommandString((ULONG
)ExceptionRecord
->
173 ExceptionInformation
[1],
174 (LPSTR
)ExceptionRecord
->
175 ExceptionInformation
[2],
182 /* Anything else, do nothing */
190 * If the PC was not updated, we'll increment it ourselves so execution
191 * continues past the breakpoint.
193 if (ProgramCounter
== KeGetContextPc(ContextRecord
))
196 KeSetContextPc(ContextRecord
,
197 ProgramCounter
+ KD_BREAKPOINT_SIZE
);
202 /* Call the worker routine */
203 Status
= KdpReport(TrapFrame
,
208 SecondChanceException
);
211 /* Return TRUE or FALSE to caller */
217 KdpStub(IN PKTRAP_FRAME TrapFrame
,
218 IN PKEXCEPTION_FRAME ExceptionFrame
,
219 IN PEXCEPTION_RECORD ExceptionRecord
,
220 IN PCONTEXT ContextRecord
,
221 IN KPROCESSOR_MODE PreviousMode
,
222 IN BOOLEAN SecondChanceException
)
224 ULONG ExceptionCommand
= ExceptionRecord
->ExceptionInformation
[0];
226 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
227 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
228 (ExceptionRecord
->NumberParameters
> 0) &&
229 ((ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
) ||
230 (ExceptionCommand
== BREAKPOINT_UNLOAD_SYMBOLS
) ||
231 (ExceptionCommand
== BREAKPOINT_COMMAND_STRING
) ||
232 (ExceptionCommand
== BREAKPOINT_PRINT
)))
234 /* This we can handle: simply bump the Program Counter */
235 KeSetContextPc(ContextRecord
,
236 KeGetContextPc(ContextRecord
) + KD_BREAKPOINT_SIZE
);
239 else if (KdPitchDebugger
)
241 /* There's no debugger, fail. */
244 else if ((KdAutoEnableOnEvent
) &&
245 (KdPreviouslyEnabled
) &&
246 !(KdDebuggerEnabled
) &&
247 (NT_SUCCESS(KdEnableDebugger())) &&
250 /* Debugging was Auto-Enabled. We can now send this to KD. */
251 return KdpTrap(TrapFrame
,
256 SecondChanceException
);
260 /* FIXME: All we can do in this case is trace this exception */