Sync to trunk r38250
[reactos.git] / reactos / ntoskrnl / kd64 / kdtrap.c
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 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS *****************************************************************/
16
17 BOOLEAN
18 NTAPI
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)
25 {
26 BOOLEAN Entered, Status;
27 PKPRCB Prcb;
28 NTSTATUS ExceptionCode = ExceptionRecord->ExceptionCode;
29
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))
35 {
36 /* Check if we can't really handle this */
37 if ((SecondChanceException) ||
38 (ExceptionCode == STATUS_PORT_DISCONNECTED) ||
39 (NT_SUCCESS(ExceptionCode)))
40 {
41 /* Return false to have someone else take care of the exception */
42 return FALSE;
43 }
44 }
45 else if (SecondChanceException)
46 {
47 /* We won't bother unless this is second chance */
48 return FALSE;
49 }
50
51 /* Enter the debugger */
52 Entered = KdEnterDebugger(TrapFrame, ExceptionFrame);
53
54 /*
55 * Get the KPRCB and save the CPU Control State manually instead of
56 * using KiSaveProcessorState, since we already have a valid CONTEXT.
57 */
58 Prcb = KeGetCurrentPrcb();
59 KiSaveProcessorControlState(&Prcb->ProcessorState);
60 RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
61 ContextRecord,
62 sizeof(CONTEXT));
63
64 /* Report the new state */
65 Status = KdpReportExceptionStateChange(ExceptionRecord,
66 &Prcb->ProcessorState.
67 ContextFrame,
68 SecondChanceException);
69
70 /* Now restore the processor state, manually again. */
71 RtlCopyMemory(ContextRecord,
72 &Prcb->ProcessorState.ContextFrame,
73 sizeof(CONTEXT));
74 //KiRestoreProcessorControlState(&Prcb->ProcessorState);
75
76 /* Exit the debugger and clear the CTRL-C state */
77 KdExitDebugger(Entered);
78 KdpControlCPressed = FALSE;
79 return Status;
80 }
81
82 BOOLEAN
83 NTAPI
84 KdpStub(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)
90 {
91 ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
92
93 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
94 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
95 (ExceptionRecord->NumberParameters > 0) &&
96 ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
97 (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
98 (ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
99 (ExceptionCommand == BREAKPOINT_PRINT)))
100 {
101 /* This we can handle: simply bump EIP */
102 #if defined (_M_X86)
103 ContextRecord->Eip++;
104 #elif defined (_M_AMD64)
105 ContextRecord->Rip++;
106 #else
107 #error Unknown platform
108 #endif
109 return TRUE;
110 }
111 else if (KdPitchDebugger)
112 {
113 /* There's no debugger, fail. */
114 return FALSE;
115 }
116 else if ((KdAutoEnableOnEvent) &&
117 (KdPreviouslyEnabled) &&
118 !(KdDebuggerEnabled) &&
119 (KdEnableDebugger()) &&
120 (KdDebuggerEnabled))
121 {
122 /* Debugging was Auto-Enabled. We can now send this to KD. */
123 return KdpTrap(TrapFrame,
124 ExceptionFrame,
125 ExceptionRecord,
126 ContextRecord,
127 PreviousMode,
128 SecondChanceException);
129 }
130 else
131 {
132 /* FIXME: All we can do in this case is trace this exception */
133 return FALSE;
134 }
135 }