ReactOS  0.4.14-dev-552-g2fad488
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 
50 BOOLEAN
51 NTAPI
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 
133 BOOLEAN
134 NTAPI
136  IN PKEXCEPTION_FRAME ExceptionFrame,
137  IN PEXCEPTION_RECORD ExceptionRecord,
140  IN BOOLEAN SecondChanceException)
141 {
142  BOOLEAN Unload;
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],
171  PreviousMode,
172  TrapFrame,
173  ExceptionFrame,
174  &Handled);
175 
176  /* Update the return value for the caller */
178  break;
179 
180  /* DbgPrompt */
181  case BREAKPOINT_PROMPT:
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),
188  PreviousMode,
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,
210  PreviousMode,
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],
223  PreviousMode,
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,
256  PreviousMode,
257  SecondChanceException);
258  }
259 
260  /* Return TRUE or FALSE to caller */
261  return Handled;
262 }
263 
264 BOOLEAN
265 NTAPI
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) &&
296  !(KdDebuggerEnabled) &&
299  {
300  /* Debugging was Auto-Enabled. We can now send this to KD. */
301  return KdpTrap(TrapFrame,
302  ExceptionFrame,
303  ExceptionRecord,
305  PreviousMode,
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 
315 BOOLEAN
316 NTAPI
320 {
321  /*
322  * Determine if this is a valid debug service call and make sure that
323  * it isn't a software breakpoint
324  */
325  if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
326  (ExceptionRecord->NumberParameters > 0) &&
327  (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK))
328  {
329  /* Then we have to handle it */
330  return TRUE;
331  }
332  else
333  {
334  /* We don't have to handle it */
335  return FALSE;
336  }
337 }
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
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:331
signed char * PCHAR
Definition: retypes.h:7
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1782
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
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
VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
Definition: csqtest.c:160
#define KeSetContextReturnRegister(Context, ReturnValue)
Definition: ke.h:139
VOID NTAPI KdpMoveMemory(_In_ PVOID Destination, _In_ PVOID Source, _In_ SIZE_T Length)
Definition: kdapi.c:22
BOOLEAN KdAutoEnableOnEvent
BOOLEAN NTAPI KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode)
Definition: kdtrap.c:317
LONG NTSTATUS
Definition: precomp.h:26
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:140
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:173
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1062
BOOLEAN KdPreviouslyEnabled
BOOLEAN KdPitchDebugger
Definition: kdmain.c:52
VOID NTAPI KdExitDebugger(IN BOOLEAN Enable)
Definition: kdmain.c:317
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
uint32_t ULONG_PTR
Definition: typedefs.h:63
VOID NTAPI KdpCommandString(IN PSTRING NameString, IN PSTRING CommandString, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
BOOLEAN KdpControlCPressed
Definition: kddata.c:68
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define BREAKPOINT_UNLOAD_SYMBOLS
Definition: kdtypes.h:54
CONTEXT ContextFrame
Definition: ketypes.h:531
unsigned char BOOLEAN
#define STATUS_BREAKPOINT
Definition: ntstatus.h:172
BOOLEAN KdDebuggerEnabled
Definition: kdmain.c:48
VOID NTAPI KiRestoreProcessorControlState(IN PKPROCESSOR_STATE ProcessorState)
#define KeGetContextPc(Context)
Definition: ke.h:124
#define BREAKPOINT_PROMPT
Definition: kdtypes.h:52
#define STATUS_ASSERTION_FAILURE
Definition: ntstatus.h:946
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
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)
_In_ BOOLEAN Handled
Definition: ketypes.h:337
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
NTSTATUS NTAPI KdEnableDebugger(VOID)
Definition: kdmain.c:371
KPROCESSOR_STATE ProcessorState
Definition: ketypes.h:579
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:661
#define BREAKPOINT_PRINT
Definition: kdtypes.h:51
VOID NTAPI KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:372
unsigned short USHORT
Definition: pedump.c:61
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:234
#define BREAKPOINT_LOAD_SYMBOLS
Definition: kdtypes.h:53
#define STATUS_PORT_DISCONNECTED
Definition: ntstatus.h:277
BOOLEAN NTAPI KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord, IN OUT PCONTEXT Context, IN BOOLEAN SecondChanceException)
unsigned int ULONG
Definition: retypes.h:1
#define BREAKPOINT_COMMAND_STRING
Definition: kdtypes.h:55
BOOLEAN NTAPI KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdmain.c:309
#define FLG_STOP_ON_EXCEPTION
Definition: pstypes.h:56
#define KD_BREAKPOINT_SIZE
Definition: ke.h:118
#define KeSetContextPc(Context, ProgramCounter)
Definition: ke.h:127
ULONG NtGlobalFlag
Definition: init.c:51
#define BREAKPOINT_BREAK
Definition: kdtypes.h:50