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