310 lines
11 KiB
C#
310 lines
11 KiB
C#
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
|
||
|
using System;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
|
||
|
namespace Microsoft.Singularity.KernelDebugger
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// 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.
|
||
|
/// </summary>
|
||
|
[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));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Compatible with PACKET_TYPE_XXX defines in halkd.h.
|
||
|
/// </summary>
|
||
|
[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,
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// These values identify the structure of messages / requests sent between
|
||
|
/// the kernel and KD. Compatible with DbgKdXxxApi values.
|
||
|
/// </summary>
|
||
|
[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,
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Declares error codes for Kd.ReceivePacket. Values are compatible
|
||
|
/// with unmanaged defines KDP_PACKET_RECEIVED, etc.
|
||
|
/// </summary>
|
||
|
[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,
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|