ReactOS 0.4.16-dev-329-g9223134
kdprint.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/kdprint.c
5 * PURPOSE: KD64 Trap Handler Routines
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#define KD_PRINT_MAX_BYTES 512
17
18/* FUNCTIONS *****************************************************************/
19
24{
26
27 /* Acquire the spinlock without waiting at raised IRQL */
28 while (TRUE)
29 {
30 /* Loop until the spinlock becomes available */
31 while (!KeTestSpinLock(SpinLock));
32
33 /* Spinlock is free, raise IRQL to high level */
35
36 /* Try to get the spinlock */
38 break;
39
40 /* Someone else got the spinlock, lower IRQL back */
42 }
43
44 return OldIrql;
45}
46
47VOID
52{
53 /* Release the spinlock */
55 // KeReleaseSpinLockFromDpcLevel(SpinLock);
56
57 /* Restore the old IRQL */
59}
60
61VOID
65{
66 SIZE_T Length, Remaining;
68
69 /* If the string is empty, bail out */
70 if (!String->Buffer || (String->Length == 0))
71 return;
72
73 /* If no log buffer available, bail out */
74 if (!KdPrintCircularBuffer /*|| (KdPrintBufferSize == 0)*/)
75 return;
76
77 /* Acquire the log spinlock without waiting at raised IRQL */
79
82
83 if (Length < Remaining)
84 {
87 }
88 else
89 {
90 KdpMoveMemory(KdPrintWritePointer, String->Buffer, Remaining);
91 Length -= Remaining;
92 if (Length > 0)
93 KdpMoveMemory(KdPrintCircularBuffer, String->Buffer + Remaining, Length);
94
96
97 /* Got a rollover, update count (handle wrapping, must always be >= 1) */
99 if (KdPrintRolloverCount == 0)
101 }
102
103 /* Release the spinlock */
105}
106
108NTAPI
111{
113 DBGKD_DEBUG_IO DebugIo;
115
116 /* Copy the string */
118 Output->Buffer,
119 Output->Length);
120
121 /* Make sure we don't exceed the KD Packet size */
122 Length = Output->Length;
123 if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
124 {
125 /* Normalize length */
127 }
128
129 /* Build the packet header */
132 DebugIo.Processor = KeGetCurrentPrcb()->Number;
134 Header.Length = sizeof(DBGKD_DEBUG_IO);
135 Header.Buffer = (PCHAR)&DebugIo;
136
137 /* Build the data */
138 Data.Length = Length;
139 Data.Buffer = KdpMessageBuffer;
140
141 /* Send the packet */
143
144 /* Check if the user pressed CTRL+C */
146}
147
149NTAPI
151 _In_ PSTRING PromptString,
152 _In_ PSTRING ResponseString)
153{
155 DBGKD_DEBUG_IO DebugIo;
158
159 /* Copy the string to the message buffer */
161 PromptString->Buffer,
162 PromptString->Length);
163
164 /* Make sure we don't exceed the KD Packet size */
165 Length = PromptString->Length;
166 if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
167 {
168 /* Normalize length */
170 }
171
172 /* Build the packet header */
175 DebugIo.Processor = KeGetCurrentPrcb()->Number;
177 DebugIo.u.GetString.LengthOfStringRead = ResponseString->MaximumLength;
178 Header.Length = sizeof(DBGKD_DEBUG_IO);
179 Header.Buffer = (PCHAR)&DebugIo;
180
181 /* Build the data */
182 Data.Length = Length;
183 Data.Buffer = KdpMessageBuffer;
184
185 /* Send the packet */
187
188 /* Set the maximum lengths for the receive */
189 Header.MaximumLength = sizeof(DBGKD_DEBUG_IO);
190 Data.MaximumLength = sizeof(KdpMessageBuffer);
191
192 /* Enter receive loop */
193 do
194 {
195 /* Get our reply */
197 &Header,
198 &Data,
199 &Length,
200 &KdpContext);
201
202 /* Return TRUE if we need to resend */
203 if (Status == KdPacketNeedsResend) return TRUE;
204
205 /* Loop until we succeed */
206 } while (Status != KdPacketReceived);
207
208 /* Don't copy back a larger response than there is room for */
209 Length = min(Length,
210 ResponseString->MaximumLength);
211
212 /* Copy back the string and return the length */
213 KdpMoveMemory(ResponseString->Buffer,
215 Length);
216 ResponseString->Length = (USHORT)Length;
217
218 /* Success; we don't need to resend */
219 return FALSE;
220}
221
222VOID
223NTAPI
225 IN PSTRING CommandString,
228 IN PKTRAP_FRAME TrapFrame,
229 IN PKEXCEPTION_FRAME ExceptionFrame)
230{
232 PKPRCB Prcb = KeGetCurrentPrcb();
233
234 /* Check if we need to do anything */
235 if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return;
236
237 /* Enter the debugger */
238 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
239
240 /* Save the CPU Control State and save the context */
244 sizeof(CONTEXT));
245
246 /* Send the command string to the debugger */
248 CommandString,
250
251 /* Restore the processor state */
254 sizeof(CONTEXT));
256
257 /* Exit the debugger and return */
259}
260
261VOID
262NTAPI
264 IN PKD_SYMBOLS_INFO SymbolInfo,
268 IN PKTRAP_FRAME TrapFrame,
269 IN PKEXCEPTION_FRAME ExceptionFrame)
270{
272 PKPRCB Prcb = KeGetCurrentPrcb();
273
274 /* Check if we need to do anything */
275 if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return;
276
277 /* Enter the debugger */
278 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
279
280 /* Save the CPU Control State and save the context */
284 sizeof(CONTEXT));
285
286 /* Report the new state */
288 SymbolInfo,
289 Unload,
291
292 /* Restore the processor state */
295 sizeof(CONTEXT));
297
298 /* Exit the debugger and return */
300}
301
302USHORT
303NTAPI
305 _In_reads_bytes_(PromptLength) PCHAR PromptString,
306 _In_ USHORT PromptLength,
310 _In_ PKTRAP_FRAME TrapFrame,
311 _In_ PKEXCEPTION_FRAME ExceptionFrame)
312{
313 STRING PromptBuffer, ResponseBuffer;
314 BOOLEAN Enable, Resend;
315 PCHAR SafeResponseString;
316 CHAR CapturedPrompt[KD_PRINT_MAX_BYTES];
317 CHAR SafeResponseBuffer[KD_PRINT_MAX_BYTES];
318
319 /* Normalize the lengths */
320 PromptLength = min(PromptLength,
321 sizeof(CapturedPrompt));
323 sizeof(SafeResponseBuffer));
324
325 /* Check if we need to verify the string */
327 {
328 /* Handle user-mode buffers safely */
330 {
331 /* Probe and capture the prompt */
332 ProbeForRead(PromptString, PromptLength, 1);
333 KdpMoveMemory(CapturedPrompt, PromptString, PromptLength);
334 PromptString = CapturedPrompt;
335
336 /* Probe and make room for the response */
337 ProbeForWrite(ResponseString, MaximumResponseLength, 1);
338 SafeResponseString = SafeResponseBuffer;
339 }
341 {
342 /* Bad string pointer, bail out */
343 _SEH2_YIELD(return 0);
344 }
345 _SEH2_END;
346 }
347 else
348 {
349 SafeResponseString = ResponseString;
350 }
351
352 /* Setup the prompt and response buffers */
353 PromptBuffer.Buffer = PromptString;
354 PromptBuffer.Length = PromptBuffer.MaximumLength = PromptLength;
355 ResponseBuffer.Buffer = SafeResponseString;
356 ResponseBuffer.Length = 0;
357 ResponseBuffer.MaximumLength = MaximumResponseLength;
358
359 /* Log the print */
360 KdLogDbgPrint(&PromptBuffer);
361
362 /* Enter the debugger */
363 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
364
365 /* Enter prompt loop */
366 do
367 {
368 /* Send the prompt and receive the response */
369 Resend = KdpPromptString(&PromptBuffer, &ResponseBuffer);
370
371 /* Loop while we need to resend */
372 } while (Resend);
373
374 /* Exit the debugger */
376
377 /* Copy back the response if required */
379 {
381 {
382 /* Safely copy back the response to user mode */
383 KdpMoveMemory(ResponseString,
384 ResponseBuffer.Buffer,
385 ResponseBuffer.Length);
386 }
388 {
389 /* String became invalid after we exited, fail */
390 _SEH2_YIELD(return 0);
391 }
392 _SEH2_END;
393 }
394
395 /* Return the number of characters received */
396 return ResponseBuffer.Length;
397}
398
399static
401NTAPI
408 _In_ PKTRAP_FRAME TrapFrame,
409 _In_ PKEXCEPTION_FRAME ExceptionFrame,
411{
412 CHAR CapturedString[KD_PRINT_MAX_BYTES];
413
415 ASSERT(Length <= sizeof(CapturedString));
416
417 /* Capture user-mode buffers */
419 {
420 /* Probe and capture the string */
422 KdpMoveMemory(CapturedString, String, Length);
423 String = CapturedString;
424 }
426 {
427 /* Bad string pointer, bail out */
429 }
430 _SEH2_END;
431
432 /* Now go through the kernel-mode code path */
433 return KdpPrint(ComponentId,
434 Level,
435 String,
436 Length,
438 TrapFrame,
439 ExceptionFrame,
440 Handled);
441}
442
444NTAPI
451 _In_ PKTRAP_FRAME TrapFrame,
452 _In_ PKEXCEPTION_FRAME ExceptionFrame,
454{
457 STRING OutputString;
458
460 {
461 /* Mask validation failed */
462 *Handled = TRUE;
463 return STATUS_SUCCESS;
464 }
465
466 /* Assume failure */
467 *Handled = FALSE;
468
469 /* Normalize the length */
471
472 /* Check if we need to verify the string */
474 {
475 /* This case requires a 512 byte stack buffer.
476 * We don't want to use that much stack in the kernel case, but we
477 * can't use _alloca due to PSEH. So the buffer exists in this
478 * helper function instead.
479 */
481 Level,
482 String,
483 Length,
485 TrapFrame,
486 ExceptionFrame,
487 Handled);
488 }
489
490 /* Setup the output string */
491 OutputString.Buffer = String;
492 OutputString.Length = OutputString.MaximumLength = Length;
493
494 /* Log the print */
495 KdLogDbgPrint(&OutputString);
496
497 /* Check for a debugger */
499 {
500 /* Fail */
501 *Handled = TRUE;
503 }
504
505 /* Enter the debugger */
506 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
507
508 /* Print the string */
509 if (KdpPrintString(&OutputString))
510 {
511 /* User pressed CTRL-C, breakpoint on return */
513 }
514 else
515 {
516 /* String was printed */
518 }
519
520 /* Exit the debugger and return */
522 *Handled = TRUE;
523 return Status;
524}
525
526VOID
530 ...)
531{
534 va_list ap;
535 CHAR Buffer[512];
536
537 /* Format the string */
540 sizeof(Buffer),
541 Format,
542 ap);
543 va_end(ap);
544
545 /* Set it up */
546 String.Buffer = Buffer;
547 String.Length = String.MaximumLength = Length;
548
549 /* Send it to the debugger directly */
551}
unsigned char BOOLEAN
#define __cdecl
Definition: accygwin.h:79
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
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 ACPI_STATUS const char UINT32 const char const char UINT32 ComponentId
Definition: acpixf.h:1281
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
Definition: Header.h:9
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
KSPIN_LOCK * PKSPIN_LOCK
Definition: env_spec_w32.h:73
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
Definition: floppy.c:377
std::wstring STRING
Definition: fontsub.cpp:33
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
BOOLEAN NTAPI KdpPollBreakInWithPortLock(VOID)
Definition: kdlock.c:35
ULONG KdPrintBufferSize
Definition: kddata.c:136
ULONG KdPrintRolloverCount
Definition: kddata.c:134
KSPIN_LOCK KdpPrintSpinLock
Definition: kddata.c:138
PCHAR KdPrintWritePointer
Definition: kddata.c:133
VOID NTAPI KdpReportCommandStringStateChange(IN PSTRING NameString, IN PSTRING CommandString, IN OUT PCONTEXT Context)
Definition: kdapi.c:1678
VOID NTAPI KdpReportLoadSymbolsStateChange(IN PSTRING PathName, IN PKD_SYMBOLS_INFO SymbolInfo, IN BOOLEAN Unload, IN OUT PCONTEXT Context)
Definition: kdapi.c:1606
KD_CONTEXT KdpContext
Definition: kddata.c:65
BOOLEAN NTAPI KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdapi.c:1902
VOID NTAPI KdExitDebugger(IN BOOLEAN Enable)
Definition: kdapi.c:1955
VOID NTAPI KdpMoveMemory(_In_ PVOID Destination, _In_ PVOID Source, _In_ SIZE_T Length)
Definition: kdapi.c:27
CHAR KdpMessageBuffer[KDP_MSG_BUFFER_SIZE]
Definition: kddata.c:126
PCHAR KdPrintCircularBuffer
Definition: kddata.c:135
NTSTATUS NTAPI NtQueryDebugFilterState(_In_ ULONG ComponentId, _In_ ULONG Level)
Definition: kdapi.c:2383
BOOLEAN KdDebuggerNotPresent
Definition: kddata.c:81
VOID NTAPI KdSendPacket(IN ULONG PacketType, IN PSTRING MessageHeader, IN PSTRING MessageData, IN OUT PKD_CONTEXT KdContext)
Definition: kddll.c:314
KDP_STATUS NTAPI KdReceivePacket(IN ULONG PacketType, OUT PSTRING MessageHeader, OUT PSTRING MessageData, OUT PULONG DataLength, IN OUT PKD_CONTEXT KdContext)
Definition: kddll.c:80
VOID NTAPI KdpCommandString(IN PSTRING NameString, IN PSTRING CommandString, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdprint.c:224
#define KD_PRINT_MAX_BYTES
Definition: kdprint.c:16
KIRQL NTAPI KdpAcquireLock(_In_ PKSPIN_LOCK SpinLock)
Definition: kdprint.c:22
VOID NTAPI KdpReleaseLock(_In_ PKSPIN_LOCK SpinLock, _In_ KIRQL OldIrql)
Definition: kdprint.c:49
VOID NTAPI KdLogDbgPrint(_In_ PSTRING String)
Definition: kdprint.c:63
BOOLEAN NTAPI KdpPrintString(_In_ PSTRING Output)
Definition: kdprint.c:109
static NTSTATUS NTAPI KdpPrintFromUser(_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:402
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:445
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)
Definition: kdprint.c:263
BOOLEAN NTAPI KdpPromptString(_In_ PSTRING PromptString, _In_ PSTRING ResponseString)
Definition: kdprint.c:150
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:304
#define PCHAR
Definition: match.c:90
#define KdpDprintf(...)
Definition: mmdbg.c:19
#define ASSERT(a)
Definition: mode.c:44
static const char const char * DllPath
Definition: image.c:34
#define min(a, b)
Definition: monoChain.cc:55
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1150
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:662
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
VOID NTAPI KiRestoreProcessorControlState(IN PKPROCESSOR_STATE ProcessorState)
USHORT KeProcessorLevel
Definition: krnlinit.c:20
VOID NTAPI KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:576
BOOLEAN FASTCALL KeTestSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:475
BOOLEAN FASTCALL KeTryToAcquireSpinLockAtDpcLevel(IN OUT PKSPIN_LOCK SpinLock)
Definition: spinlock.c:309
VOID FASTCALL KiReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:298
#define STATUS_BREAKPOINT
Definition: ntstatus.h:184
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
@ Output
Definition: arc.h:85
#define KdPacketReceived
Definition: kddll.h:5
#define KdPacketNeedsResend
Definition: kddll.h:7
ULONG KDSTATUS
Definition: kddll.h:4
#define STATUS_SUCCESS
Definition: shellext.h:65
DBGKD_GET_STRING GetString
Definition: windbgkd.h:427
union _DBGKD_DEBUG_IO::@3547 u
ULONG ApiNumber
Definition: windbgkd.h:421
USHORT Processor
Definition: windbgkd.h:423
USHORT ProcessorLevel
Definition: windbgkd.h:422
DBGKD_PRINT_STRING PrintString
Definition: windbgkd.h:426
ULONG LengthOfStringRead
Definition: windbgkd.h:413
ULONG LengthOfPromptString
Definition: windbgkd.h:412
KPROCESSOR_STATE ProcessorState
Definition: ketypes.h:652
CONTEXT ContextFrame
Definition: ketypes.h:605
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFSPINLOCK * SpinLock
Definition: wdfsync.h:228
#define DbgKdPrintStringApi
Definition: windbgkd.h:122
#define PACKET_MAX_SIZE
Definition: windbgkd.h:18
#define DbgKdGetStringApi
Definition: windbgkd.h:123
struct _DBGKD_DEBUG_IO DBGKD_DEBUG_IO
#define PACKET_TYPE_KD_DEBUG_IO
Definition: windbgkd.h:44
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
_In_ ULONG MaximumResponseLength
Definition: kdfuncs.h:11
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ BOOLEAN Handled
Definition: ketypes.h:349
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define _vsnprintf
Definition: xmlstorage.h:202
char CHAR
Definition: xmlstorage.h:175