ReactOS  0.4.14-dev-828-g8dc90a4
kdmain.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Kernel
4  * FILE: ntoskrnl/kd/kdmain.c
5  * PURPOSE: Kernel Debugger Initialization
6  *
7  * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8  */
9 
10 #include <ntoskrnl.h>
11 #define NDEBUG
12 #include <debug.h>
13 
14 //
15 // Retrieves the ComponentId and Level for BREAKPOINT_PRINT
16 // and OutputString and OutputStringLength for BREAKPOINT_PROMPT.
17 //
18 #if defined(_X86_)
19 
20 //
21 // EBX/EDI on x86
22 //
23 #define KdpGetParameterThree(Context) ((Context)->Ebx)
24 #define KdpGetParameterFour(Context) ((Context)->Edi)
25 
26 #elif defined(_AMD64_)
27 
28 //
29 // R8/R9 on AMD64
30 //
31 #define KdpGetParameterThree(Context) ((Context)->R8)
32 #define KdpGetParameterFour(Context) ((Context)->R9)
33 
34 #elif defined(_ARM_)
35 
36 //
37 // R3/R4 on ARM
38 //
39 #define KdpGetParameterThree(Context) ((Context)->R3)
40 #define KdpGetParameterFour(Context) ((Context)->R4)
41 
42 #else
43 #error Unsupported Architecture
44 #endif
45 
46 /* VARIABLES ***************************************************************/
47 
54 
55 VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads);
56 
57 #if 0
58 ULONG Kd_DEFAULT_MASK = 1 << DPFLTR_ERROR_LEVEL;
59 #endif
60 
61 /* PRIVATE FUNCTIONS *********************************************************/
62 
63 ULONG
64 NTAPI
66  PVOID Buffer1,
67  ULONG Buffer1Length,
69 {
70  ULONG Result = 0;
71 
72  switch (Service)
73  {
74  case BREAKPOINT_PRINT: /* DbgPrint */
75  {
76  /* Call KDBG */
80  (PCHAR)Buffer1,
81  (USHORT)Buffer1Length,
83  NULL, // TrapFrame,
84  NULL, // ExceptionFrame,
85  &Handled);
86  break;
87  }
88 
89 #if DBG
90  case ' soR': /* ROS-INTERNAL */
91  {
92  switch ((ULONG_PTR)Buffer1)
93  {
94  case DumpAllThreads:
96  break;
97 
98  case DumpUserThreads:
100  break;
101 
102  case KdSpare3:
104  break;
105 
106  default:
107  break;
108  }
109  break;
110  }
111 
112 #if defined(_M_IX86) && !defined(_WINKD_) // See ke/i386/traphdlr.c
113  /* Register a debug callback */
114  case 'CsoR':
115  {
116  switch (Buffer1Length)
117  {
118  case ID_Win32PreServiceHook:
119  KeWin32PreServiceHook = Buffer1;
120  break;
121 
122  case ID_Win32PostServiceHook:
123  KeWin32PostServiceHook = Buffer1;
124  break;
125 
126  }
127  break;
128  }
129 #endif
130 
131  /* Special case for stack frame dumps */
132  case 'DsoR':
133  {
134  KeRosDumpStackFrames((PULONG_PTR)Buffer1, Buffer1Length);
135  break;
136  }
137 
138 #if defined(KDBG)
139  /* Register KDBG CLI callback */
140  case 'RbdK':
141  {
142  Result = KdbRegisterCliCallback(Buffer1, Buffer1Length);
143  break;
144  }
145 #endif /* KDBG */
146 #endif /* DBG */
147  default:
148  DPRINT1("Invalid debug service call!\n");
149  HalDisplayString("Invalid debug service call!\r\n");
150  break;
151  }
152 
153  return Result;
154 }
155 
156 BOOLEAN
157 NTAPI
159  IN PKEXCEPTION_FRAME ExceptionFrame,
160  IN PEXCEPTION_RECORD ExceptionRecord,
163  IN BOOLEAN SecondChance)
164 {
165  KD_CONTINUE_TYPE Return = kdHandleException;
166  ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
167 
168  /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
169  if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
170  (ExceptionRecord->NumberParameters > 0) &&
171  ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
172  (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
173  (ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
174  (ExceptionCommand == BREAKPOINT_PRINT) ||
175  (ExceptionCommand == BREAKPOINT_PROMPT)))
176  {
177  /* Check if this is a debug print */
178  if (ExceptionCommand == BREAKPOINT_PRINT)
179  {
180  /* Call KDBG */
181  NTSTATUS ReturnStatus;
183  ReturnStatus = KdpPrint((ULONG)KdpGetParameterThree(Context),
184  (ULONG)KdpGetParameterFour(Context),
185  (PCHAR)ExceptionRecord->ExceptionInformation[1],
186  (USHORT)ExceptionRecord->ExceptionInformation[2],
187  PreviousMode,
188  TrapFrame,
189  ExceptionFrame,
190  &Handled);
191 
192  /* Update the return value for the caller */
193  KeSetContextReturnRegister(Context, ReturnStatus);
194  }
195 #ifdef KDBG
196  else if (ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS)
197  {
198  PKD_SYMBOLS_INFO SymbolsInfo;
199  KD_SYMBOLS_INFO CapturedSymbolsInfo;
200  PLDR_DATA_TABLE_ENTRY LdrEntry;
201 
202  SymbolsInfo = (PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2];
204  {
205  _SEH2_TRY
206  {
207  ProbeForRead(SymbolsInfo,
208  sizeof(*SymbolsInfo),
209  1);
210  KdpMoveMemory(&CapturedSymbolsInfo,
211  SymbolsInfo,
212  sizeof(*SymbolsInfo));
213  SymbolsInfo = &CapturedSymbolsInfo;
214  }
216  {
217  SymbolsInfo = NULL;
218  }
219  _SEH2_END;
220  }
221 
222  if (SymbolsInfo != NULL)
223  {
224  /* Load symbols. Currently implemented only for KDBG! */
225  if (KdbpSymFindModule(SymbolsInfo->BaseOfDll, NULL, -1, &LdrEntry))
226  {
227  KdbSymProcessSymbols(LdrEntry);
228  }
229  }
230  }
231  else if (ExceptionCommand == BREAKPOINT_PROMPT)
232  {
233  /* Call KDBG */
235  ReturnLength = KdpPrompt((PCHAR)ExceptionRecord->ExceptionInformation[1],
236  (USHORT)ExceptionRecord->ExceptionInformation[2],
237  (PCHAR)KdpGetParameterThree(Context),
238  (USHORT)KdpGetParameterFour(Context),
239  PreviousMode,
240  TrapFrame,
241  ExceptionFrame);
242 
243  /* Update the return value for the caller */
245  }
246 #endif
247 
248  /* This we can handle: simply bump the Program Counter */
250  return TRUE;
251  }
252 
253 #ifdef KDBG
254  /* Check if this is an assertion failure */
255  if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE)
256  {
257  /* Bump EIP to the instruction following the int 2C */
258  Context->Eip += 2;
259  }
260 #endif
261 
262  /* Get out of here if the Debugger isn't connected */
263  if (KdDebuggerNotPresent) return FALSE;
264 
265 #ifdef KDBG
266  /* Call KDBG if available */
267  Return = KdbEnterDebuggerException(ExceptionRecord,
268  PreviousMode,
269  Context,
270  TrapFrame,
271  !SecondChance);
272 #else /* not KDBG */
273  if (WrapperInitRoutine)
274  {
275  /* Call GDB */
276  Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord,
277  Context,
278  TrapFrame);
279  }
280 #endif /* not KDBG */
281 
282  /* Debugger didn't handle it, please handle! */
283  if (Return == kdHandleException) return FALSE;
284 
285  /* Debugger handled it */
286  return TRUE;
287 }
288 
289 BOOLEAN
290 NTAPI
294 {
295  /* KDBG has its own mechanism for ignoring user mode exceptions */
296  return FALSE;
297 }
298 
299 /* PUBLIC FUNCTIONS *********************************************************/
300 
301 VOID
302 NTAPI
304 {
305 }
306 
307 BOOLEAN
308 NTAPI
310  IN PKEXCEPTION_FRAME ExceptionFrame)
311 {
312  return FALSE;
313 }
314 
315 VOID
316 NTAPI
318 {
319 }
320 
321 /*
322  * @implemented
323  */
324 BOOLEAN
325 NTAPI
327 {
329 
330  /* Just return whatever was set previously -- FIXME! */
331  return KdDebuggerNotPresent;
332 }
333 
334 /*
335  * @implemented
336  */
337 NTSTATUS
338 NTAPI
340 {
341  KIRQL OldIrql;
342 
343  /* Raise IRQL */
345 
346  /* TODO: Disable any breakpoints */
347 
348  /* Disable the Debugger */
350  SharedUserData->KdDebuggerEnabled = FALSE;
351 
352  /* Lower the IRQL */
354 
355  /* Return success */
356  return STATUS_SUCCESS;
357 }
358 
359 NTSTATUS
360 NTAPI
362 {
363  return STATUS_ACCESS_DENIED;
364 }
365 
366 /*
367  * @implemented
368  */
369 NTSTATUS
370 NTAPI
372 {
373  KIRQL OldIrql;
374 
375  /* Raise IRQL */
377 
378  /* TODO: Re-enable any breakpoints */
379 
380  /* Enable the Debugger */
382  SharedUserData->KdDebuggerEnabled = TRUE;
383 
384  /* Lower the IRQL */
386 
387  /* Return success */
388  return STATUS_SUCCESS;
389 }
390 
391 /*
392  * @implemented
393  */
394 BOOLEAN
395 NTAPI
397 {
398  return FALSE;
399 }
400 
401 /*
402  * @unimplemented
403  */
404 NTSTATUS
405 NTAPI
407 {
409  return STATUS_NOT_IMPLEMENTED;
410 }
411 
412 /*
413  * @unimplemented
414  */
415 NTSTATUS
416 NTAPI
418  IN ULONG InBufferLength OPTIONAL,
419  IN PVOID InBuffer,
420  IN ULONG OutBufferLength OPTIONAL,
421  OUT PVOID OutBuffer,
422  OUT PULONG OutBufferRequiredLength OPTIONAL)
423 {
425  return STATUS_NOT_IMPLEMENTED;
426 }
427 
428 /*
429  * @unimplemented
430  */
431 NTSTATUS
432 NTAPI
440 {
441  /* HACK */
443  InputBuffer,
445  PreviousMode);
446 }
447 
449 
450  /* EOF */
BOOLEAN KdEnteredDebugger
Definition: kdmain.c:49
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
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define KeRosDumpStackFrames(Frames, Count)
Definition: gdidebug.h:11
#define IN
Definition: typedefs.h:38
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
_In_ UCHAR _In_ POWER_STATE PowerState
Definition: pofuncs.h:42
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
NTSTATUS NTAPI KdDisableDebugger(VOID)
Definition: kdmain.c:339
struct _KD_SYMBOLS_INFO * PKD_SYMBOLS_INFO
VOID NTAPI MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
Definition: mminit.c:1474
#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
#define DPFLTR_INFO_LEVEL
Definition: kdtypes.h:33
BOOLEAN NTAPI KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdmain.c:309
LONG NTSTATUS
Definition: precomp.h:26
ULONG NTAPI KdpServiceDispatcher(ULONG Service, PVOID Buffer1, ULONG Buffer1Length, KPROCESSOR_MODE PreviousMode)
Definition: kdmain.c:65
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:140
VOID NTAPI KdUpdateDataBlock(VOID)
Definition: kdmain.c:303
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG _In_ ULONG OutputBufferLength
Definition: fltkernel.h:1374
VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads)
NTSTATUS NTAPI KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)
Definition: kdmain.c:361
Definition: shell.h:41
CHAR InputBuffer[80]
Definition: conmgr.c:33
NTSTATUS NTAPI KdPowerTransition(ULONG PowerState)
Definition: kdmain.c:406
_SEH2_TRY
Definition: create.c:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
UCHAR KIRQL
Definition: env_spec_w32.h:591
BOOLEAN NTAPI KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode)
Definition: kdmain.c:291
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
BOOLEAN KdPitchDebugger
Definition: kdmain.c:52
BOOLEAN NTAPI KdPollBreakIn(VOID)
Definition: kdmain.c:396
BOOLEAN NTAPI KdbRegisterCliCallback(PVOID Callback, BOOLEAN Deregister)
Definition: kdb_cli.c:3498
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
enum _SYSDBG_COMMAND SYSDBG_COMMAND
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_BREAKPOINT
Definition: ntstatus.h:172
BOOLEAN KdDebuggerEnabled
Definition: kdmain.c:48
PVOID BaseOfDll
Definition: kdtypes.h:170
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
#define KeGetContextPc(Context)
Definition: ke.h:124
NTSTATUS NTAPI KdChangeOption(IN KD_OPTION Option, IN ULONG InBufferLength OPTIONAL, IN PVOID InBuffer, IN ULONG OutBufferLength OPTIONAL, OUT PVOID OutBuffer, OUT PULONG OutBufferRequiredLength OPTIONAL)
Definition: kdmain.c:417
BOOLEAN NTAPI KdRefreshDebuggerNotPresent(VOID)
Definition: kdmain.c:326
#define BREAKPOINT_PROMPT
Definition: kdtypes.h:52
NTSTATUS NTAPI KdSystemDebugControl(IN SYSDBG_COMMAND Command, IN PVOID InputBuffer, IN ULONG InputBufferLength, OUT PVOID OutputBuffer, IN ULONG OutputBufferLength, IN OUT PULONG ReturnLength, IN KPROCESSOR_MODE PreviousMode)
Definition: kdmain.c:433
VOID NTAPI KdExitDebugger(IN BOOLEAN Enable)
Definition: kdmain.c:317
#define STATUS_ASSERTION_FAILURE
Definition: ntstatus.h:946
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
BOOLEAN NTAPI KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChance)
Definition: kdmain.c:158
if(!(yy_init))
Definition: macro.lex.yy.c:714
_In_ BOOLEAN Handled
Definition: ketypes.h:337
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
NTSTATUS NTAPI KdEnableDebugger(VOID)
Definition: kdmain.c:371
#define SharedUserData
#define BREAKPOINT_PRINT
Definition: kdtypes.h:51
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
VOID KdbSymProcessSymbols(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: kdb_symbols.c:424
Definition: btrfs_drv.h:1853
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG InputBufferLength
Definition: fltkernel.h:1372
#define MAXULONG
Definition: typedefs.h:250
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
PKDP_INIT_ROUTINE WrapperInitRoutine
Definition: kdinit.c:27
_SEH2_END
Definition: create.c:4424
#define DPFLTR_ERROR_LEVEL
Definition: main.cpp:32
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
unsigned int * PULONG
Definition: retypes.h:1
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
#define DPRINT1
Definition: precomp.h:8
BOOLEAN(NTAPI * PKDEBUG_ROUTINE)(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChance)
Definition: kd64.h:61
#define OUT
Definition: typedefs.h:39
KD_DISPATCH_TABLE WrapperTable
Definition: kdinit.c:28
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:114
#define BREAKPOINT_COMMAND_STRING
Definition: kdtypes.h:55
uint32_t * PULONG_PTR
Definition: typedefs.h:63
PKDEBUG_ROUTINE KiDebugRoutine
Definition: kdmain.c:448
enum _KD_OPTION KD_OPTION
BOOLEAN KdIgnoreUmExceptions
Definition: kdmain.c:53
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define KD_BREAKPOINT_SIZE
Definition: ke.h:118
KD_CONTINUE_TYPE KdbEnterDebuggerException(IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT Context, IN OUT PKTRAP_FRAME TrapFrame, IN BOOLEAN FirstChance)
KDB Exception filter.
Definition: kdb.c:1318
#define KeSetContextPc(Context, ProgramCounter)
Definition: ke.h:127
return STATUS_SUCCESS
Definition: btrfs.c:2938
BOOLEAN KdBreakAfterSymbolLoad
Definition: kdmain.c:51
BOOLEAN KdDebuggerNotPresent
Definition: kdmain.c:50
BOOLEAN KdbpSymFindModule(IN PVOID Address OPTIONAL, IN LPCWSTR Name OPTIONAL, IN INT Index OPTIONAL, OUT PLDR_DATA_TABLE_ENTRY *pLdrEntry)
Find a module...
Definition: kdb_symbols.c:76
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68