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