KD64: remove some FrLdrDbgPrints, fix a warning.
[reactos.git] / reactos / ntoskrnl / kd64 / kdapi.c
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 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PRIVATE FUNCTIONS *********************************************************/
16
17 VOID
18 NTAPI
19 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,
20 IN PCONTEXT Context)
21 {
22 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;
23 STRING Header;
24 NTSTATUS Status = STATUS_SUCCESS;
25
26 /* Validate the address space */
27 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)
28 {
29 /* Check if this is process memory */
30 if ((PVOID)(LONG_PTR)Memory->Address < MmHighestUserAddress)
31 {
32 /* It is */
33 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
34 }
35 else
36 {
37 /* FIXME: Check if it's session space */
38 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
39 }
40
41 /* Set flags */
42 Memory->Flags = DBGKD_QUERY_MEMORY_READ |
43 DBGKD_QUERY_MEMORY_WRITE |
44 DBGKD_QUERY_MEMORY_EXECUTE;
45 }
46 else
47 {
48 /* Invalid */
49 Status = STATUS_INVALID_PARAMETER;
50 }
51
52 /* Return structure */
53 State->ReturnStatus = Status;
54 Memory->Reserved = 0;
55
56 /* Build header */
57 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
58 Header.Buffer = (PCHAR)State;
59
60 /* Send the packet */
61 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
62 &Header,
63 NULL,
64 &KdpContext);
65 }
66
67 VOID
68 NTAPI
69 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
70 IN PSTRING Data,
71 IN PCONTEXT Context)
72 {
73 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
74 STRING Header;
75
76 /* Build header */
77 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
78 Header.Buffer = (PCHAR)State;
79 ASSERT(Data->Length == 0);
80
81 /* Create the breakpoint */
82 Breakpoint->BreakPointHandle =
83 KdpAddBreakpoint((PVOID)(LONG_PTR)Breakpoint->BreakPointAddress);
84 if (!Breakpoint->BreakPointHandle)
85 {
86 /* We failed */
87 State->ReturnStatus = STATUS_UNSUCCESSFUL;
88 }
89 else
90 {
91 /* Success! */
92 State->ReturnStatus = STATUS_SUCCESS;
93 }
94
95 /* Send the packet */
96 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
97 &Header,
98 NULL,
99 &KdpContext);
100 }
101
102 VOID
103 NTAPI
104 DumpTraceData(OUT PSTRING TraceData)
105 {
106 /* Update the buffer */
107 TraceDataBuffer[0] = TraceDataBufferPosition;
108
109 /* Setup the trace data */
110 TraceData->Length = TraceDataBufferPosition * sizeof(ULONG);
111 TraceData->Buffer = (PCHAR)TraceDataBuffer;
112
113 /* Reset the buffer location */
114 TraceDataBufferPosition = 1;
115 }
116
117 VOID
118 NTAPI
119 KdpGetStateChange(IN PDBGKD_MANIPULATE_STATE64 State,
120 IN PCONTEXT Context)
121 {
122 PKPRCB Prcb;
123 ULONG i;
124
125 /* Check for success */
126 if (NT_SUCCESS(State->u.Continue2.ContinueStatus))
127 {
128 /* Check if we're tracing */
129 if (State->u.Continue2.ControlSet.TraceFlag)
130 {
131 /* Enable TF */
132 Context->EFlags |= EFLAGS_TF;
133 }
134 else
135 {
136 /* Remove it */
137 Context->EFlags &= ~EFLAGS_TF;
138 }
139
140 /* Loop all processors */
141 for (i = 0; i < KeNumberProcessors; i++)
142 {
143 /* Get the PRCB and update DR7 and DR6 */
144 Prcb = KiProcessorBlock[i];
145 Prcb->ProcessorState.SpecialRegisters.KernelDr7 =
146 State->u.Continue2.ControlSet.Dr7;
147 Prcb->ProcessorState.SpecialRegisters.KernelDr6 = 0;
148 }
149
150 /* Check if we have new symbol information */
151 if (State->u.Continue2.ControlSet.CurrentSymbolStart != 1)
152 {
153 /* Update it */
154 KdpCurrentSymbolStart =
155 State->u.Continue2.ControlSet.CurrentSymbolStart;
156 KdpCurrentSymbolEnd= State->u.Continue2.ControlSet.CurrentSymbolEnd;
157 }
158 }
159 }
160
161 VOID
162 NTAPI
163 KdpSetCommonState(IN ULONG NewState,
164 IN PCONTEXT Context,
165 OUT PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange)
166 {
167 USHORT InstructionCount;
168 BOOLEAN HadBreakpoints;
169
170 /* Setup common stuff available for all CPU architectures */
171 WaitStateChange->NewState = NewState;
172 WaitStateChange->ProcessorLevel = KeProcessorLevel;
173 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
174 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
175 WaitStateChange->Thread = (LONG_PTR)KeGetCurrentThread();
176 #if defined(_M_X86_)
177 WaitStateChange->ProgramCounter = (ULONG)(LONG_PTR)Context->Eip;
178 #elif defined(_M_AMD64)
179 WaitStateChange->ProgramCounter = (LONG_PTR)Context->Rip;
180 #else
181 #error Unknown platform
182 #endif
183
184 /* Zero out the Control Report */
185 RtlZeroMemory(&WaitStateChange->ControlReport,
186 sizeof(DBGKD_CONTROL_REPORT));
187
188 /* Now copy the instruction stream and set the count */
189 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
190 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
191 DBGKD_MAXSTREAM);
192 InstructionCount = DBGKD_MAXSTREAM;
193 WaitStateChange->ControlReport.InstructionCount = InstructionCount;
194
195 /* Clear all the breakpoints in this region */
196 HadBreakpoints =
197 KdpDeleteBreakpointRange((PVOID)(LONG_PTR)WaitStateChange->ProgramCounter,
198 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
199 WaitStateChange->ControlReport.InstructionCount - 1));
200 if (HadBreakpoints)
201 {
202 /* Copy the instruction stream again, this time without breakpoints */
203 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
204 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
205 WaitStateChange->ControlReport.InstructionCount);
206 }
207 }
208
209 VOID
210 NTAPI
211 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
212 {
213 STRING Header;
214
215 /* Fill out the header */
216 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
217 Header.Buffer = (PCHAR)State;
218
219 /* Get the version block */
220 KdpSysGetVersion(&State->u.GetVersion64);
221
222 /* Fill out the state */
223 State->ApiNumber = DbgKdGetVersionApi;
224 State->ReturnStatus = STATUS_SUCCESS;
225
226 /* Send the packet */
227 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
228 &Header,
229 NULL,
230 &KdpContext);
231 }
232
233 VOID
234 NTAPI
235 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
236 IN PSTRING Data,
237 IN PCONTEXT Context)
238 {
239 STRING Header;
240 ULONG Length = State->u.ReadMemory.TransferCount;
241 NTSTATUS Status = STATUS_SUCCESS;
242 ULONG64 TargetBaseAddress = State->u.ReadMemory.TargetBaseAddress;
243
244 /* Validate length */
245 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
246 {
247 /* Overflow, set it to maximum possible */
248 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
249 }
250
251 #if 0
252 if (!MmIsAddressValid((PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress))
253 {
254 Ke386SetCr2(State->u.ReadMemory.TargetBaseAddress);
255 while (TRUE);
256 }
257 #endif
258
259 // HACK for x64, until KD stops sending bogus addresses to WinDbg
260 if (TargetBaseAddress < (ULONG_PTR)MM_LOWEST_SYSTEM_ADDRESS)
261 {
262 FrLdrDbgPrint("Trying to read memory at 0x%p\n", TargetBaseAddress);
263 // DPRINT1("Trying to read memory at 0x%p\n", TargetBaseAddress);
264 TargetBaseAddress = 0;
265 }
266
267 if (!TargetBaseAddress)
268 {
269 Length = 0;
270 Status = STATUS_UNSUCCESSFUL;
271 }
272 else
273 {
274 RtlCopyMemory(Data->Buffer,
275 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress,
276 Length);
277 }
278
279 /* Fill out the header */
280 Data->Length = Length;
281 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
282 Header.Buffer = (PCHAR)State;
283
284 /* Fill out the state */
285 State->ReturnStatus = Status;
286 State->u.ReadMemory.ActualBytesRead = Length;
287
288 /* Send the packet */
289 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
290 &Header,
291 Data,
292 &KdpContext);
293 }
294
295 VOID
296 NTAPI
297 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
298 IN PSTRING Data,
299 IN PCONTEXT Context)
300 {
301 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
302 STRING Header;
303 ULONG Length, RealLength;
304 PVOID ControlStart;
305
306 /* Setup the header */
307 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
308 Header.Buffer = (PCHAR)State;
309 ASSERT(Data->Length == 0);
310
311 /* Check the length requested */
312 Length = ReadMemory->TransferCount;
313 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
314 {
315 /* Use maximum allowed */
316 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
317 }
318
319 #if defined (_M_AMD64)
320 if ((ULONG)ReadMemory->TargetBaseAddress <= 2)
321 {
322 switch ((ULONG_PTR)ReadMemory->TargetBaseAddress)
323 {
324 case 1:
325 ControlStart = &KiProcessorBlock[State->Processor];
326 RealLength = sizeof(PVOID);
327 break;
328
329 case 2:
330 ControlStart = &KiProcessorBlock[State->Processor]->
331 ProcessorState.SpecialRegisters;
332 RealLength = sizeof(KSPECIAL_REGISTERS);
333 break;
334
335 default:
336 RealLength = 0;
337 ControlStart = NULL;
338 ASSERT(FALSE);
339 }
340
341 if (RealLength < Length) Length = RealLength;
342
343 /* Copy the memory */
344 RtlCopyMemory(Data->Buffer, ControlStart, Length);
345 Data->Length = Length;
346
347 /* Finish up */
348 State->ReturnStatus = STATUS_SUCCESS;
349 ReadMemory->ActualBytesRead = Data->Length;
350 }
351 #else
352 /* Make sure that this is a valid request */
353 if (((ULONG)ReadMemory->TargetBaseAddress < sizeof(KPROCESSOR_STATE)) &&
354 (State->Processor < KeNumberProcessors))
355 {
356 /* Get the actual length */
357 RealLength = sizeof(KPROCESSOR_STATE) -
358 (ULONG_PTR)ReadMemory->TargetBaseAddress;
359 if (RealLength < Length) Length = RealLength;
360
361 /* Set the proper address */
362 ControlStart = (PVOID)((ULONG_PTR)ReadMemory->TargetBaseAddress +
363 (ULONG_PTR)&KiProcessorBlock[State->Processor]->
364 ProcessorState);
365
366 /* Copy the memory */
367 RtlCopyMemory(Data->Buffer, ControlStart, Length);
368 Data->Length = Length;
369
370 /* Finish up */
371 State->ReturnStatus = STATUS_SUCCESS;
372 ReadMemory->ActualBytesRead = Data->Length;
373 }
374 #endif
375 else
376 {
377 /* Invalid request */
378 Data->Length = 0;
379 State->ReturnStatus = STATUS_UNSUCCESSFUL;
380 ReadMemory->ActualBytesRead = 0;
381 }
382
383 /* Send the reply */
384 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
385 &Header,
386 Data,
387 &KdpContext);
388 }
389
390 VOID
391 NTAPI
392 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
393 IN PSTRING Data,
394 IN PCONTEXT Context)
395 {
396 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
397 STRING Header;
398 ULONG Length;
399 PVOID ControlStart;
400
401 /* Setup the header */
402 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
403 Header.Buffer = (PCHAR)State;
404
405 /* Make sure that this is a valid request */
406 Length = WriteMemory->TransferCount;
407 if ((((ULONG)WriteMemory->TargetBaseAddress + Length) <=
408 sizeof(KPROCESSOR_STATE)) &&
409 (State->Processor < KeNumberProcessors))
410 {
411 /* Set the proper address */
412 ControlStart = (PVOID)((ULONG_PTR)WriteMemory->TargetBaseAddress +
413 (ULONG_PTR)&KiProcessorBlock[State->Processor]->
414 ProcessorState);
415
416 /* Copy the memory */
417 RtlCopyMemory(ControlStart, Data->Buffer, Data->Length);
418 Length = Data->Length;
419
420 /* Finish up */
421 State->ReturnStatus = STATUS_SUCCESS;
422 WriteMemory->ActualBytesWritten = Length;
423 }
424 else
425 {
426 /* Invalid request */
427 Data->Length = 0;
428 State->ReturnStatus = STATUS_UNSUCCESSFUL;
429 WriteMemory->ActualBytesWritten = 0;
430 }
431
432 /* Send the reply */
433 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
434 &Header,
435 Data,
436 &KdpContext);
437 }
438
439 VOID
440 NTAPI
441 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
442 IN PSTRING Data,
443 IN PCONTEXT Context)
444 {
445 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
446 STRING Header;
447
448 /* Fill out the header */
449 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
450 Header.Buffer = (PCHAR)State;
451 ASSERT(Data->Length == 0);
452
453 /* Get the version block */
454 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
455 {
456 /* We're all good */
457 State->ReturnStatus = STATUS_SUCCESS;
458 }
459 else
460 {
461 /* We failed */
462 State->ReturnStatus = STATUS_UNSUCCESSFUL;
463 }
464
465 /* Send the packet */
466 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
467 &Header,
468 NULL,
469 &KdpContext);
470 }
471
472 VOID
473 NTAPI
474 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
475 IN PSTRING Data,
476 IN PCONTEXT Context)
477 {
478 STRING Header;
479 PVOID ControlStart;
480
481 /* Setup the header */
482 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
483 Header.Buffer = (PCHAR)State;
484 ASSERT(Data->Length == 0);
485
486 /* Make sure that this is a valid request */
487 if (State->Processor < KeNumberProcessors)
488 {
489 /* Check if the request is for this CPU */
490 if (State->Processor == KeGetCurrentPrcb()->Number)
491 {
492 /* We're just copying our own context */
493 ControlStart = Context;
494 }
495 else
496 {
497 /* SMP not yet handled */
498 ControlStart = NULL;
499 while (TRUE);
500 }
501
502 /* Copy the memory */
503 RtlCopyMemory(Data->Buffer, ControlStart, sizeof(CONTEXT));
504 Data->Length = sizeof(CONTEXT);
505
506 /* Finish up */
507 State->ReturnStatus = STATUS_SUCCESS;
508 }
509 else
510 {
511 /* Invalid request */
512 State->ReturnStatus = STATUS_UNSUCCESSFUL;
513 }
514
515 /* Send the reply */
516 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
517 &Header,
518 Data,
519 &KdpContext);
520 }
521
522 VOID
523 NTAPI
524 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
525 IN PSTRING Data,
526 IN PCONTEXT Context)
527 {
528 STRING Header;
529 PVOID ControlStart;
530
531 /* Setup the header */
532 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
533 Header.Buffer = (PCHAR)State;
534 ASSERT(Data->Length == sizeof(CONTEXT));
535
536 /* Make sure that this is a valid request */
537 if (State->Processor < KeNumberProcessors)
538 {
539 /* Check if the request is for this CPU */
540 if (State->Processor == KeGetCurrentPrcb()->Number)
541 {
542 /* We're just copying our own context */
543 ControlStart = Context;
544 }
545 else
546 {
547 /* SMP not yet handled */
548 ControlStart = NULL;
549 while (TRUE);
550 }
551
552 /* Copy the memory */
553 RtlCopyMemory(ControlStart, Data->Buffer, sizeof(CONTEXT));
554
555 /* Finish up */
556 State->ReturnStatus = STATUS_SUCCESS;
557 }
558 else
559 {
560 /* Invalid request */
561 State->ReturnStatus = STATUS_UNSUCCESSFUL;
562 }
563
564 /* Send the reply */
565 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
566 &Header,
567 Data,
568 &KdpContext);
569 }
570
571 KCONTINUE_STATUS
572 NTAPI
573 KdpSendWaitContinue(IN ULONG PacketType,
574 IN PSTRING SendHeader,
575 IN PSTRING SendData OPTIONAL,
576 IN OUT PCONTEXT Context)
577 {
578 STRING Data, Header;
579 DBGKD_MANIPULATE_STATE64 ManipulateState;
580 ULONG Length;
581 KDSTATUS RecvCode;
582
583 /* Setup the Manipulate State structure */
584 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
585 Header.Buffer = (PCHAR)&ManipulateState;
586 Data.MaximumLength = sizeof(KdpMessageBuffer);
587 Data.Buffer = KdpMessageBuffer;
588 //KdpContextSent = FALSE;
589
590 SendPacket:
591 /* Send the Packet */
592 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
593
594 /* If the debugger isn't present anymore, just return success */
595 if (KdDebuggerNotPresent) return ContinueSuccess;
596
597 /* Main processing Loop */
598 for (;;)
599 {
600 /* Receive Loop */
601 do
602 {
603 /* Wait to get a reply to our packet */
604 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
605 &Header,
606 &Data,
607 &Length,
608 &KdpContext);
609
610 /* If we got a resend request, do it */
611 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
612 } while (RecvCode == KdPacketTimedOut);
613
614 /* Now check what API we got */
615 switch (ManipulateState.ApiNumber)
616 {
617 case DbgKdReadVirtualMemoryApi:
618
619 /* Read virtual memory */
620 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
621 break;
622
623 case DbgKdWriteVirtualMemoryApi:
624
625 /* FIXME: TODO */
626 Ke386SetCr2(DbgKdWriteVirtualMemoryApi);
627 while (TRUE);
628 break;
629
630 case DbgKdGetContextApi:
631
632 /* Get the current context */
633 KdpGetContext(&ManipulateState, &Data, Context);
634 break;
635
636 case DbgKdSetContextApi:
637
638 /* Set a new context */
639 KdpSetContext(&ManipulateState, &Data, Context);
640 break;
641
642 case DbgKdWriteBreakPointApi:
643
644 /* Write the breakpoint */
645 KdpWriteBreakpoint(&ManipulateState, &Data, Context);
646 break;
647
648 case DbgKdRestoreBreakPointApi:
649
650 /* FIXME: TODO */
651 KdpRestoreBreakpoint(&ManipulateState, &Data, Context);
652 break;
653
654 case DbgKdContinueApi:
655
656 /* Simply continue */
657 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);
658
659 case DbgKdReadControlSpaceApi:
660
661 /* Read control space */
662 KdpReadControlSpace(&ManipulateState, &Data, Context);
663 break;
664
665 case DbgKdWriteControlSpaceApi:
666
667 /* FIXME: TODO */
668 KdpWriteControlSpace(&ManipulateState, &Data, Context);
669 break;
670
671 case DbgKdReadIoSpaceApi:
672
673 /* FIXME: TODO */
674 Ke386SetCr2(DbgKdReadIoSpaceApi);
675 while (TRUE);
676 break;
677
678 case DbgKdWriteIoSpaceApi:
679
680 /* FIXME: TODO */
681 Ke386SetCr2(DbgKdWriteIoSpaceApi);
682 while (TRUE);
683 break;
684
685 case DbgKdRebootApi:
686
687 /* FIXME: TODO */
688 Ke386SetCr2(DbgKdRebootApi);
689 while (TRUE);
690 break;
691
692 case DbgKdContinueApi2:
693
694 /* Check if caller reports success */
695 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))
696 {
697 /* Update the state */
698 KdpGetStateChange(&ManipulateState, Context);
699 return ContinueSuccess;
700 }
701 else
702 {
703 /* Return an error */
704 return ContinueError;
705 }
706 break;
707
708 case DbgKdReadPhysicalMemoryApi:
709
710 /* FIXME: TODO */
711 goto fail;
712 Ke386SetCr2(DbgKdReadPhysicalMemoryApi);
713 while (TRUE);
714 break;
715
716 case DbgKdWritePhysicalMemoryApi:
717
718 /* FIXME: TODO */
719 Ke386SetCr2(DbgKdWritePhysicalMemoryApi);
720 while (TRUE);
721 break;
722
723 case DbgKdQuerySpecialCallsApi:
724
725 /* FIXME: TODO */
726 Ke386SetCr2(DbgKdQuerySpecialCallsApi);
727 while (TRUE);
728 break;
729
730 case DbgKdSetSpecialCallApi:
731
732 /* FIXME: TODO */
733 Ke386SetCr2(DbgKdSetSpecialCallApi);
734 while (TRUE);
735 break;
736
737 case DbgKdClearSpecialCallsApi:
738
739 /* FIXME: TODO */
740 Ke386SetCr2(DbgKdClearSpecialCallsApi);
741 while (TRUE);
742 break;
743
744 case DbgKdSetInternalBreakPointApi:
745
746 /* FIXME: TODO */
747 Ke386SetCr2(DbgKdSetInternalBreakPointApi);
748 while (TRUE);
749 break;
750
751 case DbgKdGetInternalBreakPointApi:
752
753 /* FIXME: TODO */
754 Ke386SetCr2(DbgKdGetInternalBreakPointApi);
755 while (TRUE);
756 break;
757
758 case DbgKdReadIoSpaceExtendedApi:
759
760 /* FIXME: TODO */
761 Ke386SetCr2(DbgKdReadIoSpaceExtendedApi);
762 while (TRUE);
763 break;
764
765 case DbgKdWriteIoSpaceExtendedApi:
766
767 /* FIXME: TODO */
768 Ke386SetCr2(DbgKdWriteIoSpaceExtendedApi);
769 while (TRUE);
770 break;
771
772 case DbgKdGetVersionApi:
773
774 /* Get version data */
775 KdpGetVersion(&ManipulateState);
776 break;
777
778 case DbgKdWriteBreakPointExApi:
779
780 /* FIXME: TODO */
781 Ke386SetCr2(DbgKdWriteBreakPointExApi);
782 while (TRUE);
783 break;
784
785 case DbgKdRestoreBreakPointExApi:
786
787 /* FIXME: TODO */
788 Ke386SetCr2(DbgKdRestoreBreakPointExApi);
789 while (TRUE);
790 break;
791
792 case DbgKdCauseBugCheckApi:
793
794 /* FIXME: TODO */
795 Ke386SetCr2(DbgKdCauseBugCheckApi);
796 while (TRUE);
797 break;
798
799 case DbgKdSwitchProcessor:
800
801 /* FIXME: TODO */
802 Ke386SetCr2(DbgKdSwitchProcessor);
803 while (TRUE);
804 break;
805
806 case DbgKdPageInApi:
807
808 /* FIXME: TODO */
809 Ke386SetCr2(DbgKdPageInApi);
810 while (TRUE);
811 break;
812
813 case DbgKdReadMachineSpecificRegister:
814
815 /* FIXME: TODO */
816 Ke386SetCr2(DbgKdReadMachineSpecificRegister);
817 while (TRUE);
818 break;
819
820 case DbgKdWriteMachineSpecificRegister:
821
822 /* FIXME: TODO */
823 Ke386SetCr2(DbgKdWriteMachineSpecificRegister);
824 while (TRUE);
825 break;
826
827 case OldVlm1:
828
829 /* FIXME: TODO */
830 Ke386SetCr2(OldVlm1);
831 while (TRUE);
832 break;
833
834 case OldVlm2:
835
836 /* FIXME: TODO */
837 Ke386SetCr2(OldVlm2);
838 while (TRUE);
839 break;
840
841 case DbgKdSearchMemoryApi:
842
843 /* FIXME: TODO */
844 Ke386SetCr2(DbgKdSearchMemoryApi);
845 while (TRUE);
846 break;
847
848 case DbgKdGetBusDataApi:
849
850 /* FIXME: TODO */
851 Ke386SetCr2(DbgKdGetBusDataApi);
852 while (TRUE);
853 break;
854
855 case DbgKdSetBusDataApi:
856
857 /* FIXME: TODO */
858 Ke386SetCr2(DbgKdSetBusDataApi);
859 while (TRUE);
860 break;
861
862 case DbgKdCheckLowMemoryApi:
863
864 /* FIXME: TODO */
865 Ke386SetCr2(DbgKdCheckLowMemoryApi);
866 while (TRUE);
867 break;
868
869 case DbgKdClearAllInternalBreakpointsApi:
870
871 /* Just clear the counter */
872 KdpNumInternalBreakpoints = 0;
873 break;
874
875 case DbgKdFillMemoryApi:
876
877 /* FIXME: TODO */
878 Ke386SetCr2(DbgKdFillMemoryApi);
879 while (TRUE);
880 break;
881
882 case DbgKdQueryMemoryApi:
883
884 /* Query memory */
885 KdpQueryMemory(&ManipulateState, Context);
886 break;
887
888 case DbgKdSwitchPartition:
889
890 /* FIXME: TODO */
891 Ke386SetCr2(DbgKdSwitchPartition);
892 while (TRUE);
893 break;
894
895 /* Unsupported Message */
896 default:
897
898 /* Setup an empty message, with failure */
899 while (TRUE);
900 fail:
901 Data.Length = 0;
902 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
903
904 /* Send it */
905 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
906 &Header,
907 &Data,
908 &KdpContext);
909 break;
910 }
911 }
912 }
913
914 BOOLEAN
915 NTAPI
916 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
917 IN PKD_SYMBOLS_INFO SymbolInfo,
918 IN BOOLEAN Unload,
919 IN OUT PCONTEXT Context)
920 {
921 PSTRING ExtraData;
922 STRING Data, Header;
923 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
924 KCONTINUE_STATUS Status;
925
926 /* Start wait loop */
927 do
928 {
929 /* Build the architecture common parts of the message */
930 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
931 Context,
932 &WaitStateChange);
933
934 /* Now finish creating the structure */
935 KdpSetContextState(&WaitStateChange, Context);
936
937 /* Fill out load data */
938 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
939 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONGLONG)(LONG_PTR)SymbolInfo->BaseOfDll;
940 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
941 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
942 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
943
944 /* Check if we have a symbol name */
945 if (PathName)
946 {
947 /* Setup the information */
948 WaitStateChange.u.LoadSymbols.PathNameLength = PathName->Length;
949 RtlCopyMemory(KdpPathBuffer, PathName->Buffer, PathName->Length);
950 Data.Buffer = KdpPathBuffer;
951 Data.Length = WaitStateChange.u.LoadSymbols.PathNameLength;
952 ExtraData = &Data;
953 }
954 else
955 {
956 /* No name */
957 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
958 ExtraData = NULL;
959 }
960
961 /* Setup the header */
962 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
963 Header.Buffer = (PCHAR)&WaitStateChange;
964
965 /* Send the packet */
966 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
967 &Header,
968 ExtraData,
969 Context);
970 } while(Status == ContinueProcessorReselected);
971
972 /* Return status */
973 return Status;
974 }
975
976 BOOLEAN
977 NTAPI
978 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
979 IN OUT PCONTEXT Context,
980 IN BOOLEAN SecondChanceException)
981 {
982 STRING Header, Data;
983 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
984 BOOLEAN Status;
985
986 /* Start report loop */
987 do
988 {
989 /* Build the architecture common parts of the message */
990 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
991
992 /* Convert the exception record to 64-bits and set First Chance flag */
993 ExceptionRecordTo64(ExceptionRecord,
994 &WaitStateChange.u.Exception.ExceptionRecord);
995 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
996
997 /* Now finish creating the structure */
998 KdpSetContextState(&WaitStateChange, Context);
999
1000 /* Setup the actual header to send to KD */
1001 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64) - sizeof(CONTEXT);
1002 Header.Buffer = (PCHAR)&WaitStateChange;
1003
1004 /* Setup the trace data */
1005 DumpTraceData(&Data);
1006
1007 /* Send State Change packet and wait for a reply */
1008 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1009 &Header,
1010 &Data,
1011 Context);
1012 } while (Status == KdPacketNeedsResend);
1013
1014 /* Return */
1015 return Status;
1016 }
1017
1018 VOID
1019 NTAPI
1020 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1021 IN PVOID DeferredContext,
1022 IN PVOID SystemArgument1,
1023 IN PVOID SystemArgument2)
1024 {
1025 LONG OldSlip, NewSlip, PendingSlip;
1026
1027 /* Get the current pending slip */
1028 PendingSlip = KdpTimeSlipPending;
1029 do
1030 {
1031 /* Save the old value and either disable or enable it now. */
1032 OldSlip = PendingSlip;
1033 NewSlip = OldSlip > 1 ? 1 : 0;
1034
1035 /* Try to change the value */
1036 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1037 NewSlip,
1038 OldSlip) != OldSlip);
1039
1040 /* If the New Slip value is 1, then do the Time Slipping */
1041 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1042 }
1043
1044 VOID
1045 NTAPI
1046 KdpTimeSlipWork(IN PVOID Context)
1047 {
1048 KIRQL OldIrql;
1049 LARGE_INTEGER DueTime;
1050
1051 /* Update the System time from the CMOS */
1052 ExAcquireTimeRefreshLock(FALSE);
1053 ExUpdateSystemTimeFromCmos(FALSE, 0);
1054 ExReleaseTimeRefreshLock();
1055
1056 /* Check if we have a registered Time Slip Event and signal it */
1057 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1058 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1059 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1060
1061 /* Delay the DPC until it runs next time */
1062 DueTime.QuadPart = -1800000000;
1063 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1064 }
1065
1066 BOOLEAN
1067 NTAPI
1068 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
1069 IN OUT PCONTEXT ContextRecord,
1070 IN BOOLEAN SecondChanceException)
1071 {
1072 BOOLEAN Status;
1073
1074 /* Save the port data */
1075 KdSave(FALSE);
1076
1077 /* Report a state change */
1078 Status = KdpReportExceptionStateChange(ExceptionRecord,
1079 ContextRecord,
1080 SecondChanceException);
1081
1082 /* Restore the port data and return */
1083 KdRestore(FALSE);
1084 return Status;
1085 }
1086
1087 LARGE_INTEGER
1088 NTAPI
1089 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1090 {
1091 LARGE_INTEGER Null = {{0}};
1092
1093 /* Check if interrupts were disabled */
1094 if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
1095 {
1096 /* Nothing to return */
1097 return Null;
1098 }
1099
1100 /* Otherwise, do the call */
1101 return KeQueryPerformanceCounter(NULL);
1102 }
1103
1104 BOOLEAN
1105 NTAPI
1106 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1107 IN PKEXCEPTION_FRAME ExceptionFrame)
1108 {
1109 BOOLEAN Entered;
1110
1111 /* Check if we have a trap frame */
1112 if (TrapFrame)
1113 {
1114 /* Calculate the time difference for the enter */
1115 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1116 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1117 KdTimerStart.QuadPart;
1118 }
1119 else
1120 {
1121 /* No trap frame, so can't calculate */
1122 KdTimerStop.QuadPart = 0;
1123 }
1124
1125 /* Save the current IRQL */
1126 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1127
1128 /* Freeze all CPUs */
1129 Entered = KeFreezeExecution(TrapFrame, ExceptionFrame);
1130
1131 /* Lock the port, save the state and set debugger entered */
1132 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1133 KdSave(FALSE);
1134 KdEnteredDebugger = TRUE;
1135
1136 /* Check freeze flag */
1137 if (KiFreezeFlag & 1)
1138 {
1139 /* Print out errror */
1140 DbgPrint("FreezeLock was jammed! Backup SpinLock was used!\n");
1141 }
1142
1143 /* Check processor state */
1144 if (KiFreezeFlag & 2)
1145 {
1146 /* Print out errror */
1147 DbgPrint("Some processors not frozen in debugger!\n");
1148 }
1149
1150 /* Make sure we acquired the port */
1151 if (!KdpPortLocked) DbgPrint("Port lock was not acquired!\n");
1152
1153 /* Return enter state */
1154 return Entered;
1155 }
1156
1157 VOID
1158 NTAPI
1159 KdExitDebugger(IN BOOLEAN Entered)
1160 {
1161 ULONG TimeSlip;
1162
1163 /* Restore the state and unlock the port */
1164 KdRestore(FALSE);
1165 if (KdpPortLocked) KdpPortUnlock();
1166
1167 /* Unfreeze the CPUs */
1168 KeThawExecution(Entered);
1169
1170 /* Compare time with the one from KdEnterDebugger */
1171 if (!KdTimerStop.QuadPart)
1172 {
1173 /* We didn't get a trap frame earlier in so never got the time */
1174 KdTimerStart = KdTimerStop;
1175 }
1176 else
1177 {
1178 /* Query the timer */
1179 KdTimerStart = KeQueryPerformanceCounter(NULL);
1180 }
1181
1182 /* Check if a Time Slip was on queue */
1183 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1184 if (TimeSlip == 1)
1185 {
1186 /* Queue a DPC for the time slip */
1187 InterlockedIncrement(&KdpTimeSlipPending);
1188 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
1189 }
1190 }
1191
1192 NTSTATUS
1193 NTAPI
1194 KdEnableDebuggerWithLock(BOOLEAN NeedLock)
1195 {
1196 KIRQL OldIrql = PASSIVE_LEVEL;
1197
1198 /* Check if we need to acquire the lock */
1199 if (NeedLock)
1200 {
1201 /* Lock the port */
1202 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1203 KdpPortLock();
1204 }
1205
1206 /* Check if we're not disabled */
1207 if (!KdDisableCount)
1208 {
1209 /* Check if we had locked the port before */
1210 if (NeedLock)
1211 {
1212 /* Do the unlock */
1213 KeLowerIrql(OldIrql);
1214 KdpPortUnlock();
1215 }
1216
1217 /* Fail: We're already enabled */
1218 return STATUS_INVALID_PARAMETER;
1219 }
1220
1221 /* Decrease the disable count */
1222 if (!(--KdDisableCount))
1223 {
1224 /* We're now enabled again! Were we enabled before, too? */
1225 if (KdPreviouslyEnabled)
1226 {
1227 /* Reinitialize the Debugger */
1228 KdInitSystem(0, NULL) ;
1229 KdpRestoreAllBreakpoints();
1230 }
1231 }
1232
1233 /* Check if we had locked the port before */
1234 if (NeedLock)
1235 {
1236 /* Yes, now unlock it */
1237 KeLowerIrql(OldIrql);
1238 KdpPortUnlock();
1239 }
1240
1241 /* We're done */
1242 return STATUS_SUCCESS;
1243 }
1244
1245 /* PUBLIC FUNCTIONS **********************************************************/
1246
1247 /*
1248 * @implemented
1249 */
1250 NTSTATUS
1251 NTAPI
1252 KdEnableDebugger(VOID)
1253 {
1254 /* Use the internal routine */
1255 while (TRUE);
1256 return KdEnableDebuggerWithLock(TRUE);
1257 }
1258
1259 /*
1260 * @unimplemented
1261 */
1262 NTSTATUS
1263 NTAPI
1264 KdSystemDebugControl(IN SYSDBG_COMMAND Command,
1265 IN PVOID InputBuffer,
1266 IN ULONG InputBufferLength,
1267 OUT PVOID OutputBuffer,
1268 IN ULONG OutputBufferLength,
1269 IN OUT PULONG ReturnLength,
1270 IN KPROCESSOR_MODE PreviousMode)
1271 {
1272 /* HACK */
1273 return STATUS_SUCCESS;
1274 }
1275
1276 /*
1277 * @unimplemented
1278 */
1279 NTSTATUS
1280 NTAPI
1281 KdChangeOption(IN KD_OPTION Option,
1282 IN ULONG InBufferBytes OPTIONAL,
1283 IN PVOID InBuffer,
1284 IN ULONG OutBufferBytes OPTIONAL,
1285 OUT PVOID OutBuffer,
1286 OUT PULONG OutBufferNeeded OPTIONAL)
1287 {
1288 /* HACK */
1289 return STATUS_SUCCESS;
1290 }
1291
1292 /*
1293 * @unimplemented
1294 */
1295 NTSTATUS
1296 NTAPI
1297 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
1298 {
1299 /* HACK */
1300 return STATUS_SUCCESS;
1301 }
1302
1303 /*
1304 * @unimplemented
1305 */
1306 NTSTATUS
1307 NTAPI
1308 KdDisableDebugger(VOID)
1309 {
1310 /* HACK */
1311 return STATUS_SUCCESS;
1312 }
1313
1314 /*
1315 * @unimplemented
1316 */
1317 BOOLEAN
1318 NTAPI
1319 KdRefreshDebuggerNotPresent(VOID)
1320 {
1321 /* HACK */
1322 return KdDebuggerNotPresent;
1323 }
1324
1325 NTSTATUS
1326 NTAPI
1327 NtQueryDebugFilterState(ULONG ComponentId,
1328 ULONG Level)
1329 {
1330 /* HACK */
1331 return STATUS_SUCCESS;
1332 }
1333
1334 NTSTATUS
1335 NTAPI
1336 NtSetDebugFilterState(ULONG ComponentId,
1337 ULONG Level,
1338 BOOLEAN State)
1339 {
1340 /* HACK */
1341 return STATUS_SUCCESS;
1342 }
1343