|
|
|
@ -13,6 +13,8 @@ namespace Debugger.Interop.CorDebug
@@ -13,6 +13,8 @@ namespace Debugger.Interop.CorDebug
|
|
|
|
|
{ |
|
|
|
|
public static partial class CorDebugExtensionMethods |
|
|
|
|
{ |
|
|
|
|
const int EnumerateBufferSize = 16; |
|
|
|
|
|
|
|
|
|
static void ProcessOutParameter(object parameter) |
|
|
|
|
{ |
|
|
|
|
TrackedComObjects.ProcessOutParameter(parameter); |
|
|
|
@ -23,7 +25,7 @@ namespace Debugger.Interop.CorDebug
@@ -23,7 +25,7 @@ namespace Debugger.Interop.CorDebug
|
|
|
|
|
public static unsafe uint[] GetDimensions(this ICorDebugArrayValue corArray) |
|
|
|
|
{ |
|
|
|
|
uint[] dimensions = new uint[corArray.GetRank()]; |
|
|
|
|
fixed (void* pDimensions = dimensions) |
|
|
|
|
fixed(uint* pDimensions = dimensions) |
|
|
|
|
corArray.GetDimensions((uint)dimensions.Length, new IntPtr(pDimensions)); |
|
|
|
|
return dimensions; |
|
|
|
|
} |
|
|
|
@ -31,20 +33,20 @@ namespace Debugger.Interop.CorDebug
@@ -31,20 +33,20 @@ namespace Debugger.Interop.CorDebug
|
|
|
|
|
public static unsafe uint[] GetBaseIndicies(this ICorDebugArrayValue corArray) |
|
|
|
|
{ |
|
|
|
|
uint[] baseIndicies = new uint[corArray.GetRank()]; |
|
|
|
|
fixed (void* pBaseIndicies = baseIndicies) |
|
|
|
|
fixed(uint* pBaseIndicies = baseIndicies) |
|
|
|
|
corArray.GetBaseIndicies((uint)baseIndicies.Length, new IntPtr(pBaseIndicies)); |
|
|
|
|
return baseIndicies; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static unsafe ICorDebugValue GetElement(this ICorDebugArrayValue corArray, uint[] indices) |
|
|
|
|
{ |
|
|
|
|
fixed (void* pIndices = indices) |
|
|
|
|
fixed(uint* pIndices = indices) |
|
|
|
|
return corArray.GetElement((uint)indices.Length, new IntPtr(pIndices)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static unsafe ICorDebugValue GetElement(this ICorDebugArrayValue corArray, int[] indices) |
|
|
|
|
{ |
|
|
|
|
fixed (void* pIndices = indices) |
|
|
|
|
fixed(int* pIndices = indices) |
|
|
|
|
return corArray.GetElement((uint)indices.Length, new IntPtr(pIndices)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -61,133 +63,122 @@ namespace Debugger.Interop.CorDebug
@@ -61,133 +63,122 @@ namespace Debugger.Interop.CorDebug
|
|
|
|
|
{ |
|
|
|
|
if (corCode.IsIL() == 0) return null; |
|
|
|
|
byte[] code = new byte[corCode.GetSize()]; |
|
|
|
|
fixed(void* pCode = code) |
|
|
|
|
fixed(byte* pCode = code) |
|
|
|
|
corCode.GetCode(0, (uint)code.Length, (uint)code.Length, new IntPtr(pCode)); |
|
|
|
|
return code; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ICorDebugFrameEnum
|
|
|
|
|
// ICorDebugEnum
|
|
|
|
|
|
|
|
|
|
public static IEnumerable<ICorDebugFrame> GetEnumerator(this ICorDebugFrameEnum corFrameEnum) |
|
|
|
|
public static IEnumerable<ICorDebugFrame> GetEnumerator(this ICorDebugFrameEnum corEnum) |
|
|
|
|
{ |
|
|
|
|
// TODO: As list
|
|
|
|
|
corFrameEnum.Reset(); |
|
|
|
|
corEnum.Reset(); |
|
|
|
|
while (true) { |
|
|
|
|
ICorDebugFrame corFrame = corFrameEnum.Next(); |
|
|
|
|
if (corFrame != null) { |
|
|
|
|
yield return corFrame; |
|
|
|
|
} else { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
ICorDebugFrame[] corFrames = new ICorDebugFrame[EnumerateBufferSize]; |
|
|
|
|
uint fetched = corEnum.Next(EnumerateBufferSize, corFrames); |
|
|
|
|
if (fetched == 0) |
|
|
|
|
yield break; |
|
|
|
|
for(int i = 0; i < fetched; i++) |
|
|
|
|
yield return corFrames[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static ICorDebugFrame Next(this ICorDebugFrameEnum corFrameEnum) |
|
|
|
|
public static ICorDebugFrame Next(this ICorDebugFrameEnum corEnum) |
|
|
|
|
{ |
|
|
|
|
ICorDebugFrame[] corFrames = new ICorDebugFrame[1]; |
|
|
|
|
uint framesFetched = corFrameEnum.Next(1, corFrames); |
|
|
|
|
if (framesFetched == 0) { |
|
|
|
|
return null; |
|
|
|
|
} else { |
|
|
|
|
return corFrames[0]; |
|
|
|
|
ICorDebugFrame[] corFrames = new ICorDebugFrame[] { null }; |
|
|
|
|
uint framesFetched = corEnum.Next(1, corFrames); |
|
|
|
|
return corFrames[0]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static IEnumerable<ICorDebugChain> GetEnumerator(this ICorDebugChainEnum corEnum) |
|
|
|
|
{ |
|
|
|
|
corEnum.Reset(); |
|
|
|
|
while (true) { |
|
|
|
|
ICorDebugChain[] corChains = new ICorDebugChain[EnumerateBufferSize]; |
|
|
|
|
uint fetched = corEnum.Next(EnumerateBufferSize, corChains); |
|
|
|
|
if (fetched == 0) |
|
|
|
|
yield break; |
|
|
|
|
for(int i = 0; i < fetched; i++) |
|
|
|
|
yield return corChains[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static ICorDebugChain Next(this ICorDebugChainEnum corChainEnum) |
|
|
|
|
{ |
|
|
|
|
ICorDebugChain[] corChains = new ICorDebugChain[] { null }; |
|
|
|
|
uint chainsFetched = corChainEnum.Next(1, corChains); |
|
|
|
|
return corChains[0]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ICorDebugGenericValue
|
|
|
|
|
|
|
|
|
|
public static unsafe Byte[] GetRawValue(this ICorDebugGenericValue corGenVal) |
|
|
|
|
{ |
|
|
|
|
// TODO: Unset fixing insead
|
|
|
|
|
Byte[] retValue = new Byte[(int)corGenVal.GetSize()]; |
|
|
|
|
IntPtr pValue = Marshal.AllocHGlobal(retValue.Length); |
|
|
|
|
corGenVal.GetValue(pValue); |
|
|
|
|
Marshal.Copy(pValue, retValue, 0, retValue.Length); |
|
|
|
|
Marshal.FreeHGlobal(pValue); |
|
|
|
|
byte[] retValue = new byte[(int)corGenVal.GetSize()]; |
|
|
|
|
fixed(byte* pRetValue = retValue) |
|
|
|
|
corGenVal.GetValue(new IntPtr(pRetValue)); |
|
|
|
|
return retValue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static unsafe void SetRawValue(this ICorDebugGenericValue corGenVal, byte[] value) |
|
|
|
|
{ |
|
|
|
|
if (corGenVal.GetSize() != value.Length) throw new ArgumentException("Incorrect length"); |
|
|
|
|
IntPtr pValue = Marshal.AllocHGlobal(value.Length); |
|
|
|
|
Marshal.Copy(value, 0, pValue, value.Length); |
|
|
|
|
corGenVal.SetValue(pValue); |
|
|
|
|
Marshal.FreeHGlobal(pValue); |
|
|
|
|
if (corGenVal.GetSize() != value.Length) |
|
|
|
|
throw new ArgumentException("Incorrect length"); |
|
|
|
|
fixed(byte* pValue = value) |
|
|
|
|
corGenVal.SetValue(new IntPtr(pValue)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static unsafe object GetValue(this ICorDebugGenericValue corGenVal,Type type) |
|
|
|
|
public static unsafe object GetValue(this ICorDebugGenericValue corGenVal, Type type) |
|
|
|
|
{ |
|
|
|
|
object retValue; |
|
|
|
|
IntPtr pValue = Marshal.AllocHGlobal((int)corGenVal.GetSize()); |
|
|
|
|
corGenVal.GetValue(pValue); |
|
|
|
|
switch(type.FullName) { |
|
|
|
|
case "System.Boolean": retValue = *((System.Boolean*)pValue); break; |
|
|
|
|
case "System.Char": retValue = *((System.Char*) pValue); break; |
|
|
|
|
case "System.SByte": retValue = *((System.SByte*) pValue); break; |
|
|
|
|
case "System.Byte": retValue = *((System.Byte*) pValue); break; |
|
|
|
|
case "System.Int16": retValue = *((System.Int16*) pValue); break; |
|
|
|
|
case "System.UInt16": retValue = *((System.UInt16*) pValue); break; |
|
|
|
|
case "System.Int32": retValue = *((System.Int32*) pValue); break; |
|
|
|
|
case "System.UInt32": retValue = *((System.UInt32*) pValue); break; |
|
|
|
|
case "System.Int64": retValue = *((System.Int64*) pValue); break; |
|
|
|
|
case "System.UInt64": retValue = *((System.UInt64*) pValue); break; |
|
|
|
|
case "System.Single": retValue = *((System.Single*) pValue); break; |
|
|
|
|
case "System.Double": retValue = *((System.Double*) pValue); break; |
|
|
|
|
case "System.IntPtr": retValue = *((System.IntPtr*) pValue); break; |
|
|
|
|
case "System.UIntPtr": retValue = *((System.UIntPtr*)pValue); break; |
|
|
|
|
default: throw new NotSupportedException(); |
|
|
|
|
byte[] value = new byte[(int)corGenVal.GetSize()]; |
|
|
|
|
fixed(byte* pValue = value) { |
|
|
|
|
corGenVal.GetValue(new IntPtr(pValue)); |
|
|
|
|
switch(type.FullName) { |
|
|
|
|
case "System.Boolean": retValue = *((System.Boolean*)pValue); break; |
|
|
|
|
case "System.Char": retValue = *((System.Char*) pValue); break; |
|
|
|
|
case "System.SByte": retValue = *((System.SByte*) pValue); break; |
|
|
|
|
case "System.Byte": retValue = *((System.Byte*) pValue); break; |
|
|
|
|
case "System.Int16": retValue = *((System.Int16*) pValue); break; |
|
|
|
|
case "System.UInt16": retValue = *((System.UInt16*) pValue); break; |
|
|
|
|
case "System.Int32": retValue = *((System.Int32*) pValue); break; |
|
|
|
|
case "System.UInt32": retValue = *((System.UInt32*) pValue); break; |
|
|
|
|
case "System.Int64": retValue = *((System.Int64*) pValue); break; |
|
|
|
|
case "System.UInt64": retValue = *((System.UInt64*) pValue); break; |
|
|
|
|
case "System.Single": retValue = *((System.Single*) pValue); break; |
|
|
|
|
case "System.Double": retValue = *((System.Double*) pValue); break; |
|
|
|
|
case "System.IntPtr": retValue = *((System.IntPtr*) pValue); break; |
|
|
|
|
case "System.UIntPtr": retValue = *((System.UIntPtr*)pValue); break; |
|
|
|
|
default: throw new NotSupportedException(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Marshal.FreeHGlobal(pValue); |
|
|
|
|
return retValue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static unsafe void SetValue(this ICorDebugGenericValue corGenVal, Type type, object value) |
|
|
|
|
{ |
|
|
|
|
IntPtr pValue = Marshal.AllocHGlobal((int)corGenVal.GetSize()); |
|
|
|
|
switch(type.FullName) { |
|
|
|
|
case "System.Boolean": *((System.Boolean*)pValue) = (System.Boolean)value; break; |
|
|
|
|
case "System.Char": *((System.Char*) pValue) = (System.Char) value; break; |
|
|
|
|
case "System.SByte": *((System.SByte*) pValue) = (System.SByte) value; break; |
|
|
|
|
case "System.Byte": *((System.Byte*) pValue) = (System.Byte) value; break; |
|
|
|
|
case "System.Int16": *((System.Int16*) pValue) = (System.Int16) value; break; |
|
|
|
|
case "System.UInt16": *((System.UInt16*) pValue) = (System.UInt16) value; break; |
|
|
|
|
case "System.Int32": *((System.Int32*) pValue) = (System.Int32) value; break; |
|
|
|
|
case "System.UInt32": *((System.UInt32*) pValue) = (System.UInt32) value; break; |
|
|
|
|
case "System.Int64": *((System.Int64*) pValue) = (System.Int64) value; break; |
|
|
|
|
case "System.UInt64": *((System.UInt64*) pValue) = (System.UInt64) value; break; |
|
|
|
|
case "System.Single": *((System.Single*) pValue) = (System.Single) value; break; |
|
|
|
|
case "System.Double": *((System.Double*) pValue) = (System.Double) value; break; |
|
|
|
|
case "System.IntPtr": *((System.IntPtr*) pValue) = (System.IntPtr) value; break; |
|
|
|
|
case "System.UIntPtr": *((System.UIntPtr*)pValue) = (System.UIntPtr)value; break; |
|
|
|
|
default: throw new NotSupportedException(); |
|
|
|
|
} |
|
|
|
|
corGenVal.SetValue(pValue); |
|
|
|
|
Marshal.FreeHGlobal(pValue); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ICorDebugChainEnum
|
|
|
|
|
|
|
|
|
|
public static IEnumerable<ICorDebugChain> GetEnumerator(this ICorDebugChainEnum corChainEnum) |
|
|
|
|
{ |
|
|
|
|
corChainEnum.Reset(); |
|
|
|
|
while (true) { |
|
|
|
|
ICorDebugChain corChain = corChainEnum.Next(); |
|
|
|
|
if (corChain != null) { |
|
|
|
|
yield return corChain; |
|
|
|
|
} else { |
|
|
|
|
break; |
|
|
|
|
public static unsafe void SetValue(this ICorDebugGenericValue corGenVal, object value) |
|
|
|
|
{ |
|
|
|
|
if (value == null) |
|
|
|
|
throw new ArgumentNullException("value"); |
|
|
|
|
byte[] val = new byte[(int)corGenVal.GetSize()]; |
|
|
|
|
fixed(byte* pValue = val) { |
|
|
|
|
switch(value.GetType().FullName) { |
|
|
|
|
case "System.Boolean": *((System.Boolean*)pValue) = (System.Boolean)value; break; |
|
|
|
|
case "System.Char": *((System.Char*) pValue) = (System.Char) value; break; |
|
|
|
|
case "System.SByte": *((System.SByte*) pValue) = (System.SByte) value; break; |
|
|
|
|
case "System.Byte": *((System.Byte*) pValue) = (System.Byte) value; break; |
|
|
|
|
case "System.Int16": *((System.Int16*) pValue) = (System.Int16) value; break; |
|
|
|
|
case "System.UInt16": *((System.UInt16*) pValue) = (System.UInt16) value; break; |
|
|
|
|
case "System.Int32": *((System.Int32*) pValue) = (System.Int32) value; break; |
|
|
|
|
case "System.UInt32": *((System.UInt32*) pValue) = (System.UInt32) value; break; |
|
|
|
|
case "System.Int64": *((System.Int64*) pValue) = (System.Int64) value; break; |
|
|
|
|
case "System.UInt64": *((System.UInt64*) pValue) = (System.UInt64) value; break; |
|
|
|
|
case "System.Single": *((System.Single*) pValue) = (System.Single) value; break; |
|
|
|
|
case "System.Double": *((System.Double*) pValue) = (System.Double) value; break; |
|
|
|
|
case "System.IntPtr": *((System.IntPtr*) pValue) = (System.IntPtr) value; break; |
|
|
|
|
case "System.UIntPtr": *((System.UIntPtr*)pValue) = (System.UIntPtr)value; break; |
|
|
|
|
default: throw new NotSupportedException(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static ICorDebugChain Next(this ICorDebugChainEnum corChainEnum) |
|
|
|
|
{ |
|
|
|
|
ICorDebugChain[] corChains = new ICorDebugChain[1]; |
|
|
|
|
uint chainsFetched = corChainEnum.Next(1, corChains); |
|
|
|
|
if (chainsFetched == 0) { |
|
|
|
|
return null; |
|
|
|
|
} else { |
|
|
|
|
return corChains[0]; |
|
|
|
|
corGenVal.SetValue(new IntPtr(pValue)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -209,7 +200,7 @@ namespace Debugger.Interop.CorDebug
@@ -209,7 +200,7 @@ namespace Debugger.Interop.CorDebug
|
|
|
|
|
|
|
|
|
|
public static unsafe void StepRange(this ICorDebugStepper corStepper, bool bStepIn, int[] ranges) |
|
|
|
|
{ |
|
|
|
|
fixed (int* pRanges = ranges) |
|
|
|
|
fixed(int* pRanges = ranges) |
|
|
|
|
corStepper.StepRange(bStepIn?1:0, (IntPtr)pRanges, (uint)ranges.Length / 2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|