ReactOS  r75619
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 /* VARIABLES ***************************************************************/
15 
25 VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads);
26 
27 typedef struct
28 {
32 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
35 
37 
38 /* PRIVATE FUNCTIONS *********************************************************/
39 
40 ULONG
41 NTAPI
43  PVOID Buffer1,
44  ULONG Buffer1Length)
45 {
46  ULONG Result = 0;
47 
48  switch (Service)
49  {
50  case BREAKPOINT_PRINT: /* DbgPrint */
51  Result = KdpPrintString(Buffer1, Buffer1Length);
52  break;
53 
54 #if DBG
55  case ' soR': /* ROS-INTERNAL */
56  {
57  switch ((ULONG_PTR)Buffer1)
58  {
59  case DumpAllThreads:
61  break;
62 
63  case DumpUserThreads:
65  break;
66 
67  case KdSpare3:
69  break;
70 
71  default:
72  break;
73  }
74  break;
75  }
76 
77 #if defined(_M_IX86) && !defined(_WINKD_) // See ke/i386/traphdlr.c
78  /* Register a debug callback */
79  case 'CsoR':
80  {
81  switch (Buffer1Length)
82  {
83  case ID_Win32PreServiceHook:
84  KeWin32PreServiceHook = Buffer1;
85  break;
86 
87  case ID_Win32PostServiceHook:
88  KeWin32PostServiceHook = Buffer1;
89  break;
90 
91  }
92  break;
93  }
94 #endif
95 
96  /* Special case for stack frame dumps */
97  case 'DsoR':
98  {
99  KeRosDumpStackFrames((PULONG)Buffer1, Buffer1Length);
100  break;
101  }
102 
103 #if defined(KDBG)
104  /* Register KDBG CLI callback */
105  case 'RbdK':
106  {
107  Result = KdbRegisterCliCallback(Buffer1, Buffer1Length);
108  break;
109  }
110 #endif /* KDBG */
111 #endif /* DBG */
112  default:
113  DPRINT1("Invalid debug service call!\n");
114  HalDisplayString("Invalid debug service call!\r\n");
115  break;
116  }
117 
118  return Result;
119 }
120 
121 BOOLEAN
122 NTAPI
124  IN PKEXCEPTION_FRAME ExceptionFrame,
125  IN PEXCEPTION_RECORD ExceptionRecord,
128  IN BOOLEAN SecondChance)
129 {
130  KD_CONTINUE_TYPE Return = kdHandleException;
131  ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
132 
133  /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
134  if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
135  (ExceptionRecord->NumberParameters > 0) &&
136  ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
137  (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
138  (ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
139  (ExceptionCommand == BREAKPOINT_PRINT) ||
140  (ExceptionCommand == BREAKPOINT_PROMPT)))
141  {
142  /* Check if this is a debug print */
143  if (ExceptionCommand == BREAKPOINT_PRINT)
144  {
145  /* Print the string */
147  (PVOID)ExceptionRecord->ExceptionInformation[1],
148  ExceptionRecord->ExceptionInformation[2]);
149 
150  /* Return success */
152  }
153 #ifdef KDBG
154  else if (ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS)
155  {
156  PLDR_DATA_TABLE_ENTRY LdrEntry;
157 
158  /* Load symbols. Currently implemented only for KDBG! */
159  if(KdbpSymFindModule(((PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2])->BaseOfDll, NULL, -1, &LdrEntry))
160  KdbSymProcessSymbols(LdrEntry);
161  }
162  else if (ExceptionCommand == BREAKPOINT_PROMPT)
163  {
165  LPSTR OutString;
166  USHORT OutStringLength;
167 
168  /* Get the response string and length */
169  OutString = (LPSTR)Context->Ebx;
170  OutStringLength = (USHORT)Context->Edi;
171 
172  /* Call KDBG */
173  ReturnValue = KdpPrompt((LPSTR)ExceptionRecord->
174  ExceptionInformation[1],
175  (USHORT)ExceptionRecord->
176  ExceptionInformation[2],
177  OutString,
178  OutStringLength);
179 
180  /* Return the number of characters that we received */
181  Context->Eax = ReturnValue;
182  }
183 #endif
184 
185  /* This we can handle: simply bump the Program Counter */
186  KeSetContextPc(Context, KeGetContextPc(Context) + KD_BREAKPOINT_SIZE);
187  return TRUE;
188  }
189 
190 #ifdef KDBG
191  /* Check if this is an assertion failure */
192  if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE)
193  {
194  /* Bump EIP to the instruction following the int 2C */
195  Context->Eip += 2;
196  }
197 #endif
198 
199  /* Get out of here if the Debugger isn't connected */
200  if (KdDebuggerNotPresent) return FALSE;
201 
202 #ifdef KDBG
203  /* Call KDBG if available */
204  Return = KdbEnterDebuggerException(ExceptionRecord,
205  PreviousMode,
206  Context,
207  TrapFrame,
208  !SecondChance);
209 #else /* not KDBG */
210  if (WrapperInitRoutine)
211  {
212  /* Call GDB */
213  Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord,
214  Context,
215  TrapFrame);
216  }
217 #endif /* not KDBG */
218 
219  /* Debugger didn't handle it, please handle! */
220  if (Return == kdHandleException) return FALSE;
221 
222  /* Debugger handled it */
223  return TRUE;
224 }
225 
226 BOOLEAN
227 NTAPI
229  IN PEXCEPTION_RECORD ExceptionRecord,
231 {
232  KD_CONTINUE_TYPE Return = kdDoNotHandleException;
233 
234  /* Get out of here if the Debugger isn't connected */
235  if (KdDebuggerNotPresent) return FALSE;
236 
237  /* FIXME:
238  * Right now, the GDB wrapper seems to handle exceptions differntly
239  * from KDGB and both are called at different times, while the GDB
240  * one is only called once and that's it. I don't really have the knowledge
241  * to fix the GDB stub, so until then, we'll be using this hack
242  */
243  if (WrapperInitRoutine)
244  {
245  Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord,
246  Context,
247  TrapFrame);
248  }
249 
250  /* Debugger didn't handle it, please handle! */
251  if (Return == kdHandleException) return FALSE;
252 
253  /* Debugger handled it */
254  return TRUE;
255 }
256 
257 BOOLEAN
258 NTAPI
262 {
263  /* KDBG has its own mechanism for ignoring user mode exceptions */
264  return FALSE;
265 }
266 
267 /* PUBLIC FUNCTIONS *********************************************************/
268 
269 /*
270  * @implemented
271  */
272 BOOLEAN
273 NTAPI
275 {
277 
278  /* Just return whatever was set previously -- FIXME! */
279  return KdDebuggerNotPresent;
280 }
281 
282 /*
283  * @implemented
284  */
285 NTSTATUS
286 NTAPI
288 {
289  KIRQL OldIrql;
290 
291  /* Raise IRQL */
292  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
293 
294  /* TODO: Disable any breakpoints */
295 
296  /* Disable the Debugger */
298  SharedUserData->KdDebuggerEnabled = FALSE;
299 
300  /* Lower the IRQL */
301  KeLowerIrql(OldIrql);
302 
303  /* Return success */
304  return STATUS_SUCCESS;
305 }
306 
307 /*
308  * @implemented
309  */
310 NTSTATUS
311 NTAPI
313 {
314  KIRQL OldIrql;
315 
316  /* Raise IRQL */
317  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
318 
319  /* TODO: Re-enable any breakpoints */
320 
321  /* Enable the Debugger */
323  SharedUserData->KdDebuggerEnabled = TRUE;
324 
325  /* Lower the IRQL */
326  KeLowerIrql(OldIrql);
327 
328  /* Return success */
329  return STATUS_SUCCESS;
330 }
331 
332 /*
333  * @implemented
334  */
335 BOOLEAN
336 NTAPI
338 {
339  return KdpBreakPending;
340 }
341 
342 /*
343  * @unimplemented
344  */
345 NTSTATUS
346 NTAPI
348 {
350  return STATUS_NOT_IMPLEMENTED;
351 }
352 
353 /*
354  * @unimplemented
355  */
356 NTSTATUS
357 NTAPI
359  IN ULONG InBufferLength OPTIONAL,
360  IN PVOID InBuffer,
361  IN ULONG OutBufferLength OPTIONAL,
362  OUT PVOID OutBuffer,
363  OUT PULONG OutBufferRequiredLength OPTIONAL)
364 {
366  return STATUS_NOT_IMPLEMENTED;
367 }
368 
369 
370 NTSTATUS
371 NTAPI
373  IN ULONG Level)
374 {
375  ULONG i;
376 
377  /* Convert Level to mask if it isn't already one */
378  if (Level < 32)
379  Level = 1 << Level;
380 
381  /* Check if it is not the default component */
382  if (ComponentId != MAXULONG)
383  {
384  /* No, search for an existing entry in the table */
385  for (i = 0; i < KdComponentTableEntries; i++)
386  {
387  /* Check if it is the right component */
388  if (ComponentId == KdComponentTable[i].ComponentId)
389  {
390  /* Check if mask are matching */
391  return (Level & KdComponentTable[i].Level) ? TRUE : FALSE;
392  }
393  }
394  }
395 
396  /* Entry not found in the table, use default mask */
397  return (Level & Kd_DEFAULT_MASK) ? TRUE : FALSE;
398 }
399 
400 NTSTATUS
401 NTAPI
403  IN ULONG Level,
404  IN BOOLEAN State)
405 {
406  ULONG i;
407 
408  /* Convert Level to mask if it isn't already one */
409  if (Level < 32)
410  Level = 1 << Level;
411  Level &= ~DPFLTR_MASK;
412 
413  /* Check if it is the default component */
414  if (ComponentId == MAXULONG)
415  {
416  /* Yes, modify the default mask */
417  if (State)
419  else
420  Kd_DEFAULT_MASK &= ~Level;
421 
422  return STATUS_SUCCESS;
423  }
424 
425  /* Search for an existing entry */
426  for (i = 0; i < KdComponentTableEntries; i++ )
427  {
428  if (ComponentId == KdComponentTable[i].ComponentId)
429  break;
430  }
431 
432  /* Check if we have found an existing entry */
433  if (i == KdComponentTableEntries)
434  {
435  /* Check if we have enough space in the table */
438 
439  /* Add a new entry */
441  KdComponentTable[i].ComponentId = ComponentId;
442  KdComponentTable[i].Level = Kd_DEFAULT_MASK;
443  }
444 
445  /* Update entry table */
446  if (State)
447  KdComponentTable[i].Level |= Level;
448  else
449  KdComponentTable[i].Level &= ~Level;
450 
451  return STATUS_SUCCESS;
452 }
453 
454 /*
455  * @unimplemented
456  */
457 NTSTATUS
458 NTAPI
466 {
467  /* HACK */
468  return KdpServiceDispatcher(Command, InputBuffer, InputBufferLength);
469 }
470 
472 
473  /* EOF */
BOOLEAN KdEnteredDebugger
Definition: kdmain.c:17
DWORD *typedef PVOID
Definition: winlogon.h:52
ULONG Kd_WIN2000_Mask
Definition: kdmain.c:24
#define STATUS_SUCCESS
Definition: contextmenu.cpp:55
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define KeRosDumpStackFrames(Frames, Count)
Definition: gdidebug.h:11
KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES]
Definition: kdmain.c:33
#define IN
Definition: typedefs.h:39
BOOLEAN NTAPI KdpCallGdb(IN PKTRAP_FRAME TrapFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context)
Definition: kdmain.c:228
#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
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:59
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
NTSTATUS NTAPI KdDisableDebugger(VOID)
Definition: kdmain.c:287
VOID NTAPI MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
Definition: mminit.c:1464
#define KeSetContextReturnRegister(Context, ReturnValue)
Definition: ke.h:115
ULONG NTAPI KdpPrintString(LPSTR String, ULONG Length)
Definition: kdio.c:579
USHORT NTAPI KdpPrompt(IN LPSTR PromptString, IN USHORT PromptLength, OUT LPSTR ResponseString, IN USHORT MaximumResponseLength, IN KPROCESSOR_MODE PreviousMode, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
#define DPFLTR_MASK
Definition: kdtypes.h:34
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG _In_ ULONG OutputBufferLength
Definition: fltkernel.h:1374
VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads)
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
_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
Definition: shell.h:41
char * LPSTR
Definition: xmlstorage.h:182
CHAR InputBuffer[80]
Definition: conmgr.c:33
NTSTATUS NTAPI KdPowerTransition(ULONG PowerState)
Definition: kdmain.c:347
uint32_t ULONG_PTR
Definition: typedefs.h:64
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLenum GLclampf GLint i
Definition: glfuncs.h:14
BOOLEAN NTAPI KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode)
Definition: kdmain.c:259
UINT32 void void ** ReturnValue
Definition: acevents.h:192
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define MAX_KD_COMPONENT_TABLE_ENTRIES
Definition: kdmain.c:32
#define BREAKPOINT_UNLOAD_SYMBOLS
Definition: kdtypes.h:54
BOOLEAN KdPitchDebugger
Definition: kdmain.c:21
BOOLEAN NTAPI KdPollBreakIn(VOID)
Definition: kdmain.c:337
BOOLEAN NTAPI KdbRegisterCliCallback(PVOID Callback, BOOLEAN Deregister)
Definition: kdb_cli.c:3307
enum _SYSDBG_COMMAND SYSDBG_COMMAND
smooth NULL
Definition: ftsmooth.c:513
#define STATUS_BREAKPOINT
Definition: ntstatus.h:172
BOOLEAN KdDebuggerEnabled
Definition: kdmain.c:16
_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:100
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:358
BOOLEAN NTAPI KdRefreshDebuggerNotPresent(VOID)
Definition: kdmain.c:274
#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:459
#define STATUS_ASSERTION_FAILURE
Definition: ntstatus.h:946
unsigned char BOOLEAN
_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:123
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
NTSTATUS NTAPI KdEnableDebugger(VOID)
Definition: kdmain.c:312
#define DPFLTR_ERROR_LEVEL
Definition: shimdbg.c:14
#define SharedUserData
BOOLEAN KdpBreakPending
Definition: kdmain.c:20
#define BREAKPOINT_PRINT
Definition: kdtypes.h:51
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:461
VOID KdbSymProcessSymbols(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: kdb_symbols.c:424
Definition: ntddk_ex.h:202
NTSTATUS NTAPI NtQueryDebugFilterState(IN ULONG ComponentId, IN ULONG Level)
Definition: kdmain.c:372
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG InputBufferLength
Definition: fltkernel.h:1372
#define MAXULONG
Definition: typedefs.h:251
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
PKDP_INIT_ROUTINE WrapperInitRoutine
Definition: kdinit.c:27
ULONG Kd_DEFAULT_MASK
Definition: kdmain.c:36
LONG NTSTATUS
Definition: DriverTester.h:11
unsigned short USHORT
Definition: pedump.c:61
ULONG KdComponentTableEntries
Definition: kdmain.c:34
#define BREAKPOINT_LOAD_SYMBOLS
Definition: kdtypes.h:53
unsigned int * PULONG
Definition: retypes.h:1
ULONG ComponentId
Definition: kdmain.c:29
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
#define DPRINT1
Definition: precomp.h:8
#define OUT
Definition: typedefs.h:40
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
PKDEBUG_ROUTINE KiDebugRoutine
Definition: kdmain.c:471
enum _KD_OPTION KD_OPTION
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 const char UINT32 const char const char UINT32 ComponentId
Definition: acpixf.h:1256
ULONG NTAPI KdpServiceDispatcher(ULONG Service, PVOID Buffer1, ULONG Buffer1Length)
Definition: kdmain.c:42
BOOLEAN KdIgnoreUmExceptions
Definition: kdmain.c:22
#define KD_BREAKPOINT_SIZE
Definition: ke.h:94
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:1352
#define KeSetContextPc(Context, ProgramCounter)
Definition: ke.h:103
BOOLEAN KdBreakAfterSymbolLoad
Definition: kdmain.c:19
NTSTATUS NTAPI NtSetDebugFilterState(IN ULONG ComponentId, IN ULONG Level, IN BOOLEAN State)
Definition: kdmain.c:402
KD_CONTEXT KdpContext
Definition: kdmain.c:23
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
BOOLEAN KdDebuggerNotPresent
Definition: kdmain.c:18
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