Browse Source

Some marshaling code moved to wrappers, optimized getting of unmanaged strings

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1165 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 20 years ago
parent
commit
e5065b0a9e
  1. 5
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
  2. 13
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Modules/Module.cs
  3. 71
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PrimitiveValue.cs
  4. 66
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugGenericValue.cs
  5. 21
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugModule.cs
  6. 21
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugStringValue.cs
  7. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorSym/ISymUnmanagedDocument.cs
  8. 207
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaData.cs
  9. 36
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/Util.cs

5
src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj

@ -363,6 +363,9 @@
<Compile Include="Src\Wrappers\CorSym\ISymUnmanagedScope.cs" /> <Compile Include="Src\Wrappers\CorSym\ISymUnmanagedScope.cs" />
<Compile Include="Src\Wrappers\CorSym\ISymUnmanagedVariable.cs" /> <Compile Include="Src\Wrappers\CorSym\ISymUnmanagedVariable.cs" />
<Compile Include="Src\Wrappers\CorSym\SequencePoint.cs" /> <Compile Include="Src\Wrappers\CorSym\SequencePoint.cs" />
<Compile Include="Src\Wrappers\CorDebug\ICorDebugModule.cs" />
<Compile Include="Src\Wrappers\CorDebug\ICorDebugStringValue.cs" />
<Compile Include="Src\Wrappers\CorDebug\ICorDebugGenericValue.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="README.TXT" /> <Content Include="README.TXT" />
@ -375,4 +378,4 @@
<Folder Include="Src\Wrappers\MetaData" /> <Folder Include="Src\Wrappers\MetaData" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
</Project> </Project>

13
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Modules/Module.cs

@ -127,18 +127,7 @@ namespace Debugger
metaData = new MetaData(pModule); metaData = new MetaData(pModule);
uint pStringLenght = 0; // Terminating character included in pStringLenght fullPath = pModule.Name;
IntPtr pString = IntPtr.Zero;
pModule.GetName(pStringLenght,
out pStringLenght, // real string lenght
pString);
// Allocate string buffer
pString = Marshal.AllocHGlobal((int)pStringLenght * 2);
pModule.GetName(pStringLenght,
out pStringLenght, // real string lenght
pString);
fullPath = Marshal.PtrToStringUni(pString);
Marshal.FreeHGlobal(pString);
symReader = metaData.GetSymReader(fullPath, null); symReader = metaData.GetSymReader(fullPath, null);

71
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PrimitiveValue.cs

@ -25,55 +25,12 @@ namespace Debugger
} }
} }
public unsafe object Primitive { public object Primitive {
get { get {
if (CorType == CorElementType.STRING) { if (CorType == CorElementType.STRING) {
uint pStringLenght = 1; // Terminating character NOT included in pStringLenght return (corValue.CastTo<ICorDebugStringValue>()).String;
IntPtr pString = Marshal.AllocHGlobal(2);
// For some reason this function does not accept IntPtr.Zero
(corValue.CastTo<ICorDebugStringValue>()).GetString(pStringLenght,
out pStringLenght,
pString);
// Re-allocate string buffer
Marshal.FreeHGlobal(pString);
// Termination null is not included in pStringLenght
pStringLenght++;
pString = Marshal.AllocHGlobal((int)pStringLenght * 2);
(corValue.CastTo<ICorDebugStringValue>()).GetString(pStringLenght,
out pStringLenght,
pString);
string text = Marshal.PtrToStringUni(pString);
Marshal.FreeHGlobal(pString);
return text;
} else { } else {
return (corValue.CastTo<ICorDebugGenericValue>()).Value;
object retValue;
IntPtr pValue = Marshal.AllocHGlobal(8);
(corValue.CastTo<ICorDebugGenericValue>()).GetValue(pValue);
switch(CorType)
{
case CorElementType.BOOLEAN: retValue = *((System.Boolean*)pValue); break;
case CorElementType.CHAR: retValue = *((System.Char*)pValue); break;
case CorElementType.I1: retValue = *((System.SByte*)pValue); break;
case CorElementType.U1: retValue = *((System.Byte*)pValue); break;
case CorElementType.I2: retValue = *((System.Int16*)pValue); break;
case CorElementType.U2: retValue = *((System.UInt16*)pValue); break;
case CorElementType.I4: retValue = *((System.Int32*)pValue); break;
case CorElementType.U4: retValue = *((System.UInt32*)pValue); break;
case CorElementType.I8: retValue = *((System.Int64*)pValue); break;
case CorElementType.U8: retValue = *((System.UInt64*)pValue); break;
case CorElementType.R4: retValue = *((System.Single*)pValue); break;
case CorElementType.R8: retValue = *((System.Double*)pValue); break;
case CorElementType.I: retValue = *((int*)pValue); break;
case CorElementType.U: retValue = *((uint*)pValue); break;
default: retValue = null; break;
}
Marshal.FreeHGlobal(pValue);
return retValue;
} }
} }
set { set {
@ -88,27 +45,7 @@ namespace Debugger
if (CorType == CorElementType.STRING) { if (CorType == CorElementType.STRING) {
throw new NotSupportedException(); throw new NotSupportedException();
} else { } else {
IntPtr pValue = Marshal.AllocHGlobal(8); (corValue.CastTo<ICorDebugGenericValue>()).Value = newValue;
switch(CorType)
{
case CorElementType.BOOLEAN: *((System.Boolean*)pValue) = (System.Boolean)newValue; break;
case CorElementType.CHAR: *((System.Char*)pValue) = (System.Char)newValue; break;
case CorElementType.I1: *((System.SByte*)pValue) = (System.SByte)newValue; break;
case CorElementType.U1: *((System.Byte*)pValue) = (System.Byte)newValue; break;
case CorElementType.I2: *((System.Int16*)pValue) = (System.Int16)newValue; break;
case CorElementType.U2: *((System.UInt16*)pValue) = (System.UInt16)newValue; break;
case CorElementType.I4: *((System.Int32*)pValue) = (System.Int32)newValue; break;
case CorElementType.U4: *((System.UInt32*)pValue) = (System.UInt32)newValue; break;
case CorElementType.I8: *((System.Int64*)pValue) = (System.Int64)newValue; break;
case CorElementType.U8: *((System.UInt64*)pValue) = (System.UInt64)newValue; break;
case CorElementType.R4: *((System.Single*)pValue) = (System.Single)newValue; break;
case CorElementType.R8: *((System.Double*)pValue) = (System.Double)newValue; break;
case CorElementType.I: *((int*)pValue) = (int)newValue; break;
case CorElementType.U: *((uint*)pValue) = (uint)newValue; break;
default: throw new NotSupportedException();
}
(corValue.CastTo<ICorDebugGenericValue>()).SetValue(pValue);
Marshal.FreeHGlobal(pValue);
} }
OnValueChanged(); OnValueChanged();
} }

66
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugGenericValue.cs

@ -0,0 +1,66 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
namespace Debugger.Wrappers.CorDebug
{
using System;
using System.Runtime.InteropServices;
public partial class ICorDebugGenericValue
{
public unsafe object Value {
get {
object retValue;
IntPtr pValue = Marshal.AllocHGlobal((int)Size);
GetValue(pValue);
switch((CorElementType)Type)
{
case CorElementType.BOOLEAN: retValue = *((System.Boolean*)pValue); break;
case CorElementType.CHAR: retValue = *((System.Char*) pValue); break;
case CorElementType.I1: retValue = *((System.SByte*) pValue); break;
case CorElementType.U1: retValue = *((System.Byte*) pValue); break;
case CorElementType.I2: retValue = *((System.Int16*) pValue); break;
case CorElementType.U2: retValue = *((System.UInt16*) pValue); break;
case CorElementType.I4: retValue = *((System.Int32*) pValue); break;
case CorElementType.U4: retValue = *((System.UInt32*) pValue); break;
case CorElementType.I8: retValue = *((System.Int64*) pValue); break;
case CorElementType.U8: retValue = *((System.UInt64*) pValue); break;
case CorElementType.R4: retValue = *((System.Single*) pValue); break;
case CorElementType.R8: retValue = *((System.Double*) pValue); break;
case CorElementType.I: retValue = *((int*) pValue); break;
case CorElementType.U: retValue = *((uint*) pValue); break;
default: throw new NotSupportedException();
}
Marshal.FreeHGlobal(pValue);
return retValue;
}
set {
IntPtr pValue = Marshal.AllocHGlobal((int)Size);
switch((CorElementType)Type)
{
case CorElementType.BOOLEAN: *((System.Boolean*)pValue) = (System.Boolean)value; break;
case CorElementType.CHAR: *((System.Char*) pValue) = (System.Char) value; break;
case CorElementType.I1: *((System.SByte*) pValue) = (System.SByte) value; break;
case CorElementType.U1: *((System.Byte*) pValue) = (System.Byte) value; break;
case CorElementType.I2: *((System.Int16*) pValue) = (System.Int16) value; break;
case CorElementType.U2: *((System.UInt16*) pValue) = (System.UInt16) value; break;
case CorElementType.I4: *((System.Int32*) pValue) = (System.Int32) value; break;
case CorElementType.U4: *((System.UInt32*) pValue) = (System.UInt32) value; break;
case CorElementType.I8: *((System.Int64*) pValue) = (System.Int64) value; break;
case CorElementType.U8: *((System.UInt64*) pValue) = (System.UInt64) value; break;
case CorElementType.R4: *((System.Single*) pValue) = (System.Single) value; break;
case CorElementType.R8: *((System.Double*) pValue) = (System.Double) value; break;
case CorElementType.I: *((int*) pValue) = (int) value; break;
case CorElementType.U: *((uint*) pValue) = (uint) value; break;
default: throw new NotSupportedException();
}
SetValue(pValue);
Marshal.FreeHGlobal(pValue);
}
}
}
}

21
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugModule.cs

@ -0,0 +1,21 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
namespace Debugger.Wrappers.CorDebug
{
using System;
public partial class ICorDebugModule
{
public string Name {
get {
return Util.GetString(GetName);
}
}
}
}

21
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugStringValue.cs

@ -0,0 +1,21 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
namespace Debugger.Wrappers.CorDebug
{
using System;
public partial class ICorDebugStringValue
{
public string String {
get {
return Util.GetString(GetString);
}
}
}
}

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorSym/ISymUnmanagedDocument.cs

@ -14,7 +14,7 @@ namespace Debugger.Wrappers.CorSym
{ {
public string URL { public string URL {
get { get {
return Util.GetString(GetURL); return Util.GetString(GetURL, 0);
} }
} }
} }

207
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaData.cs

@ -49,64 +49,33 @@ namespace Debugger.Wrappers.MetaData
public TypeDefProps GetTypeDefProps(uint typeToken) public TypeDefProps GetTypeDefProps(uint typeToken)
{ {
TypeDefProps typeDefProps; TypeDefProps typeDefProps = new TypeDefProps();
typeDefProps.Token = typeToken; typeDefProps.Token = typeToken;
typeDefProps.Name =
uint pStringLenght = 0; // Terminating character included in pStringLenght Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
IntPtr pString = IntPtr.Zero; metaData.GetTypeDefProps(typeDefProps.Token,
pString, pStringLenght, out stringLenght, // The string to get
// Get length of string out typeDefProps.Flags,
metaData.GetTypeDefProps(typeDefProps.Token, out typeDefProps.SuperClassToken);
pString, });
pStringLenght,
out pStringLenght,
out typeDefProps.Flags,
out typeDefProps.SuperClassToken);
// Allocate string buffer
pString = Marshal.AllocHGlobal((int)pStringLenght * 2);
// Get properties
metaData.GetTypeDefProps(typeDefProps.Token,
pString,
pStringLenght,
out pStringLenght,
out typeDefProps.Flags,
out typeDefProps.SuperClassToken);
typeDefProps.Name = Marshal.PtrToStringUni(pString);
Marshal.FreeHGlobal(pString);
return typeDefProps; return typeDefProps;
} }
public TypeRefProps GetTypeRefProps(uint typeToken) public TypeRefProps GetTypeRefProps(uint typeToken)
{ {
TypeRefProps typeRefProps; TypeRefProps typeRefProps = new TypeRefProps();
typeRefProps.Token = typeToken; typeRefProps.Token = typeToken;
typeRefProps.Name =
uint unused; Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
uint pStringLenght = 0; // Terminating character included in pStringLenght uint unused;
IntPtr pString = IntPtr.Zero; metaData.GetTypeRefProps(typeRefProps.Token,
metaData.GetTypeRefProps(typeRefProps.Token, out unused,
out unused, pString, pStringLenght,out stringLenght // The string to get
pString, );
pStringLenght, });
out pStringLenght); // real string lenght
// Allocate string buffer
pString = Marshal.AllocHGlobal((int)pStringLenght * 2);
metaData.GetTypeRefProps(typeRefProps.Token,
out unused,
pString,
pStringLenght,
out pStringLenght); // real string lenght
typeRefProps.Name = Marshal.PtrToStringUni(pString);
Marshal.FreeHGlobal(pString);
return typeRefProps; return typeRefProps;
} }
@ -128,43 +97,23 @@ namespace Debugger.Wrappers.MetaData
public FieldProps GetFieldProps(uint fieldToken) public FieldProps GetFieldProps(uint fieldToken)
{ {
FieldProps fieldProps; FieldProps fieldProps = new FieldProps();
fieldProps.Token = fieldToken; fieldProps.Token = fieldToken;
fieldProps.Name =
uint unused; Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
IntPtr unusedPtr = IntPtr.Zero; uint unused;
uint pStringLenght = 0; // Terminating character included in pStringLenght IntPtr unusedPtr = IntPtr.Zero;
IntPtr pString = IntPtr.Zero; metaData.GetFieldProps(fieldProps.Token,
metaData.GetFieldProps(fieldProps.Token, out fieldProps.ClassToken,
out fieldProps.ClassToken, pString, pStringLenght, out stringLenght, // The string to get
pString, out fieldProps.Flags,
pStringLenght, IntPtr.Zero,
out pStringLenght, // real string lenght out unused,
out fieldProps.Flags, out unused,
IntPtr.Zero, out unusedPtr,
out unused, out unused);
out unused, });
out unusedPtr,
out unused);
// Allocate string buffer
pString = Marshal.AllocHGlobal((int)pStringLenght * 2);
metaData.GetFieldProps(fieldProps.Token,
out fieldProps.ClassToken,
pString,
pStringLenght,
out pStringLenght, // real string lenght
out fieldProps.Flags,
IntPtr.Zero,
out unused,
out unused,
out unusedPtr,
out unused);
fieldProps.Name = Marshal.PtrToStringUni(pString);
Marshal.FreeHGlobal(pString);
return fieldProps; return fieldProps;
} }
@ -186,45 +135,24 @@ namespace Debugger.Wrappers.MetaData
public unsafe MethodProps GetMethodProps(uint methodToken) public unsafe MethodProps GetMethodProps(uint methodToken)
{ {
MethodProps methodProps; MethodProps methodProps = new MethodProps();
methodProps.Token = methodToken; methodProps.Token = methodToken;
methodProps.Name =
uint pStringLenght = 0; // Terminating character included in pStringLenght Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
IntPtr pString = IntPtr.Zero; uint sigBlobSize;
//IntPtr pSigBlob; metaData.GetMethodProps(methodProps.Token,
uint sigBlobSize; out methodProps.ClassToken,
metaData.GetMethodProps(methodProps.Token, pString, pStringLenght, out stringLenght, // The string to get
out methodProps.ClassToken, out methodProps.Flags,
pString, IntPtr.Zero,//new IntPtr(&pSigBlob),
pStringLenght, out sigBlobSize,
out pStringLenght, // real string lenght out methodProps.CodeRVA,
out methodProps.Flags, out methodProps.ImplFlags);
IntPtr.Zero,//new IntPtr(&pSigBlob), });
out sigBlobSize,
out methodProps.CodeRVA,
out methodProps.ImplFlags);
// Allocate string buffer
pString = Marshal.AllocHGlobal((int)pStringLenght * 2);
metaData.GetMethodProps(methodProps.Token,
out methodProps.ClassToken,
pString,
pStringLenght,
out pStringLenght, // real string lenght
out methodProps.Flags,
IntPtr.Zero,//new IntPtr(&pSigBlob),
out sigBlobSize,
out methodProps.CodeRVA,
out methodProps.ImplFlags);
methodProps.Name = Marshal.PtrToStringUni(pString);
Marshal.FreeHGlobal(pString);
methodProps.Signature = null; methodProps.Signature = null;
//methodProps.Signature = new SignatureStream(pSigBlob, sigBlobSize); //methodProps.Signature = new SignatureStream(pSigBlob, sigBlobSize);
//Marshal.FreeCoTaskMem(pSigBlob); //Marshal.FreeCoTaskMem(pSigBlob);
return methodProps; return methodProps;
@ -239,40 +167,21 @@ namespace Debugger.Wrappers.MetaData
public ParamProps GetParamProps(uint paramToken) public ParamProps GetParamProps(uint paramToken)
{ {
ParamProps paramProps; ParamProps paramProps = new ParamProps();
paramProps.Token = paramToken; paramProps.Token = paramToken;
paramProps.Name =
uint unused; Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
uint pStringLenght = 0; // Terminating character included in pStringLenght uint unused;
IntPtr pString = IntPtr.Zero; metaData.GetParamProps(paramProps.Token,
metaData.GetParamProps(paramProps.Token, out paramProps.MethodToken,
out paramProps.MethodToken, out paramProps.ParameterSequence,
out paramProps.ParameterSequence, pString, pStringLenght, out stringLenght, // The string to get
pString, out paramProps.Flags,
pStringLenght, out unused,
out pStringLenght, // real string lenght IntPtr.Zero,
out paramProps.Flags, out unused);
out unused, });
IntPtr.Zero,
out unused);
// Allocate string buffer
pString = Marshal.AllocHGlobal((int)pStringLenght * 2);
metaData.GetParamProps(paramProps.Token,
out paramProps.MethodToken,
out paramProps.ParameterSequence,
pString,
pStringLenght,
out pStringLenght, // real string lenght
out paramProps.Flags,
out unused,
IntPtr.Zero,
out unused);
paramProps.Name = Marshal.PtrToStringUni(pString);
Marshal.FreeHGlobal(pString);
return paramProps; return paramProps;
} }

36
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/Util.cs

@ -11,22 +11,36 @@ using System.Runtime.InteropServices;
namespace Debugger.Wrappers namespace Debugger.Wrappers
{ {
public delegate void UnmanagedStringGetter(uint bufferSize, out uint returnedSize, System.IntPtr pString); public delegate void UnmanagedStringGetter(uint pStringLenght, out uint stringLenght, System.IntPtr pString);
public static class Util public static class Util
{ {
public static string GetString(UnmanagedStringGetter getter) public static string GetString(UnmanagedStringGetter getter)
{ {
uint pStringLenght = 0; return GetString(getter, 64);
IntPtr pString = IntPtr.Zero; }
getter(pStringLenght, out pStringLenght, pString);
// Allocate string buffer public static string GetString(UnmanagedStringGetter getter, uint defaultLenght)
pString = Marshal.AllocHGlobal((int)pStringLenght * 2); {
getter(pStringLenght, out pStringLenght, pString); string managedString;
string str = Marshal.PtrToStringUni(pString); IntPtr unmanagedString;
// Release buffer uint exactLenght;
Marshal.FreeHGlobal(pString);
return str; // First attempt
unmanagedString = Marshal.AllocHGlobal((int)defaultLenght * 2 + 2); // + 2 for terminating zero
getter(defaultLenght, out exactLenght, defaultLenght > 0 ? unmanagedString : IntPtr.Zero);
if(exactLenght > defaultLenght) {
// Second attempt
Marshal.FreeHGlobal(unmanagedString);
unmanagedString = Marshal.AllocHGlobal((int)exactLenght * 2 + 2); // + 2 for terminating zero
getter(exactLenght, out exactLenght, unmanagedString);
}
// Return managed string and free unmanaged memory
managedString = Marshal.PtrToStringUni(unmanagedString);
Marshal.FreeHGlobal(unmanagedString);
return managedString;
} }
} }
} }

Loading…
Cancel
Save