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