1 /* $Id: kdebug.c,v 1.54 2004/08/07 03:41:31 sedwards Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/kd/kdebug.c
6 * PURPOSE: Kernel debugger
7 * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
12 #include <ddk/ntddk.h>
13 #include <internal/ntoskrnl.h>
14 #include <internal/kd.h>
15 #include <internal/mm.h>
17 #include "../dbg/kdb.h"
18 #include <internal/debug.h>
20 /* serial debug connection */
21 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
22 #define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */
23 #define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
24 #define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
26 /* bochs debug output */
27 #define BOCHS_LOGGER_PORT (0xe9)
29 /* VARIABLES ***************************************************************/
33 KdDebuggerEnabled
= FALSE
; /* EXPORTED */
37 KdEnteredDebugger
= FALSE
; /* EXPORTED */
41 KdDebuggerNotPresent
= TRUE
; /* EXPORTED */
45 KiBugCheckData
; /* EXPORTED */
49 KiEnableTimerWatchdog
= FALSE
; /* EXPORTED */
52 static BOOLEAN KdpBreakPending
= FALSE
;
53 ULONG KdDebugState
= KD_DEBUG_DISABLED
;
56 KD_PORT_INFORMATION GdbPortInfo
;
57 KD_PORT_INFORMATION LogPortInfo
;
59 /* PRIVATE FUNCTIONS ********************************************************/
62 PrintString(char* fmt
,...)
68 vsprintf(buffer
, fmt
, ap
);
71 HalDisplayString(buffer
);
76 KdInitSystem(ULONG Reserved
,
77 PLOADER_PARAMETER_BLOCK LoaderBlock
)
79 KD_PORT_INFORMATION PortInfo
;
84 /* Initialize runtime debugging if available */
89 /* Initialize the local kernel debugger. */
90 KdDebuggerEnabled
= TRUE
;
91 KdDebugState
|= KD_DEBUG_KDB
;
94 /* Set debug port default values */
95 PortInfo
.ComPort
= DEFAULT_DEBUG_PORT
;
96 PortInfo
.BaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
97 KdpPortIrq
= DEFAULT_DEBUG_COM2_IRQ
;
99 /* Set serial log port default values */
100 LogPortInfo
.ComPort
= DEFAULT_DEBUG_PORT
;
101 LogPortInfo
.BaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
103 /* Parse kernel command line */
105 /* Check for 'DEBUGPORT' */
106 p1
= (PCHAR
)LoaderBlock
->CommandLine
;
107 while (p1
&& (p2
= strchr(p1
, '/')))
110 if (!_strnicmp(p2
, "DEBUGPORT", 9))
116 if (!_strnicmp(p2
, "SCREEN", 6))
119 KdDebuggerEnabled
= TRUE
;
120 KdDebugState
|= KD_DEBUG_SCREEN
;
122 else if (!_strnicmp(p2
, "BOCHS", 5))
125 KdDebuggerEnabled
= TRUE
;
126 KdDebugState
|= KD_DEBUG_BOCHS
;
128 else if (!_strnicmp(p2
, "GDB", 3))
131 KdDebuggerEnabled
= TRUE
;
132 KdDebugState
|= KD_DEBUG_GDB
;
134 /* Reset port information to defaults */
135 RtlMoveMemory(&GdbPortInfo
, &PortInfo
, sizeof(KD_PORT_INFORMATION
));
136 PortInfo
.ComPort
= DEFAULT_DEBUG_PORT
;
137 PortInfo
.BaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
139 else if (!_strnicmp(p2
, "PICE", 4))
142 KdDebuggerEnabled
= TRUE
;
143 KdDebugState
|= KD_DEBUG_PICE
;
145 else if (!_strnicmp(p2
, "COM", 3))
148 Value
= (ULONG
)atol(p2
);
149 if (Value
> 0 && Value
< 5)
151 KdDebuggerEnabled
= TRUE
;
152 KdDebugState
|= KD_DEBUG_SERIAL
;
153 LogPortInfo
.ComPort
= Value
;
156 else if (!_strnicmp(p2
, "BOOTLOG", 4))
159 KdDebuggerEnabled
= TRUE
;
160 KdDebugState
|= KD_DEBUG_BOOTLOG
;
162 else if (!_strnicmp(p2
, "MDA", 3))
165 KdDebuggerEnabled
= TRUE
;
166 KdDebugState
|= KD_DEBUG_MDA
;
170 else if (!_strnicmp(p2
, "KDSERIAL", 8))
173 KdDebuggerEnabled
= TRUE
;
174 KdDebugState
|= KD_DEBUG_SERIAL
| KD_DEBUG_KDSERIAL
;
176 else if (!_strnicmp(p2
, "KDNOECHO", 8))
179 KdDebuggerEnabled
= TRUE
;
180 KdDebugState
|= KD_DEBUG_KDNOECHO
;
182 else if (!_strnicmp(p2
, "DEBUG", 5))
185 KdDebuggerEnabled
= TRUE
;
186 KdDebugState
|= KD_DEBUG_SERIAL
;
188 else if (!_strnicmp(p2
, "NODEBUG", 7))
191 KdDebuggerEnabled
= FALSE
;
192 KdDebugState
= KD_DEBUG_DISABLED
;
194 else if (!_strnicmp(p2
, "CRASHDEBUG", 10))
197 KdDebuggerEnabled
= FALSE
;
198 KdDebugState
= KD_DEBUG_DISABLED
;
200 else if (!_strnicmp(p2
, "BREAK", 5))
203 KdpBreakPending
= TRUE
;
205 else if (!_strnicmp(p2
, "COM", 3))
211 Value
= (ULONG
)atol(p2
);
212 if (0 < Value
&& Value
< 5)
214 PortInfo
.ComPort
= Value
;
218 else if (!_strnicmp(p2
, "BAUDRATE", 8))
224 Value
= (ULONG
)atol(p2
);
227 PortInfo
.BaudRate
= Value
;
231 else if (!_strnicmp(p2
, "IRQ", 3))
237 Value
= (ULONG
)atol(p2
);
245 else if (!_strnicmp(p2
, "PROFILE", 7))
253 /* Perform any initialization nescessary */
254 if (KdDebuggerEnabled
== TRUE
)
256 if (KdDebugState
& KD_DEBUG_GDB
)
257 KdPortInitializeEx(&GdbPortInfo
, 0, 0);
259 if (KdDebugState
& KD_DEBUG_SERIAL
)
260 KdPortInitializeEx(&LogPortInfo
, 0, 0);
262 if (KdDebugState
& KD_DEBUG_BOOTLOG
)
265 if (KdDebugState
& KD_DEBUG_MDA
)
274 /* Initialize kernel debugger (phase 0) */
275 if ((KdDebuggerEnabled
== TRUE
) &&
276 (KdDebugState
& KD_DEBUG_GDB
))
286 /* Initialize kernel debugger (phase 1) */
287 if ((KdDebuggerEnabled
== TRUE
) &&
288 (KdDebugState
& KD_DEBUG_GDB
))
298 /* Print some information */
299 if (KdDebuggerEnabled
== TRUE
)
301 if (KdDebugState
& KD_DEBUG_GDB
)
302 PrintString("\n GDB debugging enabled. COM%ld %ld Baud\n\n",
303 GdbPortInfo
.ComPort
, GdbPortInfo
.BaudRate
);
305 if (KdDebugState
& KD_DEBUG_PICE
)
306 PrintString("\n Private ICE debugger enabled\n\n");
308 if (KdDebugState
& KD_DEBUG_SCREEN
)
309 PrintString("\n Screen debugging enabled\n\n");
311 if (KdDebugState
& KD_DEBUG_BOCHS
)
312 PrintString("\n Bochs debugging enabled\n\n");
314 if (KdDebugState
& KD_DEBUG_SERIAL
)
315 PrintString("\n Serial debugging enabled. COM%ld %ld Baud\n\n",
316 LogPortInfo
.ComPort
, LogPortInfo
.BaudRate
);
318 if (KdDebugState
& KD_DEBUG_BOOTLOG
)
319 PrintString("\n File log debugging enabled\n\n");
320 if (KdDebugState
& KD_DEBUG_MDA
)
321 PrintString("\n MDA debugging enabled\n\n");
327 KdSerialDebugPrint (LPSTR Message
)
329 PCHAR pch
= (PCHAR
) Message
;
335 KdPortPutByteEx (&LogPortInfo
, '\r');
337 KdPortPutByteEx (&LogPortInfo
, *pch
);
344 KdBochsDebugPrint(IN LPSTR Message
)
346 while (*Message
!= 0)
348 if (*Message
== '\n')
350 WRITE_PORT_UCHAR((PUCHAR
)BOCHS_LOGGER_PORT
, '\r');
352 WRITE_PORT_UCHAR((PUCHAR
)BOCHS_LOGGER_PORT
, *Message
);
359 KdpPrintString(PANSI_STRING String
)
361 PCH pch
= String
->Buffer
;
363 if (KdDebugState
& KD_DEBUG_GDB
)
364 KdGdbDebugPrint(pch
);
366 if (KdDebugState
& KD_DEBUG_SCREEN
)
367 HalDisplayString(pch
);
369 if (KdDebugState
& KD_DEBUG_SERIAL
)
370 KdSerialDebugPrint(pch
);
372 if (KdDebugState
& KD_DEBUG_BOCHS
)
373 KdBochsDebugPrint(pch
);
375 if (KdDebugState
& KD_DEBUG_BOOTLOG
)
378 if (KdDebugState
& KD_DEBUG_MDA
)
381 return((ULONG
)String
->Length
);
384 /* PUBLIC FUNCTIONS *********************************************************/
386 /* NTOSKRNL.KdPollBreakIn */
431 if ((!KdDebuggerEnabled
) || (!(KdDebugState
& KD_DEBUG_SERIAL
)))
433 return KdpBreakPending
;
440 KeEnterKernelDebugger(VOID
)
442 HalDisplayString("\n\n *** Entered kernel debugger ***\n");
446 #if defined(__GNUC__)
448 #elif defined(_MSC_VER)
451 #error Unknown compiler for inline assembler
457 KdSystemDebugControl(ULONG Code
)
459 extern VOID
PsDumpThreads(BOOLEAN IncludeSystem
);
461 /* A - Dump the entire contents of the non-paged pool. */
464 MiDebugDumpNonPagedPool(FALSE
);
466 /* B - Bug check the system. */
469 KEBUGCHECK(0xDEADDEAD);
472 * C - Dump statistics about the distribution of tagged blocks in
473 * the non-paged pool.
477 MiDebugDumpNonPagedPoolStats(FALSE
);
480 * D - Dump the blocks created in the non-paged pool since the last
481 * SysRq + D and SysRq + E command.
485 MiDebugDumpNonPagedPool(TRUE
);
487 /* E - Dump statistics about the tags of newly created blocks. */
490 MiDebugDumpNonPagedPoolStats(TRUE
);
500 PsDumpThreads(FALSE
);
514 /* K - Enter the system debugger. */
520 DbgPrint("No local kernel debugger\n");
521 #endif /* not KDBG */
535 return STATUS_NOT_IMPLEMENTED
;
538 /* Support routines for the GDB stubs */
541 KdPutChar(UCHAR Value
)
543 KdPortPutByteEx (&GdbPortInfo
, Value
);
552 while (!KdPortGetByteEx (&GdbPortInfo
, &Value
));