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