1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdapi.c
5 * PURPOSE: KD64 Public Routines and Internal Support
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
14 #ifdef KDBG
15 #include <kdbg/kdb.h>
16 #endif
17
18 #define NDEBUG
19 #include <debug.h>
20
21 VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads);
22
23 /* PRIVATE FUNCTIONS *********************************************************/
24
25 VOID
26 NTAPI
KdpMoveMemory(_In_ PVOID Destination,_In_ PVOID Source,_In_ SIZE_T Length)27 KdpMoveMemory(
28 _In_ PVOID Destination,
29 _In_ PVOID Source,
30 _In_ SIZE_T Length)
31 {
32 PCHAR DestinationBytes, SourceBytes;
33
34 /* Copy the buffers 1 byte at a time */
35 DestinationBytes = Destination;
36 SourceBytes = Source;
37 while (Length--) *DestinationBytes++ = *SourceBytes++;
38 }
39
40 VOID
41 NTAPI
KdpZeroMemory(_In_ PVOID Destination,_In_ SIZE_T Length)42 KdpZeroMemory(
43 _In_ PVOID Destination,
44 _In_ SIZE_T Length)
45 {
46 PCHAR DestinationBytes;
47
48 /* Zero the buffer 1 byte at a time */
49 DestinationBytes = Destination;
50 while (Length--) *DestinationBytes++ = 0;
51 }
52
53 NTSTATUS
54 NTAPI
KdpCopyMemoryChunks(_In_ ULONG64 Address,_In_ PVOID Buffer,_In_ ULONG TotalSize,_In_ ULONG ChunkSize,_In_ ULONG Flags,_Out_opt_ PULONG ActualSize)55 KdpCopyMemoryChunks(
56 _In_ ULONG64 Address,
57 _In_ PVOID Buffer,
58 _In_ ULONG TotalSize,
59 _In_ ULONG ChunkSize,
60 _In_ ULONG Flags,
61 _Out_opt_ PULONG ActualSize)
62 {
63 NTSTATUS Status;
64 ULONG RemainingLength, CopyChunk;
65
66 /* Check if we didn't get a chunk size or if it is too big */
67 if (ChunkSize == 0)
68 {
69 /* Default to 4 byte chunks */
70 ChunkSize = 4;
71 }
72 else if (ChunkSize > MMDBG_COPY_MAX_SIZE)
73 {
74 /* Normalize to maximum size */
75 ChunkSize = MMDBG_COPY_MAX_SIZE;
76 }
77
78 /* Copy the whole range in aligned chunks */
79 RemainingLength = TotalSize;
80 CopyChunk = 1;
81 while (RemainingLength > 0)
82 {
83 /*
84 * Determine the best chunk size for this round.
85 * The ideal size is aligned, isn't larger than the
86 * the remaining length and respects the chunk limit.
87 */
88 while (((CopyChunk * 2) <= RemainingLength) &&
89 (CopyChunk < ChunkSize) &&
90 ((Address & ((CopyChunk * 2) - 1)) == 0))
91 {
92 /* Increase it */
93 CopyChunk *= 2;
94 }
95
96 /*
97 * The chunk size can be larger than the remaining size if this
98 * isn't the first round, so check if we need to shrink it back.
99 */
100 while (CopyChunk > RemainingLength)
101 {
102 /* Shrink it */
103 CopyChunk /= 2;
104 }
105
106 /* Do the copy */
107 Status = MmDbgCopyMemory(Address, Buffer, CopyChunk, Flags);
108 if (!NT_SUCCESS(Status))
109 {
110 /* Copy failed, break out */
111 break;
112 }
113
114 /* Update pointers and length for the next run */
115 Address = Address + CopyChunk;
116 Buffer = (PVOID)((ULONG_PTR)Buffer + CopyChunk);
117 RemainingLength = RemainingLength - CopyChunk;
118 }
119
120 /* We may have modified executable code, flush the instruction cache */
121 KeSweepICache((PVOID)(ULONG_PTR)Address, TotalSize);
122
123 /*
124 * Return the size we managed to copy and return
125 * success if we could copy the whole range.
126 */
127 if (ActualSize) *ActualSize = TotalSize - RemainingLength;
128 return RemainingLength == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
129 }
130
131 VOID
132 NTAPI
KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PCONTEXT Context)133 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,
134 IN PCONTEXT Context)
135 {
136 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;
137 STRING Header;
138 NTSTATUS Status = STATUS_SUCCESS;
139
140 /* Validate the address space */
141 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)
142 {
143 /* Check if this is process memory */
144 if ((PVOID)(ULONG_PTR)Memory->Address < MmHighestUserAddress)
145 {
146 /* It is */
147 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
148 }
149 else
150 {
151 /* Check if it's session space */
152 if (MmIsSessionAddress((PVOID)(ULONG_PTR)Memory->Address))
153 {
154 /* It is */
155 Memory->AddressSpace = DBGKD_QUERY_MEMORY_SESSION;
156 }
157 else
158 {
159 /* Not session space but some other kernel memory */
160 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
161 }
162 }
163
164 /* Set flags */
165 Memory->Flags = DBGKD_QUERY_MEMORY_READ |
166 DBGKD_QUERY_MEMORY_WRITE |
167 DBGKD_QUERY_MEMORY_EXECUTE;
168 }
169 else
170 {
171 /* Invalid */
172 Status = STATUS_INVALID_PARAMETER;
173 }
174
175 /* Return structure */
176 State->ReturnStatus = Status;
177 Memory->Reserved = 0;
178
179 /* Build header */
180 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
181 Header.Buffer = (PCHAR)State;
182
183 /* Send the packet */
184 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
185 &Header,
186 NULL,
187 &KdpContext);
188 }
189
190 VOID
191 NTAPI
KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)192 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,
193 IN PSTRING Data,
194 IN PCONTEXT Context)
195 {
196 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory;
197 STRING Header;
198
199 /* TODO */
200 KdpDprintf("Memory Search support is unimplemented!\n");
201
202 /* Send a failure packet */
203 State->ReturnStatus = STATUS_UNSUCCESSFUL;
204 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
205 Header.Buffer = (PCHAR)State;
206 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
207 &Header,
208 NULL,
209 &KdpContext);
210 }
211
212 VOID
213 NTAPI
KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)214 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,
215 IN PSTRING Data,
216 IN PCONTEXT Context)
217 {
218 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory;
219 STRING Header;
220
221 /* TODO */
222 KdpDprintf("Memory Fill support is unimplemented!\n");
223
224 /* Send a failure packet */
225 State->ReturnStatus = STATUS_UNSUCCESSFUL;
226 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
227 Header.Buffer = (PCHAR)State;
228 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
229 &Header,
230 NULL,
231 &KdpContext);
232 }
233
234 VOID
235 NTAPI
KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)236 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
237 IN PSTRING Data,
238 IN PCONTEXT Context)
239 {
240 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
241 STRING Header;
242
243 /* Build header */
244 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
245 Header.Buffer = (PCHAR)State;
246 ASSERT(Data->Length == 0);
247
248 /* Create the breakpoint */
249 Breakpoint->BreakPointHandle =
250 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress);
251 if (!Breakpoint->BreakPointHandle)
252 {
253 /* We failed */
254 State->ReturnStatus = STATUS_UNSUCCESSFUL;
255 }
256 else
257 {
258 /* Success! */
259 State->ReturnStatus = STATUS_SUCCESS;
260 }
261
262 /* Send the packet */
263 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
264 &Header,
265 NULL,
266 &KdpContext);
267 }
268
269 VOID
270 NTAPI
KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)271 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
272 IN PSTRING Data,
273 IN PCONTEXT Context)
274 {
275 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
276 STRING Header;
277
278 /* Fill out the header */
279 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
280 Header.Buffer = (PCHAR)State;
281 ASSERT(Data->Length == 0);
282
283 /* Get the version block */
284 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
285 {
286 /* We're all good */
287 State->ReturnStatus = STATUS_SUCCESS;
288 }
289 else
290 {
291 /* We failed */
292 State->ReturnStatus = STATUS_UNSUCCESSFUL;
293 }
294
295 /* Send the packet */
296 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
297 &Header,
298 NULL,
299 &KdpContext);
300 }
301
302 NTSTATUS
303 NTAPI
KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)304 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
305 IN PSTRING Data,
306 IN PCONTEXT Context)
307 {
308 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
309 STRING Header;
310
311 /* TODO */
312 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n");
313
314 /* Send a failure packet */
315 State->ReturnStatus = STATUS_UNSUCCESSFUL;
316 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
317 Header.Buffer = (PCHAR)State;
318 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
319 &Header,
320 Data,
321 &KdpContext);
322 return STATUS_UNSUCCESSFUL;
323 }
324
325 VOID
326 NTAPI
KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)327 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
328 IN PSTRING Data,
329 IN PCONTEXT Context)
330 {
331 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
332 STRING Header;
333
334 /* TODO */
335 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n");
336
337 /* Send a failure packet */
338 State->ReturnStatus = STATUS_UNSUCCESSFUL;
339 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
340 Header.Buffer = (PCHAR)State;
341 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
342 &Header,
343 Data,
344 &KdpContext);
345 }
346
347 VOID
348 NTAPI
KdpWriteCustomBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)349 KdpWriteCustomBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
350 IN PSTRING Data,
351 IN PCONTEXT Context)
352 {
353 //PDBGKD_WRITE_CUSTOM_BREAKPOINT = &State->u.WriteCustomBreakpoint;
354 STRING Header;
355
356 /* Not supported */
357 KdpDprintf("Custom Breakpoint Write is unimplemented\n");
358
359 /* Send a failure packet */
360 State->ReturnStatus = STATUS_UNSUCCESSFUL;
361 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
362 Header.Buffer = (PCHAR)State;
363 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
364 &Header,
365 NULL,
366 &KdpContext);
367 }
368
369 VOID
370 NTAPI
DumpTraceData(IN PSTRING TraceData)371 DumpTraceData(IN PSTRING TraceData)
372 {
373 /* Update the buffer */
374 TraceDataBuffer[0] = TraceDataBufferPosition;
375
376 /* Setup the trace data */
377 TraceData->Length = (USHORT)(TraceDataBufferPosition * sizeof(ULONG));
378 TraceData->Buffer = (PCHAR)TraceDataBuffer;
379
380 /* Reset the buffer location */
381 TraceDataBufferPosition = 1;
382 }
383
384 VOID
385 NTAPI
KdpSetCommonState(IN ULONG NewState,IN PCONTEXT Context,IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange)386 KdpSetCommonState(IN ULONG NewState,
387 IN PCONTEXT Context,
388 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange)
389 {
390 ULONG InstructionCount;
391 BOOLEAN HadBreakpoints;
392
393 /* Setup common stuff available for all CPU architectures */
394 WaitStateChange->NewState = NewState;
395 WaitStateChange->ProcessorLevel = KeProcessorLevel;
396 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
397 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
398 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
399 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
400
401 /* Zero out the entire Control Report */
402 KdpZeroMemory(&WaitStateChange->AnyControlReport,
403 sizeof(DBGKD_ANY_CONTROL_REPORT));
404
405 /* Now copy the instruction stream and set the count */
406 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter,
407 &WaitStateChange->ControlReport.InstructionStream[0],
408 DBGKD_MAXSTREAM,
409 0,
410 MMDBG_COPY_UNSAFE,
411 &InstructionCount);
412 WaitStateChange->ControlReport.InstructionCount = (USHORT)InstructionCount;
413
414 /* Clear all the breakpoints in this region */
415 HadBreakpoints =
416 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
417 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
418 WaitStateChange->ControlReport.InstructionCount - 1));
419 if (HadBreakpoints)
420 {
421 /* Copy the instruction stream again, this time without breakpoints */
422 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter,
423 &WaitStateChange->ControlReport.InstructionStream[0],
424 InstructionCount,
425 0,
426 MMDBG_COPY_UNSAFE,
427 NULL);
428 }
429 }
430
431 VOID
432 NTAPI
KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version)433 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version)
434 {
435 /* Copy the version block */
436 KdpMoveMemory(Version,
437 &KdVersionBlock,
438 sizeof(DBGKD_GET_VERSION64));
439 }
440
441 VOID
442 NTAPI
KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)443 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
444 {
445 STRING Header;
446
447 /* Fill out the header */
448 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
449 Header.Buffer = (PCHAR)State;
450
451 /* Get the version block */
452 KdpSysGetVersion(&State->u.GetVersion64);
453
454 /* Fill out the state */
455 State->ApiNumber = DbgKdGetVersionApi;
456 State->ReturnStatus = STATUS_SUCCESS;
457
458 /* Send the packet */
459 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
460 &Header,
461 NULL,
462 &KdpContext);
463 }
464
465 VOID
466 NTAPI
KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)467 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
468 IN PSTRING Data,
469 IN PCONTEXT Context)
470 {
471 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
472 STRING Header;
473 ULONG Length = ReadMemory->TransferCount;
474
475 /* Setup the header */
476 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
477 Header.Buffer = (PCHAR)State;
478 ASSERT(Data->Length == 0);
479
480 /* Validate length */
481 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
482 {
483 /* Overflow, set it to maximum possible */
484 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
485 }
486
487 /* Do the read */
488 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress,
489 Data->Buffer,
490 Length,
491 0,
492 MMDBG_COPY_UNSAFE,
493 &Length);
494
495 /* Return the actual length read */
496 ReadMemory->ActualBytesRead = Length;
497 Data->Length = (USHORT)Length;
498
499 /* Send the packet */
500 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
501 &Header,
502 Data,
503 &KdpContext);
504 }
505
506 VOID
507 NTAPI
KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)508 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
509 IN PSTRING Data,
510 IN PCONTEXT Context)
511 {
512 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
513 STRING Header;
514
515 /* Setup the header */
516 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
517 Header.Buffer = (PCHAR)State;
518
519 /* Do the write */
520 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress,
521 Data->Buffer,
522 Data->Length,
523 0,
524 MMDBG_COPY_UNSAFE |
525 MMDBG_COPY_WRITE,
526 &WriteMemory->ActualBytesWritten);
527
528 /* Send the packet */
529 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
530 &Header,
531 NULL,
532 &KdpContext);
533 }
534
535 VOID
536 NTAPI
KdpReadPhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)537 KdpReadPhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State,
538 IN PSTRING Data,
539 IN PCONTEXT Context)
540 {
541 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
542 STRING Header;
543 ULONG Length = ReadMemory->TransferCount;
544 ULONG Flags, CacheFlags;
545
546 /* Setup the header */
547 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
548 Header.Buffer = (PCHAR)State;
549 ASSERT(Data->Length == 0);
550
551 /* Validate length */
552 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
553 {
554 /* Overflow, set it to maximum possible */
555 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
556 }
557
558 /* Start with the default flags */
559 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_PHYSICAL;
560
561 /* Get the caching flags and check if a type is specified */
562 CacheFlags = ReadMemory->ActualBytesRead;
563 if (CacheFlags == DBGKD_CACHING_CACHED)
564 {
565 /* Cached */
566 Flags |= MMDBG_COPY_CACHED;
567 }
568 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
569 {
570 /* Uncached */
571 Flags |= MMDBG_COPY_UNCACHED;
572 }
573 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED)
574 {
575 /* Write Combined */
576 Flags |= MMDBG_COPY_WRITE_COMBINED;
577 }
578
579 /* Do the read */
580 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress,
581 Data->Buffer,
582 Length,
583 0,
584 Flags,
585 &Length);
586
587 /* Return the actual length read */
588 ReadMemory->ActualBytesRead = Length;
589 Data->Length = (USHORT)Length;
590
591 /* Send the packet */
592 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
593 &Header,
594 Data,
595 &KdpContext);
596 }
597
598 VOID
599 NTAPI
KdpWritePhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)600 KdpWritePhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State,
601 IN PSTRING Data,
602 IN PCONTEXT Context)
603 {
604 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
605 STRING Header;
606 ULONG Flags, CacheFlags;
607
608 /* Setup the header */
609 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
610 Header.Buffer = (PCHAR)State;
611
612 /* Start with the default flags */
613 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE | MMDBG_COPY_PHYSICAL;
614
615 /* Get the caching flags and check if a type is specified */
616 CacheFlags = WriteMemory->ActualBytesWritten;
617 if (CacheFlags == DBGKD_CACHING_CACHED)
618 {
619 /* Cached */
620 Flags |= MMDBG_COPY_CACHED;
621 }
622 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
623 {
624 /* Uncached */
625 Flags |= MMDBG_COPY_UNCACHED;
626 }
627 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED)
628 {
629 /* Write Combined */
630 Flags |= MMDBG_COPY_WRITE_COMBINED;
631 }
632
633 /* Do the write */
634 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress,
635 Data->Buffer,
636 Data->Length,
637 0,
638 Flags,
639 &WriteMemory->ActualBytesWritten);
640
641 /* Send the packet */
642 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
643 &Header,
644 NULL,
645 &KdpContext);
646 }
647
648 VOID
649 NTAPI
KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)650 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
651 IN PSTRING Data,
652 IN PCONTEXT Context)
653 {
654 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
655 STRING Header;
656 ULONG Length;
657
658 /* Setup the header */
659 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
660 Header.Buffer = (PCHAR)State;
661 ASSERT(Data->Length == 0);
662
663 /* Check the length requested */
664 Length = ReadMemory->TransferCount;
665 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
666 {
667 /* Use maximum allowed */
668 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
669 }
670
671 /* Call the internal routine */
672 State->ReturnStatus = KdpSysReadControlSpace(State->Processor,
673 ReadMemory->TargetBaseAddress,
674 Data->Buffer,
675 Length,
676 &Length);
677
678 /* Return the actual length read */
679 ReadMemory->ActualBytesRead = Length;
680 Data->Length = (USHORT)Length;
681
682 /* Send the reply */
683 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
684 &Header,
685 Data,
686 &KdpContext);
687 }
688
689 VOID
690 NTAPI
KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)691 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
692 IN PSTRING Data,
693 IN PCONTEXT Context)
694 {
695 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
696 STRING Header;
697
698 /* Setup the header */
699 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
700 Header.Buffer = (PCHAR)State;
701
702 /* Call the internal routine */
703 State->ReturnStatus = KdpSysWriteControlSpace(State->Processor,
704 WriteMemory->TargetBaseAddress,
705 Data->Buffer,
706 Data->Length,
707 &WriteMemory->ActualBytesWritten);
708
709 /* Send the reply */
710 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
711 &Header,
712 Data,
713 &KdpContext);
714 }
715
716 VOID
717 NTAPI
KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)718 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
719 IN PSTRING Data,
720 IN PCONTEXT Context)
721 {
722 STRING Header;
723 PCONTEXT TargetContext;
724
725 /* Setup the header */
726 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
727 Header.Buffer = (PCHAR)State;
728 ASSERT(Data->Length == 0);
729
730 /* Make sure that this is a valid request */
731 if (State->Processor < KeNumberProcessors)
732 {
733 /* Check if the request is for this CPU */
734 if (State->Processor == KeGetCurrentPrcb()->Number)
735 {
736 /* We're just copying our own context */
737 TargetContext = Context;
738 }
739 else
740 {
741 /* Get the context from the PRCB array */
742 TargetContext = &KiProcessorBlock[State->Processor]->
743 ProcessorState.ContextFrame;
744 }
745
746 /* Copy it over to the debugger */
747 KdpMoveMemory(Data->Buffer,
748 TargetContext,
749 sizeof(CONTEXT));
750 Data->Length = sizeof(CONTEXT);
751
752 /* Let the debugger set the context now */
753 KdpContextSent = TRUE;
754
755 /* Finish up */
756 State->ReturnStatus = STATUS_SUCCESS;
757 }
758 else
759 {
760 /* Invalid request */
761 State->ReturnStatus = STATUS_UNSUCCESSFUL;
762 }
763
764 /* Send the reply */
765 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
766 &Header,
767 Data,
768 &KdpContext);
769 }
770
771 VOID
772 NTAPI
KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)773 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
774 IN PSTRING Data,
775 IN PCONTEXT Context)
776 {
777 STRING Header;
778 PCONTEXT TargetContext;
779
780 /* Setup the header */
781 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
782 Header.Buffer = (PCHAR)State;
783 ASSERT(Data->Length == sizeof(CONTEXT));
784
785 /* Make sure that this is a valid request */
786 if ((State->Processor < KeNumberProcessors) &&
787 (KdpContextSent))
788 {
789 /* Check if the request is for this CPU */
790 if (State->Processor == KeGetCurrentPrcb()->Number)
791 {
792 /* We're just copying our own context */
793 TargetContext = Context;
794 }
795 else
796 {
797 /* Get the context from the PRCB array */
798 TargetContext = &KiProcessorBlock[State->Processor]->
799 ProcessorState.ContextFrame;
800 }
801
802 /* Copy the new context to it */
803 KdpMoveMemory(TargetContext,
804 Data->Buffer,
805 sizeof(CONTEXT));
806
807 /* Finish up */
808 State->ReturnStatus = STATUS_SUCCESS;
809 }
810 else
811 {
812 /* Invalid request */
813 State->ReturnStatus = STATUS_UNSUCCESSFUL;
814 }
815
816 /* Send the reply */
817 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
818 &Header,
819 NULL,
820 &KdpContext);
821 }
822
823 VOID
824 NTAPI
KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)825 KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
826 IN PSTRING Data,
827 IN PCONTEXT Context)
828 {
829 STRING Header;
830 PDBGKD_CONTEXT_EX ContextEx;
831 PCONTEXT TargetContext;
832 ASSERT(Data->Length == 0);
833
834 /* Get our struct */
835 ContextEx = &State->u.ContextEx;
836
837 /* Set up the header */
838 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
839 Header.Buffer = (PCHAR)State;
840
841 /* Make sure that this is a valid request */
842 if ((State->Processor < KeNumberProcessors) &&
843 (ContextEx->Offset + ContextEx->ByteCount) <= sizeof(CONTEXT))
844 {
845 /* Check if the request is for this CPU */
846 if (State->Processor == KeGetCurrentPrcb()->Number)
847 {
848 /* We're just copying our own context */
849 TargetContext = Context;
850 }
851 else
852 {
853 /* Get the context from the PRCB array */
854 TargetContext = &KiProcessorBlock[State->Processor]->
855 ProcessorState.ContextFrame;
856 }
857
858 /* Copy what is requested */
859 KdpMoveMemory(Data->Buffer,
860 (PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
861 ContextEx->ByteCount);
862
863 /* KD copies all */
864 Data->Length = ContextEx->BytesCopied = ContextEx->ByteCount;
865
866 /* Let the debugger set the context now */
867 KdpContextSent = TRUE;
868
869 /* Finish up */
870 State->ReturnStatus = STATUS_SUCCESS;
871 }
872 else
873 {
874 /* Invalid request */
875 ContextEx->BytesCopied = 0;
876 State->ReturnStatus = STATUS_UNSUCCESSFUL;
877 }
878
879 /* Send the reply */
880 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
881 &Header,
882 Data,
883 &KdpContext);
884 }
885
886 VOID
887 NTAPI
KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)888 KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
889 IN PSTRING Data,
890 IN PCONTEXT Context)
891 {
892 STRING Header;
893 PDBGKD_CONTEXT_EX ContextEx;
894 PCONTEXT TargetContext;
895
896 /* Get our struct */
897 ContextEx = &State->u.ContextEx;
898 ASSERT(Data->Length == ContextEx->ByteCount);
899
900 /* Set up the header */
901 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
902 Header.Buffer = (PCHAR)State;
903
904 /* Make sure that this is a valid request */
905 if ((State->Processor < KeNumberProcessors) &&
906 ((ContextEx->Offset + ContextEx->ByteCount) <= sizeof(CONTEXT)) &&
907 (KdpContextSent))
908 {
909 /* Check if the request is for this CPU */
910 if (State->Processor == KeGetCurrentPrcb()->Number)
911 {
912 /* We're just copying our own context */
913 TargetContext = Context;
914 }
915 else
916 {
917 /* Get the context from the PRCB array */
918 TargetContext = &KiProcessorBlock[State->Processor]->
919 ProcessorState.ContextFrame;
920 }
921
922 /* Copy what is requested */
923 KdpMoveMemory((PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
924 Data->Buffer,
925 ContextEx->ByteCount);
926
927 /* KD copies all */
928 ContextEx->BytesCopied = ContextEx->ByteCount;
929
930 /* Finish up */
931 State->ReturnStatus = STATUS_SUCCESS;
932 }
933 else
934 {
935 /* Invalid request */
936 ContextEx->BytesCopied = 0;
937 State->ReturnStatus = STATUS_UNSUCCESSFUL;
938 }
939
940 /* Send the reply */
941 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
942 &Header,
943 NULL,
944 &KdpContext);
945 }
946
947 VOID
948 NTAPI
KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)949 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)
950 {
951 /* Crash with the special code */
952 KeBugCheck(MANUALLY_INITIATED_CRASH);
953 }
954
955 VOID
956 NTAPI
KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)957 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
958 IN PSTRING Data,
959 IN PCONTEXT Context)
960 {
961 STRING Header;
962 PDBGKD_READ_WRITE_MSR ReadMsr = &State->u.ReadWriteMsr;
963 LARGE_INTEGER MsrValue;
964
965 /* Setup the header */
966 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
967 Header.Buffer = (PCHAR)State;
968 ASSERT(Data->Length == 0);
969
970 /* Call the internal routine */
971 State->ReturnStatus = KdpSysReadMsr(ReadMsr->Msr,
972 &MsrValue);
973
974 /* Return the data */
975 ReadMsr->DataValueLow = MsrValue.LowPart;
976 ReadMsr->DataValueHigh = MsrValue.HighPart;
977
978 /* Send the reply */
979 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
980 &Header,
981 NULL,
982 &KdpContext);
983 }
984
985 VOID
986 NTAPI
KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)987 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
988 IN PSTRING Data,
989 IN PCONTEXT Context)
990 {
991 STRING Header;
992 PDBGKD_READ_WRITE_MSR WriteMsr = &State->u.ReadWriteMsr;
993 LARGE_INTEGER MsrValue;
994
995 /* Setup the header */
996 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
997 Header.Buffer = (PCHAR)State;
998 ASSERT(Data->Length == 0);
999
1000 /* Call the internal routine */
1001 MsrValue.LowPart = WriteMsr->DataValueLow;
1002 MsrValue.HighPart = WriteMsr->DataValueHigh;
1003 State->ReturnStatus = KdpSysWriteMsr(WriteMsr->Msr,
1004 &MsrValue);
1005
1006 /* Send the reply */
1007 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1008 &Header,
1009 NULL,
1010 &KdpContext);
1011 }
1012
1013 VOID
1014 NTAPI
KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1015 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
1016 IN PSTRING Data,
1017 IN PCONTEXT Context)
1018 {
1019 STRING Header;
1020 PDBGKD_GET_SET_BUS_DATA GetBusData = &State->u.GetSetBusData;
1021 ULONG Length;
1022
1023 /* Setup the header */
1024 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1025 Header.Buffer = (PCHAR)State;
1026 ASSERT(Data->Length == 0);
1027
1028 /* Check the length requested */
1029 Length = GetBusData->Length;
1030 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
1031 {
1032 /* Use maximum allowed */
1033 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
1034 }
1035
1036 /* Call the internal routine */
1037 State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType,
1038 GetBusData->BusNumber,
1039 GetBusData->SlotNumber,
1040 GetBusData->Offset,
1041 Data->Buffer,
1042 Length,
1043 &Length);
1044
1045 /* Return the actual length read */
1046 GetBusData->Length = Length;
1047 Data->Length = (USHORT)Length;
1048
1049 /* Send the reply */
1050 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1051 &Header,
1052 Data,
1053 &KdpContext);
1054 }
1055
1056 VOID
1057 NTAPI
KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1058 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
1059 IN PSTRING Data,
1060 IN PCONTEXT Context)
1061 {
1062 STRING Header;
1063 PDBGKD_GET_SET_BUS_DATA SetBusData = &State->u.GetSetBusData;
1064 ULONG Length;
1065
1066 /* Setup the header */
1067 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1068 Header.Buffer = (PCHAR)State;
1069
1070 /* Call the internal routine */
1071 State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType,
1072 SetBusData->BusNumber,
1073 SetBusData->SlotNumber,
1074 SetBusData->Offset,
1075 Data->Buffer,
1076 SetBusData->Length,
1077 &Length);
1078
1079 /* Return the actual length written */
1080 SetBusData->Length = Length;
1081
1082 /* Send the reply */
1083 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1084 &Header,
1085 NULL,
1086 &KdpContext);
1087 }
1088
1089 VOID
1090 NTAPI
KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1091 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
1092 IN PSTRING Data,
1093 IN PCONTEXT Context)
1094 {
1095 STRING Header;
1096 PDBGKD_READ_WRITE_IO64 ReadIo = &State->u.ReadWriteIo;
1097
1098 /* Setup the header */
1099 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1100 Header.Buffer = (PCHAR)State;
1101 ASSERT(Data->Length == 0);
1102
1103 /*
1104 * Clear the value so 1 or 2 byte reads
1105 * don't leave the higher bits unmodified
1106 */
1107 ReadIo->DataValue = 0;
1108
1109 /* Call the internal routine */
1110 State->ReturnStatus = KdpSysReadIoSpace(Isa,
1111 0,
1112 1,
1113 ReadIo->IoAddress,
1114 &ReadIo->DataValue,
1115 ReadIo->DataSize,
1116 &ReadIo->DataSize);
1117
1118 /* Send the reply */
1119 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1120 &Header,
1121 NULL,
1122 &KdpContext);
1123 }
1124
1125 VOID
1126 NTAPI
KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1127 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
1128 IN PSTRING Data,
1129 IN PCONTEXT Context)
1130 {
1131 STRING Header;
1132 PDBGKD_READ_WRITE_IO64 WriteIo = &State->u.ReadWriteIo;
1133
1134 /* Setup the header */
1135 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1136 Header.Buffer = (PCHAR)State;
1137 ASSERT(Data->Length == 0);
1138
1139 /* Call the internal routine */
1140 State->ReturnStatus = KdpSysWriteIoSpace(Isa,
1141 0,
1142 1,
1143 WriteIo->IoAddress,
1144 &WriteIo->DataValue,
1145 WriteIo->DataSize,
1146 &WriteIo->DataSize);
1147
1148 /* Send the reply */
1149 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1150 &Header,
1151 NULL,
1152 &KdpContext);
1153 }
1154
1155 VOID
1156 NTAPI
KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1157 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
1158 IN PSTRING Data,
1159 IN PCONTEXT Context)
1160 {
1161 STRING Header;
1162 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended = &State->u.
1163 ReadWriteIoExtended;
1164
1165 /* Setup the header */
1166 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1167 Header.Buffer = (PCHAR)State;
1168 ASSERT(Data->Length == 0);
1169
1170 /*
1171 * Clear the value so 1 or 2 byte reads
1172 * don't leave the higher bits unmodified
1173 */
1174 ReadIoExtended->DataValue = 0;
1175
1176 /* Call the internal routine */
1177 State->ReturnStatus = KdpSysReadIoSpace(ReadIoExtended->InterfaceType,
1178 ReadIoExtended->BusNumber,
1179 ReadIoExtended->AddressSpace,
1180 ReadIoExtended->IoAddress,
1181 &ReadIoExtended->DataValue,
1182 ReadIoExtended->DataSize,
1183 &ReadIoExtended->DataSize);
1184
1185 /* Send the reply */
1186 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1187 &Header,
1188 NULL,
1189 &KdpContext);
1190 }
1191
1192 VOID
1193 NTAPI
KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1194 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
1195 IN PSTRING Data,
1196 IN PCONTEXT Context)
1197 {
1198 STRING Header;
1199 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended = &State->u.
1200 ReadWriteIoExtended;
1201
1202 /* Setup the header */
1203 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1204 Header.Buffer = (PCHAR)State;
1205 ASSERT(Data->Length == 0);
1206
1207 /* Call the internal routine */
1208 State->ReturnStatus = KdpSysWriteIoSpace(WriteIoExtended->InterfaceType,
1209 WriteIoExtended->BusNumber,
1210 WriteIoExtended->AddressSpace,
1211 WriteIoExtended->IoAddress,
1212 &WriteIoExtended->DataValue,
1213 WriteIoExtended->DataSize,
1214 &WriteIoExtended->DataSize);
1215
1216 /* Send the reply */
1217 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1218 &Header,
1219 NULL,
1220 &KdpContext);
1221 }
1222
1223 VOID
1224 NTAPI
KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State)1225 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State)
1226 {
1227 STRING Header;
1228
1229 /* Setup the header */
1230 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1231 Header.Buffer = (PCHAR)State;
1232
1233 /* Call the internal routine */
1234 State->ReturnStatus = KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE);
1235
1236 /* Send the reply */
1237 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1238 &Header,
1239 NULL,
1240 &KdpContext);
1241 }
1242
1243 VOID
1244 NTAPI
KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State)1245 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State)
1246 {
1247 STRING Header;
1248
1249 /* Set failure */
1250 State->ReturnStatus = STATUS_UNSUCCESSFUL;
1251
1252 /* Setup the packet */
1253 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1254 Header.Buffer = (PCHAR)State;
1255
1256 /* Send it */
1257 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1258 &Header,
1259 NULL,
1260 &KdpContext);
1261 }
1262
1263 static
1264 KCONTINUE_STATUS
KdpSwitchProcessor(_In_ USHORT ProcessorIndex)1265 KdpSwitchProcessor(
1266 _In_ USHORT ProcessorIndex)
1267 {
1268 /* Make sure that the processor index is valid */
1269 if (ProcessorIndex >= KeNumberProcessors)
1270 {
1271 KdpDprintf("%u is not a valid processor number\n", ProcessorIndex);
1272 return ContinueProcessorReselected;
1273 }
1274
1275 /* If the new processor is the current one, there is nothing to do */
1276 if (ProcessorIndex == KeGetCurrentProcessorNumber())
1277 {
1278 return ContinueProcessorReselected;
1279 }
1280
1281 /* Call the architecture specific Ke routine */
1282 return KxSwitchKdProcessor(ProcessorIndex);
1283 }
1284
1285 KCONTINUE_STATUS
1286 NTAPI
KdpSendWaitContinue(IN ULONG PacketType,IN PSTRING SendHeader,IN PSTRING SendData OPTIONAL,IN OUT PCONTEXT Context)1287 KdpSendWaitContinue(IN ULONG PacketType,
1288 IN PSTRING SendHeader,
1289 IN PSTRING SendData OPTIONAL,
1290 IN OUT PCONTEXT Context)
1291 {
1292 STRING Data, Header;
1293 DBGKD_MANIPULATE_STATE64 ManipulateState;
1294 ULONG Length;
1295 KDSTATUS RecvCode;
1296
1297 /* Setup the Manipulate State structure */
1298 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
1299 Header.Buffer = (PCHAR)&ManipulateState;
1300 Data.MaximumLength = sizeof(KdpMessageBuffer);
1301 Data.Buffer = KdpMessageBuffer;
1302
1303 /*
1304 * Reset the context state to ensure the debugger has received
1305 * the current context before it sets it.
1306 */
1307 KdpContextSent = FALSE;
1308
1309 SendPacket:
1310 /* Send the Packet */
1311 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
1312
1313 /* If the debugger isn't present anymore, just return success */
1314 if (KdDebuggerNotPresent) return ContinueSuccess;
1315
1316 /* Main processing Loop */
1317 for (;;)
1318 {
1319 /* Receive Loop */
1320 do
1321 {
1322 /* Wait to get a reply to our packet */
1323 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1324 &Header,
1325 &Data,
1326 &Length,
1327 &KdpContext);
1328
1329 /* If we got a resend request, do it */
1330 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
1331 } while (RecvCode == KdPacketTimedOut);
1332
1333 /* Now check what API we got */
1334 switch (ManipulateState.ApiNumber)
1335 {
1336 case DbgKdReadVirtualMemoryApi:
1337
1338 /* Read virtual memory */
1339 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
1340 break;
1341
1342 case DbgKdWriteVirtualMemoryApi:
1343
1344 /* Write virtual memory */
1345 KdpWriteVirtualMemory(&ManipulateState, &Data, Context);
1346 break;
1347
1348 case DbgKdGetContextApi:
1349
1350 /* Get the current context */
1351 KdpGetContext(&ManipulateState, &Data, Context);
1352 break;
1353
1354 case DbgKdSetContextApi:
1355
1356 /* Set a new context */
1357 KdpSetContext(&ManipulateState, &Data, Context);
1358 break;
1359
1360 case DbgKdWriteBreakPointApi:
1361
1362 /* Write the breakpoint */
1363 KdpWriteBreakpoint(&ManipulateState, &Data, Context);
1364 break;
1365
1366 case DbgKdRestoreBreakPointApi:
1367
1368 /* Restore the breakpoint */
1369 KdpRestoreBreakpoint(&ManipulateState, &Data, Context);
1370 break;
1371
1372 case DbgKdContinueApi:
1373
1374 /* Simply continue */
1375 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);
1376
1377 case DbgKdReadControlSpaceApi:
1378
1379 /* Read control space */
1380 KdpReadControlSpace(&ManipulateState, &Data, Context);
1381 break;
1382
1383 case DbgKdWriteControlSpaceApi:
1384
1385 /* Write control space */
1386 KdpWriteControlSpace(&ManipulateState, &Data, Context);
1387 break;
1388
1389 case DbgKdReadIoSpaceApi:
1390
1391 /* Read I/O Space */
1392 KdpReadIoSpace(&ManipulateState, &Data, Context);
1393 break;
1394
1395 case DbgKdWriteIoSpaceApi:
1396
1397 /* Write I/O Space */
1398 KdpWriteIoSpace(&ManipulateState, &Data, Context);
1399 break;
1400
1401 case DbgKdRebootApi:
1402
1403 /* Reboot the system */
1404 HalReturnToFirmware(HalRebootRoutine);
1405 break;
1406
1407 case DbgKdContinueApi2:
1408
1409 /* Check if caller reports success */
1410 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))
1411 {
1412 /* Update the state */
1413 KdpGetStateChange(&ManipulateState, Context);
1414 return ContinueSuccess;
1415 }
1416 else
1417 {
1418 /* Return an error */
1419 return ContinueError;
1420 }
1421
1422 case DbgKdReadPhysicalMemoryApi:
1423
1424 /* Read physical memory */
1425 KdpReadPhysicalMemory(&ManipulateState, &Data, Context);
1426 break;
1427
1428 case DbgKdWritePhysicalMemoryApi:
1429
1430 /* Write physical memory */
1431 KdpWritePhysicalMemory(&ManipulateState, &Data, Context);
1432 break;
1433
1434 case DbgKdQuerySpecialCallsApi:
1435 case DbgKdSetSpecialCallApi:
1436 case DbgKdClearSpecialCallsApi:
1437
1438 /* TODO */
1439 KdpDprintf("Special Call support is unimplemented!\n");
1440 KdpNotSupported(&ManipulateState);
1441 break;
1442
1443 case DbgKdSetInternalBreakPointApi:
1444 case DbgKdGetInternalBreakPointApi:
1445
1446 /* TODO */
1447 KdpDprintf("Internal Breakpoint support is unimplemented!\n");
1448 KdpNotSupported(&ManipulateState);
1449 break;
1450
1451 case DbgKdReadIoSpaceExtendedApi:
1452
1453 /* Read I/O Space */
1454 KdpReadIoSpaceExtended(&ManipulateState, &Data, Context);
1455 break;
1456
1457 case DbgKdWriteIoSpaceExtendedApi:
1458
1459 /* Write I/O Space */
1460 KdpWriteIoSpaceExtended(&ManipulateState, &Data, Context);
1461 break;
1462
1463 case DbgKdGetVersionApi:
1464
1465 /* Get version data */
1466 KdpGetVersion(&ManipulateState);
1467 break;
1468
1469 case DbgKdWriteBreakPointExApi:
1470
1471 /* Write the breakpoint and check if it failed */
1472 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState,
1473 &Data,
1474 Context)))
1475 {
1476 /* Return an error */
1477 return ContinueError;
1478 }
1479 break;
1480
1481 case DbgKdRestoreBreakPointExApi:
1482
1483 /* Restore the breakpoint */
1484 KdpRestoreBreakPointEx(&ManipulateState, &Data, Context);
1485 break;
1486
1487 case DbgKdCauseBugCheckApi:
1488
1489 /* Crash the system */
1490 KdpCauseBugCheck(&ManipulateState);
1491 break;
1492
1493 case DbgKdSwitchProcessor:
1494
1495 /* Switch the processor and return */
1496 return KdpSwitchProcessor(ManipulateState.Processor);
1497
1498 case DbgKdPageInApi:
1499
1500 /* TODO */
1501 KdpDprintf("Page-In support is unimplemented!\n");
1502 KdpNotSupported(&ManipulateState);
1503 break;
1504
1505 case DbgKdReadMachineSpecificRegister:
1506
1507 /* Read from the specified MSR */
1508 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context);
1509 break;
1510
1511 case DbgKdWriteMachineSpecificRegister:
1512
1513 /* Write to the specified MSR */
1514 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context);
1515 break;
1516
1517 case DbgKdSearchMemoryApi:
1518
1519 /* Search memory */
1520 KdpSearchMemory(&ManipulateState, &Data, Context);
1521 break;
1522
1523 case DbgKdGetBusDataApi:
1524
1525 /* Read from the bus */
1526 KdpGetBusData(&ManipulateState, &Data, Context);
1527 break;
1528
1529 case DbgKdSetBusDataApi:
1530
1531 /* Write to the bus */
1532 KdpSetBusData(&ManipulateState, &Data, Context);
1533 break;
1534
1535 case DbgKdCheckLowMemoryApi:
1536
1537 /* Check for memory corruption in the lower 4 GB */
1538 KdpCheckLowMemory(&ManipulateState);
1539 break;
1540
1541 case DbgKdClearAllInternalBreakpointsApi:
1542
1543 /* Just clear the counter */
1544 KdpNumInternalBreakpoints = 0;
1545 break;
1546
1547 case DbgKdFillMemoryApi:
1548
1549 /* Fill memory */
1550 KdpFillMemory(&ManipulateState, &Data, Context);
1551 break;
1552
1553 case DbgKdQueryMemoryApi:
1554
1555 /* Query memory */
1556 KdpQueryMemory(&ManipulateState, Context);
1557 break;
1558
1559 case DbgKdSwitchPartition:
1560
1561 /* TODO */
1562 KdpDprintf("Partition Switch support is unimplemented!\n");
1563 KdpNotSupported(&ManipulateState);
1564 break;
1565
1566 case DbgKdWriteCustomBreakpointApi:
1567
1568 /* Write the customized breakpoint */
1569 KdpWriteCustomBreakpoint(&ManipulateState, &Data, Context);
1570 break;
1571
1572 case DbgKdGetContextExApi:
1573
1574 /* Extended Context Get */
1575 KdpGetContextEx(&ManipulateState, &Data, Context);
1576 break;
1577
1578 case DbgKdSetContextExApi:
1579
1580 /* Extended Context Set */
1581 KdpSetContextEx(&ManipulateState, &Data, Context);
1582 break;
1583
1584 /* Unsupported Messages */
1585 default:
1586
1587 /* Send warning */
1588 KdpDprintf("Received Unrecognized API 0x%lx\n", ManipulateState.ApiNumber);
1589
1590 /* Setup an empty message, with failure */
1591 Data.Length = 0;
1592 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
1593
1594 /* Send it */
1595 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1596 &Header,
1597 &Data,
1598 &KdpContext);
1599 break;
1600 }
1601 }
1602 }
1603
1604 VOID
1605 NTAPI
KdpReportLoadSymbolsStateChange(IN PSTRING PathName,IN PKD_SYMBOLS_INFO SymbolInfo,IN BOOLEAN Unload,IN OUT PCONTEXT Context)1606 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
1607 IN PKD_SYMBOLS_INFO SymbolInfo,
1608 IN BOOLEAN Unload,
1609 IN OUT PCONTEXT Context)
1610 {
1611 PSTRING ExtraData;
1612 STRING Data, Header;
1613 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1614 ULONG PathNameLength;
1615 KCONTINUE_STATUS Status;
1616
1617 /* Start wait loop */
1618 do
1619 {
1620 /* Build the architecture common parts of the message */
1621 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
1622 Context,
1623 &WaitStateChange);
1624
1625 /* Now finish creating the structure */
1626 KdpSetContextState(&WaitStateChange, Context);
1627
1628 /* Fill out load data */
1629 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
1630 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll;
1631 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
1632 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
1633 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
1634
1635 /* Check if we have a path name */
1636 if (PathName)
1637 {
1638 /* Copy it to the path buffer */
1639 KdpCopyMemoryChunks((ULONG_PTR)PathName->Buffer,
1640 KdpPathBuffer,
1641 PathName->Length,
1642 0,
1643 MMDBG_COPY_UNSAFE,
1644 &PathNameLength);
1645
1646 /* Null terminate */
1647 KdpPathBuffer[PathNameLength++] = ANSI_NULL;
1648
1649 /* Set the path length */
1650 WaitStateChange.u.LoadSymbols.PathNameLength = PathNameLength;
1651
1652 /* Set up the data */
1653 Data.Buffer = KdpPathBuffer;
1654 Data.Length = (USHORT)PathNameLength;
1655 ExtraData = &Data;
1656 }
1657 else
1658 {
1659 /* No name */
1660 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
1661 ExtraData = NULL;
1662 }
1663
1664 /* Setup the header */
1665 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1666 Header.Buffer = (PCHAR)&WaitStateChange;
1667
1668 /* Send the packet */
1669 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1670 &Header,
1671 ExtraData,
1672 Context);
1673 } while (Status == ContinueProcessorReselected);
1674 }
1675
1676 VOID
1677 NTAPI
KdpReportCommandStringStateChange(IN PSTRING NameString,IN PSTRING CommandString,IN OUT PCONTEXT Context)1678 KdpReportCommandStringStateChange(IN PSTRING NameString,
1679 IN PSTRING CommandString,
1680 IN OUT PCONTEXT Context)
1681 {
1682 STRING Header, Data;
1683 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1684 ULONG Length, ActualLength, TotalLength;
1685 KCONTINUE_STATUS Status;
1686
1687 /* Start wait loop */
1688 do
1689 {
1690 /* Build the architecture common parts of the message */
1691 KdpSetCommonState(DbgKdCommandStringStateChange,
1692 Context,
1693 &WaitStateChange);
1694
1695 /* Set the context */
1696 KdpSetContextState(&WaitStateChange, Context);
1697
1698 /* Clear the command string structure */
1699 KdpZeroMemory(&WaitStateChange.u.CommandString,
1700 sizeof(DBGKD_COMMAND_STRING));
1701
1702 /* Normalize name string to max */
1703 Length = min(128 - 1, NameString->Length);
1704
1705 /* Copy it to the message buffer */
1706 KdpCopyMemoryChunks((ULONG_PTR)NameString->Buffer,
1707 KdpMessageBuffer,
1708 Length,
1709 0,
1710 MMDBG_COPY_UNSAFE,
1711 &ActualLength);
1712
1713 /* Null terminate and calculate the total length */
1714 TotalLength = ActualLength;
1715 KdpMessageBuffer[TotalLength++] = ANSI_NULL;
1716
1717 /* Check if the command string is too long */
1718 Length = CommandString->Length;
1719 if (Length > (PACKET_MAX_SIZE -
1720 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength))
1721 {
1722 /* Use maximum possible size */
1723 Length = (PACKET_MAX_SIZE -
1724 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength);
1725 }
1726
1727 /* Copy it to the message buffer */
1728 KdpCopyMemoryChunks((ULONG_PTR)CommandString->Buffer,
1729 KdpMessageBuffer + TotalLength,
1730 Length,
1731 0,
1732 MMDBG_COPY_UNSAFE,
1733 &ActualLength);
1734
1735 /* Null terminate and calculate the total length */
1736 TotalLength += ActualLength;
1737 KdpMessageBuffer[TotalLength++] = ANSI_NULL;
1738
1739 /* Now set up the header and the data */
1740 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1741 Header.Buffer = (PCHAR)&WaitStateChange;
1742 Data.Length = (USHORT)TotalLength;
1743 Data.Buffer = KdpMessageBuffer;
1744
1745 /* Send State Change packet and wait for a reply */
1746 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1747 &Header,
1748 &Data,
1749 Context);
1750 } while (Status == ContinueProcessorReselected);
1751 }
1752
1753 BOOLEAN
1754 NTAPI
KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,IN OUT PCONTEXT Context,IN BOOLEAN SecondChanceException)1755 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
1756 IN OUT PCONTEXT Context,
1757 IN BOOLEAN SecondChanceException)
1758 {
1759 STRING Header, Data;
1760 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1761 KCONTINUE_STATUS Status;
1762
1763 /* Start report loop */
1764 do
1765 {
1766 /* Build the architecture common parts of the message */
1767 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
1768
1769 #if !defined(_WIN64)
1770
1771 /* Convert it and copy it over */
1772 ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
1773 &WaitStateChange.u.Exception.ExceptionRecord);
1774
1775 #else
1776
1777 /* Just copy it directly, no need to convert */
1778 KdpMoveMemory(&WaitStateChange.u.Exception.ExceptionRecord,
1779 ExceptionRecord,
1780 sizeof(EXCEPTION_RECORD));
1781
1782 #endif
1783
1784 /* Set the First Chance flag */
1785 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
1786
1787 /* Now finish creating the structure */
1788 KdpSetContextState(&WaitStateChange, Context);
1789
1790 /* Setup the actual header to send to KD */
1791 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1792 Header.Buffer = (PCHAR)&WaitStateChange;
1793
1794 /* Setup the trace data */
1795 DumpTraceData(&Data);
1796
1797 /* Send State Change packet and wait for a reply */
1798 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1799 &Header,
1800 &Data,
1801 Context);
1802 } while (Status == ContinueProcessorReselected);
1803
1804 /* Return */
1805 return Status;
1806 }
1807
1808 KCONTINUE_STATUS
1809 NTAPI
KdReportProcessorChange(VOID)1810 KdReportProcessorChange(
1811 VOID)
1812 {
1813 PKPRCB CurrentPrcb = KeGetCurrentPrcb();
1814 PCONTEXT ContextRecord = &CurrentPrcb->ProcessorState.ContextFrame;
1815 EXCEPTION_RECORD ExceptionRecord = {0};
1816 KCONTINUE_STATUS Status;
1817
1818 /* Save the port data */
1819 KdSave(FALSE);
1820
1821 ExceptionRecord.ExceptionAddress = (PVOID)KeGetContextPc(ContextRecord);
1822 ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER;
1823
1824 /* Report the new state */
1825 Status = KdpReportExceptionStateChange(&ExceptionRecord,
1826 ContextRecord,
1827 FALSE);
1828
1829 /* Restore the port data */
1830 KdRestore(FALSE);
1831
1832 return Status;
1833 }
1834
1835 VOID
1836 NTAPI
KdpTimeSlipDpcRoutine(IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)1837 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1838 IN PVOID DeferredContext,
1839 IN PVOID SystemArgument1,
1840 IN PVOID SystemArgument2)
1841 {
1842 LONG OldSlip, NewSlip, PendingSlip;
1843
1844 /* Get the current pending slip */
1845 PendingSlip = KdpTimeSlipPending;
1846 do
1847 {
1848 /* Save the old value and either disable or enable it now. */
1849 OldSlip = PendingSlip;
1850 NewSlip = OldSlip > 1 ? 1 : 0;
1851
1852 /* Try to change the value */
1853 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1854 NewSlip,
1855 OldSlip) != OldSlip);
1856
1857 /* If the New Slip value is 1, then do the Time Slipping */
1858 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1859 }
1860
1861 VOID
1862 NTAPI
KdpTimeSlipWork(IN PVOID Context)1863 KdpTimeSlipWork(IN PVOID Context)
1864 {
1865 KIRQL OldIrql;
1866 LARGE_INTEGER DueTime;
1867
1868 /* Update the System time from the CMOS */
1869 ExAcquireTimeRefreshLock(FALSE);
1870 ExUpdateSystemTimeFromCmos(FALSE, 0);
1871 ExReleaseTimeRefreshLock();
1872
1873 /* Check if we have a registered Time Slip Event and signal it */
1874 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1875 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1876 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1877
1878 /* Delay the DPC until it runs next time */
1879 DueTime.QuadPart = -1800000000;
1880 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1881 }
1882
1883 LARGE_INTEGER
1884 NTAPI
KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)1885 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1886 {
1887 LARGE_INTEGER Null = {{0}};
1888
1889 /* Check if interrupts were disabled */
1890 if (!KeGetTrapFrameInterruptState(TrapFrame))
1891 {
1892 /* Nothing to return */
1893 return Null;
1894 }
1895
1896 /* Otherwise, do the call */
1897 return KeQueryPerformanceCounter(NULL);
1898 }
1899
1900 BOOLEAN
1901 NTAPI
KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,IN PKEXCEPTION_FRAME ExceptionFrame)1902 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1903 IN PKEXCEPTION_FRAME ExceptionFrame)
1904 {
1905 BOOLEAN Enable;
1906
1907 /* Check if we have a trap frame */
1908 if (TrapFrame)
1909 {
1910 /* Calculate the time difference for the enter */
1911 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1912 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1913 KdTimerStart.QuadPart;
1914 }
1915 else
1916 {
1917 /* No trap frame, so can't calculate */
1918 KdTimerStop.QuadPart = 0;
1919 }
1920
1921 /* Save the current IRQL */
1922 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1923
1924 /* Freeze all CPUs, raising also the IRQL to HIGH_LEVEL */
1925 Enable = KeFreezeExecution(TrapFrame, ExceptionFrame);
1926
1927 /* Lock the port, save the state and set debugger entered */
1928 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1929 KdSave(FALSE);
1930 KdEnteredDebugger = TRUE;
1931
1932 /* Check freeze flag */
1933 if (KiFreezeFlag & 1)
1934 {
1935 /* Print out errror */
1936 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1937 }
1938
1939 /* Check processor state */
1940 if (KiFreezeFlag & 2)
1941 {
1942 /* Print out errror */
1943 KdpDprintf("Some processors not frozen in debugger!\n");
1944 }
1945
1946 /* Make sure we acquired the port */
1947 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n");
1948
1949 /* Return if interrupts needs to be re-enabled */
1950 return Enable;
1951 }
1952
1953 VOID
1954 NTAPI
KdExitDebugger(IN BOOLEAN Enable)1955 KdExitDebugger(IN BOOLEAN Enable)
1956 {
1957 ULONG TimeSlip;
1958
1959 /* Restore the state and unlock the port */
1960 KdRestore(FALSE);
1961 if (KdpPortLocked) KdpPortUnlock();
1962
1963 /* Unfreeze the CPUs, restoring also the IRQL */
1964 KeThawExecution(Enable);
1965
1966 /* Compare time with the one from KdEnterDebugger */
1967 if (!KdTimerStop.QuadPart)
1968 {
1969 /* We didn't get a trap frame earlier in so never got the time */
1970 KdTimerStart = KdTimerStop;
1971 }
1972 else
1973 {
1974 /* Query the timer */
1975 KdTimerStart = KeQueryPerformanceCounter(NULL);
1976 }
1977
1978 /* Check if a Time Slip was on queue */
1979 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1980 if (TimeSlip == 1)
1981 {
1982 /* Queue a DPC for the time slip */
1983 InterlockedIncrement(&KdpTimeSlipPending);
1984 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL); // FIXME: this can trigger context switches!
1985 }
1986 }
1987
1988 NTSTATUS
1989 NTAPI
KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)1990 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)
1991 {
1992 KIRQL OldIrql;
1993
1994 #if defined(__GNUC__)
1995 /* Make gcc happy */
1996 OldIrql = PASSIVE_LEVEL;
1997 #endif
1998
1999 /* Check if enabling the debugger is blocked */
2000 if (KdBlockEnable)
2001 {
2002 /* It is, fail the enable */
2003 return STATUS_ACCESS_DENIED;
2004 }
2005
2006 /* Check if we need to acquire the lock */
2007 if (NeedLock)
2008 {
2009 /* Lock the port */
2010 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2011 KdpPortLock();
2012 }
2013
2014 /* Check if we're not disabled */
2015 if (!KdDisableCount)
2016 {
2017 /* Check if we had locked the port before */
2018 if (NeedLock)
2019 {
2020 /* Do the unlock */
2021 KdpPortUnlock();
2022 KeLowerIrql(OldIrql);
2023
2024 /* Fail: We're already enabled */
2025 return STATUS_INVALID_PARAMETER;
2026 }
2027 else
2028 {
2029 /*
2030 * This can only happen if we are called from a bugcheck
2031 * and were never initialized, so initialize the debugger now.
2032 */
2033 KdInitSystem(0, NULL);
2034
2035 /* Return success since we initialized */
2036 return STATUS_SUCCESS;
2037 }
2038 }
2039
2040 /* Decrease the disable count */
2041 if (!(--KdDisableCount))
2042 {
2043 /* We're now enabled again! Were we enabled before, too? */
2044 if (KdPreviouslyEnabled)
2045 {
2046 /* Reinitialize the Debugger */
2047 KdInitSystem(0, NULL);
2048 KdpRestoreAllBreakpoints();
2049 }
2050 }
2051
2052 /* Check if we had locked the port before */
2053 if (NeedLock)
2054 {
2055 /* Yes, now unlock it */
2056 KdpPortUnlock();
2057 KeLowerIrql(OldIrql);
2058 }
2059
2060 /* We're done */
2061 return STATUS_SUCCESS;
2062 }
2063
2064 NTSTATUS
2065 NTAPI
KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)2066 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)
2067 {
2068 KIRQL OldIrql;
2069 NTSTATUS Status;
2070
2071 #if defined(__GNUC__)
2072 /* Make gcc happy */
2073 OldIrql = PASSIVE_LEVEL;
2074 #endif
2075
2076 /*
2077 * If enabling the debugger is blocked
2078 * then there is nothing to disable (duh)
2079 */
2080 if (KdBlockEnable)
2081 {
2082 /* Fail */
2083 return STATUS_ACCESS_DENIED;
2084 }
2085
2086 /* Check if we need to acquire the lock */
2087 if (NeedLock)
2088 {
2089 /* Lock the port */
2090 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2091 KdpPortLock();
2092 }
2093
2094 /* Check if we're not disabled */
2095 if (!KdDisableCount)
2096 {
2097 /* Check if the debugger was never actually initialized */
2098 if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
2099 {
2100 /* It wasn't, so don't re-enable it later */
2101 KdPreviouslyEnabled = FALSE;
2102 }
2103 else
2104 {
2105 /* It was, so we will re-enable it later */
2106 KdPreviouslyEnabled = TRUE;
2107 }
2108
2109 /* Check if we were called from the exported API and are enabled */
2110 if ((NeedLock) && (KdPreviouslyEnabled))
2111 {
2112 /* Check if it is safe to disable the debugger */
2113 Status = KdpAllowDisable();
2114 if (!NT_SUCCESS(Status))
2115 {
2116 /* Release the lock and fail */
2117 KdpPortUnlock();
2118 KeLowerIrql(OldIrql);
2119 return Status;
2120 }
2121 }
2122
2123 /* Only disable the debugger if it is enabled */
2124 if (KdDebuggerEnabled)
2125 {
2126 /*
2127 * Disable the debugger; suspend breakpoints
2128 * and reset the debug stub
2129 */
2130 KdpSuspendAllBreakPoints();
2131 KiDebugRoutine = KdpStub;
2132
2133 /* We are disabled now */
2134 KdDebuggerEnabled = FALSE;
2135 SharedUserData->KdDebuggerEnabled = FALSE;
2136 }
2137 }
2138
2139 /* Increment the disable count */
2140 KdDisableCount++;
2141
2142 /* Check if we had locked the port before */
2143 if (NeedLock)
2144 {
2145 /* Yes, now unlock it */
2146 KdpPortUnlock();
2147 KeLowerIrql(OldIrql);
2148 }
2149
2150 /* We're done */
2151 return STATUS_SUCCESS;
2152 }
2153
2154 /* PUBLIC FUNCTIONS **********************************************************/
2155
2156 /*
2157 * @implemented
2158 */
2159 NTSTATUS
2160 NTAPI
KdEnableDebugger(VOID)2161 KdEnableDebugger(VOID)
2162 {
2163 /* Use the internal routine */
2164 return KdEnableDebuggerWithLock(TRUE);
2165 }
2166
2167 /*
2168 * @implemented
2169 */
2170 NTSTATUS
2171 NTAPI
KdDisableDebugger(VOID)2172 KdDisableDebugger(VOID)
2173 {
2174 /* Use the internal routine */
2175 return KdDisableDebuggerWithLock(TRUE);
2176 }
2177
2178 /*
2179 * @unimplemented
2180 */
2181 NTSTATUS
2182 NTAPI
KdSystemDebugControl(_In_ SYSDBG_COMMAND Command,_In_ PVOID InputBuffer,_In_ ULONG InputBufferLength,_Out_ PVOID OutputBuffer,_In_ ULONG OutputBufferLength,_Inout_ PULONG ReturnLength,_In_ KPROCESSOR_MODE PreviousMode)2183 KdSystemDebugControl(
2184 _In_ SYSDBG_COMMAND Command,
2185 _In_ PVOID InputBuffer,
2186 _In_ ULONG InputBufferLength,
2187 _Out_ PVOID OutputBuffer,
2188 _In_ ULONG OutputBufferLength,
2189 _Inout_ PULONG ReturnLength,
2190 _In_ KPROCESSOR_MODE PreviousMode)
2191 {
2192 /* Handle some internal commands */
2193 switch ((ULONG)Command)
2194 {
2195 #if DBG
2196 case ' soR': /* ROS-INTERNAL */
2197 {
2198 switch ((ULONG_PTR)InputBuffer)
2199 {
2200 case 0x21: // DumpAllThreads:
2201 PspDumpThreads(TRUE);
2202 break;
2203
2204 case 0x22: // DumpUserThreads:
2205 PspDumpThreads(FALSE);
2206 break;
2207
2208 case 0x24: // KdSpare3:
2209 MmDumpArmPfnDatabase(FALSE);
2210 break;
2211
2212 default:
2213 break;
2214 }
2215 return STATUS_SUCCESS;
2216 }
2217
2218 #if defined(_M_IX86) && !defined(_WINKD_) // See ke/i386/traphdlr.c
2219 /* Register a debug callback */
2220 case 'CsoR':
2221 {
2222 switch (InputBufferLength)
2223 {
2224 case ID_Win32PreServiceHook:
2225 KeWin32PreServiceHook = InputBuffer;
2226 break;
2227
2228 case ID_Win32PostServiceHook:
2229 KeWin32PostServiceHook = InputBuffer;
2230 break;
2231
2232 }
2233 break;
2234 }
2235 #endif
2236
2237 /* Special case for stack frame dumps */
2238 case 'DsoR':
2239 {
2240 KeRosDumpStackFrames((PULONG_PTR)InputBuffer, InputBufferLength);
2241 break;
2242 }
2243 #ifdef KDBG
2244 /* Register KDBG CLI callback */
2245 case 'RbdK':
2246 {
2247 return KdbRegisterCliCallback(InputBuffer, InputBufferLength);
2248 }
2249 #endif // KDBG
2250 #endif
2251 default:
2252 break;
2253 }
2254
2255 /* Local kernel debugging is not yet supported */
2256 DbgPrint("KdSystemDebugControl is unimplemented!\n");
2257 return STATUS_NOT_IMPLEMENTED;
2258 }
2259
2260 /*
2261 * @implemented
2262 */
2263 NTSTATUS
2264 NTAPI
KdChangeOption(IN KD_OPTION Option,IN ULONG InBufferBytes OPTIONAL,IN PVOID InBuffer,IN ULONG OutBufferBytes OPTIONAL,OUT PVOID OutBuffer,OUT PULONG OutBufferNeeded OPTIONAL)2265 KdChangeOption(IN KD_OPTION Option,
2266 IN ULONG InBufferBytes OPTIONAL,
2267 IN PVOID InBuffer,
2268 IN ULONG OutBufferBytes OPTIONAL,
2269 OUT PVOID OutBuffer,
2270 OUT PULONG OutBufferNeeded OPTIONAL)
2271 {
2272 /* Fail if there is no debugger */
2273 if (KdPitchDebugger)
2274 {
2275 /* No debugger, no options */
2276 return STATUS_DEBUGGER_INACTIVE;
2277 }
2278
2279 /* Do we recognize this option? */
2280 if (Option != KD_OPTION_SET_BLOCK_ENABLE)
2281 {
2282 /* We don't, clear the output length and fail */
2283 if (OutBufferNeeded) *OutBufferNeeded = 0;
2284 return STATUS_INVALID_INFO_CLASS;
2285 }
2286
2287 /* Verify parameters */
2288 if ((InBufferBytes != sizeof(BOOLEAN)) ||
2289 (OutBufferBytes != 0) ||
2290 (OutBuffer != NULL))
2291 {
2292 /* Invalid parameters for this option, fail */
2293 return STATUS_INVALID_PARAMETER;
2294 }
2295
2296 /*
2297 * Check if the high bit is set, meaning we don't
2298 * allow the debugger to be enabled
2299 */
2300 if (KdBlockEnable & 0x80)
2301 {
2302 /* Fail regardless of what state the caller tried to set */
2303 return STATUS_ACCESS_VIOLATION;
2304 }
2305
2306 /* Set the new block enable state */
2307 KdBlockEnable = *(PBOOLEAN)InBuffer;
2308
2309 /* No output buffer required for this option */
2310 if (OutBufferNeeded) *OutBufferNeeded = 0;
2311
2312 /* We are done */
2313 return STATUS_SUCCESS;
2314 }
2315
2316 /*
2317 * @implemented
2318 */
2319 NTSTATUS
2320 NTAPI
KdPowerTransition(IN DEVICE_POWER_STATE NewState)2321 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
2322 {
2323 /* Check what power state this is */
2324 if (NewState == PowerDeviceD0)
2325 {
2326 /* Wake up the debug port */
2327 KdD0Transition();
2328 return STATUS_SUCCESS;
2329 }
2330 else if ((NewState == PowerDeviceD1) ||
2331 (NewState == PowerDeviceD2) ||
2332 (NewState == PowerDeviceD3))
2333 {
2334 /* Power down the debug port */
2335 KdD3Transition();
2336 return STATUS_SUCCESS;
2337 }
2338 else
2339 {
2340 /* Invalid state! */
2341 return STATUS_INVALID_PARAMETER_1;
2342 }
2343 }
2344
2345 /*
2346 * @implemented
2347 */
2348 BOOLEAN
2349 NTAPI
KdRefreshDebuggerNotPresent(VOID)2350 KdRefreshDebuggerNotPresent(VOID)
2351 {
2352 BOOLEAN Enable, DebuggerNotPresent;
2353
2354 /* Check if the debugger is completely disabled */
2355 if (KdPitchDebugger)
2356 {
2357 /* Don't try to refresh then, fail early */
2358 return TRUE;
2359 }
2360
2361 /* Enter the debugger */
2362 Enable = KdEnterDebugger(NULL, NULL);
2363
2364 /*
2365 * Attempt to send a string to the debugger
2366 * to refresh the connection state.
2367 */
2368 KdpDprintf("KDTARGET: Refreshing KD connection\n");
2369
2370 /* Save the state while we are holding the lock */
2371 DebuggerNotPresent = KdDebuggerNotPresent;
2372
2373 /* Exit the debugger and return the state */
2374 KdExitDebugger(Enable);
2375 return DebuggerNotPresent;
2376 }
2377
2378 /*
2379 * @implemented
2380 */
2381 NTSTATUS
2382 NTAPI
NtQueryDebugFilterState(_In_ ULONG ComponentId,_In_ ULONG Level)2383 NtQueryDebugFilterState(
2384 _In_ ULONG ComponentId,
2385 _In_ ULONG Level)
2386 {
2387 PULONG Mask;
2388
2389 /* Check if the ID fits in the component table */
2390 if (ComponentId < KdComponentTableSize)
2391 {
2392 /* It does, so get the mask from there */
2393 Mask = KdComponentTable[ComponentId];
2394 }
2395 else if (ComponentId == MAXULONG)
2396 {
2397 /*
2398 * This is the internal ID used for DbgPrint messages without ID
2399 * and Level. Use the system-wide mask for those.
2400 */
2401 Mask = &Kd_WIN2000_Mask;
2402 }
2403 else
2404 {
2405 #if (NTDDI_VERSION >= NTDDI_VISTA)
2406 /* Use the default component ID */
2407 Mask = &Kd_DEFAULT_Mask;
2408 // Level = DPFLTR_INFO_LEVEL; // Override the Level.
2409 #else
2410 /* Invalid ID, fail */
2411 return STATUS_INVALID_PARAMETER_1;
2412 #endif
2413 }
2414
2415 /* Convert Level to bit field if required */
2416 if (Level < 32) Level = 1 << Level;
2417 Level &= ~DPFLTR_MASK;
2418
2419 /* Determine if this Level is filtered out */
2420 if ((Kd_WIN2000_Mask & Level) || (*Mask & Level))
2421 {
2422 /* This mask will get through to the debugger */
2423 return (NTSTATUS)TRUE;
2424 }
2425 else
2426 {
2427 /* This mask is filtered out */
2428 return (NTSTATUS)FALSE;
2429 }
2430 }
2431
2432 /*
2433 * @implemented
2434 */
2435 NTSTATUS
2436 NTAPI
NtSetDebugFilterState(_In_ ULONG ComponentId,_In_ ULONG Level,_In_ BOOLEAN State)2437 NtSetDebugFilterState(
2438 _In_ ULONG ComponentId,
2439 _In_ ULONG Level,
2440 _In_ BOOLEAN State)
2441 {
2442 PULONG Mask;
2443
2444 /* Modifying debug filters requires the debug privilege */
2445 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode()))
2446 {
2447 /* Fail */
2448 return STATUS_ACCESS_DENIED;
2449 }
2450
2451 /* Check if the ID fits in the component table */
2452 if (ComponentId < KdComponentTableSize)
2453 {
2454 /* It does, so get the mask from there */
2455 Mask = KdComponentTable[ComponentId];
2456 }
2457 else if (ComponentId == MAXULONG)
2458 {
2459 /*
2460 * This is the internal ID used for DbgPrint messages without ID
2461 * and Level. Use the system-wide mask for those.
2462 */
2463 Mask = &Kd_WIN2000_Mask;
2464 }
2465 else
2466 {
2467 #if (NTDDI_VERSION >= NTDDI_VISTA)
2468 /* Use the default component ID */
2469 Mask = &Kd_DEFAULT_Mask;
2470 #else
2471 /* Invalid ID, fail */
2472 return STATUS_INVALID_PARAMETER_1;
2473 #endif
2474 }
2475
2476 /* Convert Level to bit field if required */
2477 if (Level < 32) Level = 1 << Level;
2478 Level &= ~DPFLTR_MASK;
2479
2480 /* Set or remove the Level */
2481 if (State)
2482 *Mask |= Level;
2483 else
2484 *Mask &= ~Level;
2485
2486 return STATUS_SUCCESS;
2487 }
2488