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