//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // using System; using System.Runtime.CompilerServices; namespace Microsoft.Singularity.KernelDebugger { /// /// This class exposes some of the unmanaged kernel debugger functions, mainly /// KdSendPacket and KdReceivePacket. Eventually, more of the kernel debugger /// support should be moved out of halkd.cpp and into this class. /// /// The main consumer of this class is the KdFiles class. /// [NoCCtor] [CLSCompliant(false)] [AccessedByRuntime("output to header : methods defined in halkd.cpp")] public class Kd { [AccessedByRuntime("output to header : defined in halkd.cpp")] [MethodImpl(MethodImplOptions.InternalCall)] [StackBound(1024)] [NoHeapAllocation] public static unsafe extern void SendPacket( uint PacketType, byte* MessageHeaderBuffer, int MessageHeaderLength, byte* MessageDataBuffer, int MessageDataLength ); [AccessedByRuntime("output to header : defined in halkd.cpp")] [MethodImpl(MethodImplOptions.InternalCall)] [StackBound(1024)] [NoHeapAllocation] public static unsafe extern /*KdStatus*/ uint ReceivePacket( uint PacketType, byte* MessageHeaderBuffer, int MessageHeaderLength, byte* MessageDataBuffer, int MessageDataBufferLength, out int MessageDataLength ); [AccessedByRuntime("output to header : defined in halkd.cpp")] [MethodImpl(MethodImplOptions.InternalCall)] [StackBound(1024)] [NoHeapAllocation] public static extern void Lock(); [AccessedByRuntime("output to header : defined in halkd.cpp")] [MethodImpl(MethodImplOptions.InternalCall)] [StackBound(1024)] [NoHeapAllocation] public static extern void Unlock(); public static unsafe void SendPacket( KdPacketType PacketType, byte* MessageHeaderBuffer, int MessageHeaderLength, byte* MessageDataBuffer, int MessageDataLength ) { // DebugStub.WriteLine(String.Format("MessageHeaderBuffer = 0x{0:x}", (UIntPtr)MessageHeaderBuffer)); // DebugStub.WriteLine("Kd.SendPacket: Sending packet to KD..."); // Console.WriteLine("Kd.SendPacket: Sending packet to KD..."); SendPacket( (uint)PacketType, MessageHeaderBuffer, MessageHeaderLength, MessageDataBuffer, MessageDataLength); // DebugStub.WriteLine("Kd.SendPacket: KdSendPacket has returned."); // Console.WriteLine("Kd.SendPacket: KdSendPacket has returned."); } public static unsafe KdStatus ReceivePacket( KdPacketType PacketType, byte* MessageHeaderBuffer, int MessageHeaderLength, byte* MessageDataBuffer, int MessageDataBufferLength, out int MessageDataLength ) { // DebugStub.WriteLine(String.Format("Kd.ReceivePacket: MessageHeaderBuffer = 0x{0:x}", (UIntPtr)MessageHeaderBuffer)); // Console.WriteLine("Kd.ReceivePacket: Waiting for packet from KD..."); KdStatus status = (KdStatus)ReceivePacket( (uint)PacketType, MessageHeaderBuffer, MessageHeaderLength, MessageDataBuffer, MessageDataBufferLength, out MessageDataLength); // Console.WriteLine("Kd.ReceivePacket: KdReceivePacket has returned. Status = " + status); // DebugStub.Break(); return status; } public static unsafe bool SendRequestWaitResponse( KdPacketType PacketType, byte* RequestHeaderBuffer, int RequestHeaderLength, byte* RequestDataBuffer, int RequestDataLength, byte* ResponseHeaderBuffer, int ResponseHeaderLength, byte* ResponseDataBuffer, int ResponseDataMaximumLength, out int ResponseDataActualLength) { ResponseDataActualLength = 0; send_packet: if (!IsDebuggerPresent()) return false; SendPacket( PacketType, RequestHeaderBuffer, RequestHeaderLength, RequestDataBuffer, RequestDataLength); receive_packet: KdStatus status = (KdStatus)ReceivePacket( (uint)PacketType, ResponseHeaderBuffer, ResponseHeaderLength, ResponseDataBuffer, ResponseDataMaximumLength, out ResponseDataActualLength); if (status == KdStatus.PacketReceived) { Dbg("Received response. Actual data length = {0}", ResponseDataActualLength); return true; } if (status == KdStatus.PacketTimeout) { if (IsDebuggerPresent()) { Dbg("Received PacketTimeout, trying again"); goto receive_packet; } else { ResponseDataActualLength = 0; return false; } } if (status == KdStatus.PacketResend) { Dbg("Received PacketResend -- resending packet."); goto send_packet; } Dbg("Received unrecognized response from KdReceivePacket. Return value: {0}", (uint)status); ResponseDataActualLength = 0; return false; } public static bool IsDebuggerPresent() { return DebugStub.IsDebuggerPresent(); } public const int MaxPacketSize = 4096; static bool _debug_to_console; static void Dbg(string line) { if (_debug_to_console) Console.WriteLine("KernelDebugger.cs: " + line); } static void Dbg(string format, params object[] args) { Dbg(String.Format(format, args)); } } /// /// Compatible with PACKET_TYPE_XXX defines in halkd.h. /// [CLSCompliant(false)] [AccessedByRuntime("referenced from halkd.cpp")] public enum KdPacketType : uint { Unused = 0, StateChange32 = 1, StateManipulate = 2, DebugIo = 3, Acknowledge = 4,// Packet-control type Resend = 5,// Packet-control type Reset = 6,// Packet-control type StateChange64 = 7, PollBreakin = 8, TraceIo = 9, ControlRequest = 10, [AccessedByRuntime("referenced from halkd.cpp")] FileIo = 11, MaxValue = 12, } /// /// These values identify the structure of messages / requests sent between /// the kernel and KD. Compatible with DbgKdXxxApi values. /// [CLSCompliant(false)] public enum KdApi : uint { // State change constants MinimumStateChange = 0x00003030u, ExceptionStateChange = 0x00003030u, LoadSymbolsStateChange = 0x00003031u, CommandStringStateChange = 0x00003032u, MaximumStateChange = 0x00003033u, // // If the packet type is PACKET_TYPE_KD_STATE_MANIPULATE, then // the format of the packet data is as follows: // // Api Numbers for state manipulation // MinimumManipulate = 0x00003130u, ReadVirtualMemoryApi = 0x00003130u, WriteVirtualMemoryApi = 0x00003131u, GetContextApi = 0x00003132u, SetContextApi = 0x00003133u, WriteBreakPointApi = 0x00003134u, RestoreBreakPointApi = 0x00003135u, ContinueApi = 0x00003136u, ReadControlSpaceApi = 0x00003137u, WriteControlSpaceApi = 0x00003138u, ReadIoSpaceApi = 0x00003139u, WriteIoSpaceApi = 0x0000313Au, RebootApi = 0x0000313Bu, ContinueApi2 = 0x0000313Cu, ReadPhysicalMemoryApi = 0x0000313Du, WritePhysicalMemoryApi = 0x0000313Eu, //QuerySpecialCallsApi = 0x0000313FL SetSpecialCallApi = 0x00003140u, ClearSpecialCallsApi = 0x00003141u, SetInternalBreakPointApi = 0x00003142u, GetInternalBreakPointApi = 0x00003143u, ReadIoSpaceExtendedApi = 0x00003144u, WriteIoSpaceExtendedApi = 0x00003145u, GetVersionApi = 0x00003146u, WriteBreakPointExApi = 0x00003147u, RestoreBreakPointExApi = 0x00003148u, CauseBugCheckApi = 0x00003149u, SwitchProcessor = 0x00003150u, PageInApi = 0x00003151u,// obsolete ReadMachineSpecificRegister = 0x00003152u, WriteMachineSpecificRegister = 0x00003153u, OldVlm1 = 0x00003154u, OldVlm2 = 0x00003155u, SearchMemoryApi = 0x00003156u, GetBusDataApi = 0x00003157u, SetBusDataApi = 0x00003158u, CheckLowMemoryApi = 0x00003159u, ClearAllInternalBreakpointsApi = 0x0000315Au, FillMemoryApi = 0x0000315Bu, QueryMemoryApi = 0x0000315Cu, SwitchPartition = 0x0000315Du, MaximumManipulate = 0x0000315Eu, // // If the packet type is PACKET_TYPE_KD_FILE_IO, then // the format of the packet data is as follows: // CreateFile = 0x00003430u, ReadFile = 0x00003431u, WriteFile = 0x00003432u, CloseFile = 0x00003433u, } /// /// Declares error codes for Kd.ReceivePacket. Values are compatible /// with unmanaged defines KDP_PACKET_RECEIVED, etc. /// [AccessedByRuntime("referenced from halkd.cpp")] public enum KdStatus { [AccessedByRuntime("referenced from halkd.cpp")] PacketReceived = 0, [AccessedByRuntime("referenced from halkd.cpp")] PacketTimeout = 1, [AccessedByRuntime("referenced from halkd.cpp")] PacketResend = 2, } }