3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/kd/kdebug.c
6 * PURPOSE: Kernel debugger
8 * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de)
12 #include <internal/kdb.h>
13 #include <internal/debug.h>
15 /* serial debug connection */
16 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
17 #define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */
18 #define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
19 #define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
21 /* bochs debug output */
22 #define BOCHS_LOGGER_PORT (0xe9)
24 /* VARIABLES ***************************************************************/
28 KdDebuggerEnabled
= FALSE
; /* EXPORTED */
32 KdEnteredDebugger
= FALSE
; /* EXPORTED */
36 KdDebuggerNotPresent
= TRUE
; /* EXPORTED */
40 KiBugCheckData
; /* EXPORTED */
44 KiEnableTimerWatchdog
= FALSE
; /* EXPORTED */
47 static BOOLEAN KdpBreakPending
= FALSE
;
48 ULONG KdDebugState
= KD_DEBUG_DISABLED
;
51 KD_PORT_INFORMATION GdbPortInfo
;
52 KD_PORT_INFORMATION LogPortInfo
;
54 /* PRIVATE FUNCTIONS ********************************************************/
57 PrintString(char* fmt
,...)
63 _vsnprintf(buffer
, sizeof(buffer
) - 1, fmt
, ap
);
64 buffer
[sizeof(buffer
) - 1] = 0;
67 HalDisplayString(buffer
);
72 KdInitSystem(ULONG BootPhase
,
73 PLOADER_PARAMETER_BLOCK LoaderBlock
)
75 KD_PORT_INFORMATION PortInfo
;
82 /* Initialize the local kernel debugger. */
83 KdDebuggerEnabled
= TRUE
;
84 KdDebugState
|= KD_DEBUG_KDB
;
90 /* Set debug port default values */
91 PortInfo
.ComPort
= DEFAULT_DEBUG_PORT
;
92 PortInfo
.BaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
93 KdpPortIrq
= DEFAULT_DEBUG_COM2_IRQ
;
95 /* Set serial log port default values */
96 LogPortInfo
.ComPort
= DEFAULT_DEBUG_PORT
;
97 LogPortInfo
.BaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
100 /* Parse kernel command line */
102 /* Check for 'DEBUGPORT' */
103 p1
= (PCHAR
)LoaderBlock
->CommandLine
;
104 while (p1
&& (p2
= strchr(p1
, '/')))
107 if (!_strnicmp(p2
, "DEBUGPORT", 9))
113 if (!_strnicmp(p2
, "SCREEN", 6) && BootPhase
> 0)
116 KdDebugState
|= KD_DEBUG_SCREEN
;
118 else if (!_strnicmp(p2
, "BOCHS", 5) && BootPhase
== 0)
121 KdDebugState
|= KD_DEBUG_BOCHS
;
123 else if (!_strnicmp(p2
, "GDB", 3) && BootPhase
== 0)
126 KdDebuggerEnabled
= TRUE
;
127 KdDebugState
|= KD_DEBUG_GDB
;
129 /* Reset port information to defaults */
130 RtlMoveMemory(&GdbPortInfo
, &PortInfo
, sizeof(KD_PORT_INFORMATION
));
131 PortInfo
.ComPort
= DEFAULT_DEBUG_PORT
;
132 PortInfo
.BaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
134 else if (!_strnicmp(p2
, "PICE", 4) && BootPhase
> 0)
137 KdDebuggerEnabled
= TRUE
;
138 KdDebugState
|= KD_DEBUG_PICE
;
140 else if (!_strnicmp(p2
, "COM", 3) && BootPhase
== 0)
143 Value
= (ULONG
)atol(p2
);
144 if (Value
> 0 && Value
< 5)
146 KdDebugState
|= KD_DEBUG_SERIAL
;
147 LogPortInfo
.ComPort
= Value
;
150 else if (!_strnicmp(p2
, "FILE", 4) && BootPhase
> 0)
153 KdDebugState
|= KD_DEBUG_FILELOG
;
155 else if (!_strnicmp(p2
, "MDA", 3) && BootPhase
> 0)
158 KdDebugState
|= KD_DEBUG_MDA
;
162 else if (!_strnicmp(p2
, "KDSERIAL", 8) && BootPhase
> 0)
165 KdDebugState
|= KD_DEBUG_SERIAL
| KD_DEBUG_KDSERIAL
;
167 else if (!_strnicmp(p2
, "KDNOECHO", 8) && BootPhase
> 0)
170 KdDebugState
|= KD_DEBUG_KDNOECHO
;
172 else if (!_strnicmp(p2
, "DEBUG", 5) && BootPhase
== 0)
175 KdDebuggerEnabled
= TRUE
;
176 KdDebugState
|= KD_DEBUG_SERIAL
;
178 else if (!_strnicmp(p2
, "NODEBUG", 7) && BootPhase
== 0)
181 KdDebuggerEnabled
= FALSE
;
182 KdDebugState
= KD_DEBUG_DISABLED
;
184 else if (!_strnicmp(p2
, "CRASHDEBUG", 10) && BootPhase
== 0)
187 KdDebuggerEnabled
= FALSE
;
188 KdDebugState
= KD_DEBUG_DISABLED
;
190 else if (!_strnicmp(p2
, "BREAK", 5) && BootPhase
> 0)
193 KdpBreakPending
= TRUE
;
195 else if (!_strnicmp(p2
, "COM", 3) && BootPhase
== 0)
201 Value
= (ULONG
)atol(p2
);
202 if (0 < Value
&& Value
< 5)
204 PortInfo
.ComPort
= Value
;
208 else if (!_strnicmp(p2
, "BAUDRATE", 8) && BootPhase
== 0)
214 Value
= (ULONG
)atol(p2
);
217 PortInfo
.BaudRate
= Value
;
221 else if (!_strnicmp(p2
, "IRQ", 3) && BootPhase
== 0)
227 Value
= (ULONG
)atol(p2
);
237 /* Perform any initialization nescessary */
238 if (KdDebugState
& KD_DEBUG_GDB
&& BootPhase
== 0)
239 KdPortInitializeEx(&GdbPortInfo
, 0, 0);
241 if (KdDebugState
& KD_DEBUG_SERIAL
&& BootPhase
== 0)
242 KdPortInitializeEx(&LogPortInfo
, 0, 0);
244 if (KdDebugState
& KD_DEBUG_FILELOG
&& BootPhase
> 0)
247 if (KdDebugState
& KD_DEBUG_MDA
&& BootPhase
> 0)
255 /* Initialize kernel debugger (phase 0) */
256 if ((KdDebuggerEnabled
) &&
257 (KdDebugState
& KD_DEBUG_GDB
))
267 /* Initialize kernel debugger (phase 1) */
268 if ((KdDebuggerEnabled
) &&
269 (KdDebugState
& KD_DEBUG_GDB
))
279 /* Print some information */
280 if (KdDebugState
& KD_DEBUG_GDB
)
281 PrintString("\n GDB debugging enabled. COM%ld %ld Baud\n\n",
282 GdbPortInfo
.ComPort
, GdbPortInfo
.BaudRate
);
284 if (KdDebugState
& KD_DEBUG_PICE
)
285 PrintString("\n Private ICE debugger enabled\n\n");
287 if (KdDebugState
& KD_DEBUG_SCREEN
)
288 PrintString("\n Screen debugging enabled\n\n");
290 if (KdDebugState
& KD_DEBUG_BOCHS
)
291 PrintString("\n Bochs debugging enabled\n\n");
293 if (KdDebugState
& KD_DEBUG_SERIAL
)
294 PrintString("\n Serial debugging enabled. COM%ld %ld Baud\n\n",
295 LogPortInfo
.ComPort
, LogPortInfo
.BaudRate
);
297 if (KdDebugState
& KD_DEBUG_FILELOG
)
298 PrintString("\n File log debugging enabled\n\n");
299 if (KdDebugState
& KD_DEBUG_MDA
)
300 PrintString("\n MDA debugging enabled\n\n");
305 KdSerialDebugPrint (LPSTR Message
)
307 PCHAR pch
= (PCHAR
) Message
;
313 KdPortPutByteEx (&LogPortInfo
, '\r');
315 KdPortPutByteEx (&LogPortInfo
, *pch
);
322 KdBochsDebugPrint(IN LPSTR Message
)
324 while (*Message
!= 0)
326 if (*Message
== '\n')
328 WRITE_PORT_UCHAR((PUCHAR
)BOCHS_LOGGER_PORT
, '\r');
330 WRITE_PORT_UCHAR((PUCHAR
)BOCHS_LOGGER_PORT
, *Message
);
337 KdpPrintString(PANSI_STRING String
)
339 PCH pch
= String
->Buffer
;
341 if (KdDebugState
& KD_DEBUG_GDB
)
342 KdGdbDebugPrint(pch
);
344 if (KdDebugState
& KD_DEBUG_SCREEN
)
345 HalDisplayString(pch
);
347 if (KdDebugState
& KD_DEBUG_SERIAL
)
348 KdSerialDebugPrint(pch
);
350 if (KdDebugState
& KD_DEBUG_BOCHS
)
351 KdBochsDebugPrint(pch
);
353 if (KdDebugState
& KD_DEBUG_FILELOG
)
356 if (KdDebugState
& KD_DEBUG_MDA
)
359 return((ULONG
)String
->Length
);
362 /* PUBLIC FUNCTIONS *********************************************************/
364 /* NTOSKRNL.KdPollBreakIn */
396 if ((!KdDebuggerEnabled
) || (!(KdDebugState
& KD_DEBUG_SERIAL
)))
398 return KdpBreakPending
;
405 KeEnterKernelDebugger(VOID
)
407 HalDisplayString("\n\n *** Entered kernel debugger ***\n");
411 #if defined(__GNUC__)
413 #elif defined(_MSC_VER)
416 #error Unknown compiler for inline assembler
422 KdSystemDebugControl(ULONG Code
)
424 extern VOID STDCALL
PspDumpThreads(BOOLEAN IncludeSystem
);
426 /* A - Dump the entire contents of the non-paged pool. */
429 MiDebugDumpNonPagedPool(FALSE
);
431 /* B - Bug check the system. */
434 KEBUGCHECK(MANUALLY_INITIATED_CRASH
);
437 * C - Dump statistics about the distribution of tagged blocks in
438 * the non-paged pool.
442 MiDebugDumpNonPagedPoolStats(FALSE
);
445 * D - Dump the blocks created in the non-paged pool since the last
446 * SysRq + D and SysRq + E command.
450 MiDebugDumpNonPagedPool(TRUE
);
452 /* E - Dump statistics about the tags of newly created blocks. */
455 MiDebugDumpNonPagedPoolStats(TRUE
);
460 PspDumpThreads(TRUE
);
465 PspDumpThreads(FALSE
);
479 /* K - Enter the system debugger. */
485 DbgPrint("No local kernel debugger\n");
486 #endif /* not KDBG */
500 return STATUS_NOT_IMPLEMENTED
;
503 /* Support routines for the GDB stubs */
506 KdPutChar(UCHAR Value
)
508 KdPortPutByteEx (&GdbPortInfo
, Value
);
517 while (!KdPortGetByteEx (&GdbPortInfo
, &Value
));