Browse Source

Some support for creating debug types form signature blobs

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4332 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 17 years ago
parent
commit
e2c1ff9f33
  1. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/Enums/CorElementType.cs
  2. 117
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs
  3. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaDataImport.cs
  4. 48
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs
  5. 2
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/GenericDictionary.cs

4
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/Enums/CorElementType.cs

@ -32,9 +32,9 @@ namespace Debugger.Wrappers.CorDebug @@ -32,9 +32,9 @@ namespace Debugger.Wrappers.CorDebug
// Please use VALUETYPE. VALUECLASS is deprecated.
VALUETYPE = 0x11, // VALUETYPE <class Token>
CLASS = 0x12, // CLASS <class Token>
VAR = 0x13,
ARRAY = 0x14, // MDARRAY <type> <rank> <bcount> <bound1> ... <lbcount> <lb1> ...
GENERICINST = 0x15,
TYPEDBYREF = 0x16, // This is a simple type.
I = 0x18, // native integer size

117
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs

@ -347,24 +347,119 @@ namespace Debugger.MetaData @@ -347,24 +347,119 @@ namespace Debugger.MetaData
public static DebugType Create(Module module, uint token)
{
if ((token & 0xFF000000) == (uint)CorTokenType.TypeDef) {
return Create(module.Process, module.CorModule.GetClassFromToken(token));
} else if ((token & 0xFF000000) == (uint)CorTokenType.TypeRef) {
string fullName = module.MetaData.GetTypeRefProps(token).Name;
return Create(module.Process, module.AppDomainID, fullName);
return Create(module, token, null);
}
public static DebugType Create(Module module, uint token, DebugType signatureContext)
{
CorTokenType tokenType = (CorTokenType)(token & 0xFF000000);
if (tokenType == CorTokenType.TypeDef || tokenType == CorTokenType.TypeRef) {
return Create(module.Process, GetCorClass(module, token));
} else if (tokenType == CorTokenType.TypeSpec) {
Blob typeSpecBlob = module.MetaData.GetTypeSpecFromToken(token);
Queue<byte> sig = new Queue<byte>(typeSpecBlob.GetData());
return Create(module, sig, signatureContext);
} else {
throw new DebuggerException("Unknown token type");
}
}
public static DebugType Create(Module module, Queue<byte> sig)
{
return Create(module, sig, null);
}
/// <param name="signatureContext">Type definition to use to resolve numbered generic references</param>
public static DebugType Create(Module module, Queue<byte> sig, DebugType signatureContext)
{
CorElementType corType = (CorElementType)sig.Dequeue();
System.Type sysType = CorElementTypeToManagedType(corType);
if (sysType != null) {
return Create(module.Process, module.AppDomainID, sysType.FullName);
}
if (corType == CorElementType.CLASS || corType == CorElementType.VALUETYPE) {
uint typeDefOrRef = ReadTypeDefOrRefEncoded(sig);
ICorDebugClass corClass = GetCorClass(module, typeDefOrRef);
return Create(module.Process, corClass);
}
// Numbered generic reference
if (corType == CorElementType.VAR) {
uint genArgIndex = ReadCompressedInt(sig);
if (signatureContext == null) throw new DebuggerException("Signature context is needed");
return signatureContext.GenericArguments[(int)genArgIndex];
}
if (corType == CorElementType.GENERICINST) {
CorElementType classOrValueType = (CorElementType)sig.Dequeue();
uint typeDefOrRef = ReadTypeDefOrRefEncoded(sig);
ICorDebugClass corClass = GetCorClass(module, typeDefOrRef);
uint genArgsCount = ReadCompressedInt(sig);
ICorDebugType[] genArgs = new ICorDebugType[genArgsCount];
for(int i = 0; i < genArgs.Length; i++) {
genArgs[i] = Create(module, sig, signatureContext).CorType;
}
ICorDebugType genInstance = corClass.CastTo<ICorDebugClass2>().GetParameterizedType((uint)classOrValueType, genArgs);
return Create(module.Process, genInstance);
}
throw new NotImplementedException();
}
static uint ReadTypeDefOrRefEncoded(Queue<byte> sig)
{
uint i = ReadCompressedInt(sig);
uint table = i & 0x3;
uint index = i >> 2;
CorTokenType[] tables = new CorTokenType[] {CorTokenType.TypeDef, CorTokenType.TypeRef, CorTokenType.TypeSpec};
uint token = (uint)tables[table] | index;
return token;
}
static uint ReadCompressedInt(Queue<byte> sig)
{
if ((sig.Peek() & 0x80) == 0x00) { // 1 bit
return (uint)sig.Dequeue();
} else if ((sig.Peek() & 0xC0) == 0x80) { // 2 bit
return (((uint)sig.Dequeue() & 0x3F) << 8) + (uint)sig.Dequeue();
} else if ((sig.Peek() & 0xE0) == 0xC0) { // 4 bit
return (((uint)sig.Dequeue() & 0x1F) << 24) + ((uint)sig.Dequeue() << 16) + ((uint)sig.Dequeue() << 8) + (uint)sig.Dequeue();
} else {
throw new DebuggerException("Unexpected value in signature");
}
}
public static DebugType Create(Process process, uint? domainID, string fullTypeName)
{
return Create(process, GetCorClass(process, domainID, fullTypeName));
}
static ICorDebugClass GetCorClass(Module module, uint token)
{
if ((token & 0xFF000000) == (uint)CorTokenType.TypeDef) {
return module.CorModule.GetClassFromToken(token);
} else if ((token & 0xFF000000) == (uint)CorTokenType.TypeRef) {
string fullName = module.MetaData.GetTypeRefProps(token).Name;
return GetCorClass(module.Process, module.AppDomainID, fullName);
} else {
throw new DebuggerException("TypeDef or TypeRef expected");
}
}
static ICorDebugClass GetCorClass(Process process, uint? domainID, string fullTypeName)
{
foreach(Module module in process.Modules) {
if (!domainID.HasValue || domainID == module.CorModule.Assembly.AppDomain.ID) {
try {
uint token = module.MetaData.FindTypeDefPropsByName(fullTypeName, 0 /* enclosing class for nested */).Token;
return Create(process, module.CorModule.GetClassFromToken(token));
return module.CorModule.GetClassFromToken(token);
} catch {
continue;
}
@ -427,11 +522,13 @@ namespace Debugger.MetaData @@ -427,11 +522,13 @@ namespace Debugger.MetaData
}
}
// This has to be done before LoadMemberInfo since it might use it
typesWithMatchingName.Add(type);
// The type is not in the cache, finish loading it and add it to the cache
if (type.IsClass || type.IsValueType) {
type.LoadMemberInfo();
}
typesWithMatchingName.Add(type);
type.Process.Exited += delegate { typesWithMatchingName.Remove(type); };
TimeSpan totalTime2 = Util.HighPrecisionTimer.Now - startTime;
@ -508,11 +605,7 @@ namespace Debugger.MetaData @@ -508,11 +605,7 @@ namespace Debugger.MetaData
{
// Load interfaces
foreach(InterfaceImplProps implProps in module.MetaData.EnumInterfaceImplProps(this.Token)) {
if ((implProps.Interface & 0xFF000000) == (uint)CorTokenType.TypeDef ||
(implProps.Interface & 0xFF000000) == (uint)CorTokenType.TypeRef)
{
this.interfaces.Add(DebugType.Create(module, implProps.Interface));
}
this.interfaces.Add(DebugType.Create(module, implProps.Interface, this));
}
// Load fields

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

@ -969,7 +969,7 @@ namespace Debugger.Wrappers.MetaData @@ -969,7 +969,7 @@ namespace Debugger.Wrappers.MetaData
this.size = size;
}
byte[] GetData()
public byte[] GetData()
{
byte[] data = new byte[size];
Marshal.Copy(adress, data, 0, (int)size);

48
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// </file>
using System;
using System.Collections.Generic;
namespace Debugger.Tests.TestPrograms
{
@ -16,14 +17,15 @@ namespace Debugger.Tests.TestPrograms @@ -16,14 +17,15 @@ namespace Debugger.Tests.TestPrograms
}
public interface MyInterface
public interface MyInterface<K, V, T>
{
K ItemKey { get; }
}
public class MyInterfaceImpl: MyInterface
public class MyInterfaceImpl<T> : MyInterface<string, IEnumerable<int>, MyClass>
{
public T Item { get { return default(T); } }
public string ItemKey { get { return null; } }
}
public struct Point {
@ -51,8 +53,8 @@ namespace Debugger.Tests.TestPrograms @@ -51,8 +53,8 @@ namespace Debugger.Tests.TestPrograms
Point locStruct;
Point* locStructPtr = &locStruct;
object box = 40;
MyInterfaceImpl myInterfaceImpl = new MyInterfaceImpl();
MyInterface myInterface = myInterfaceImpl;
MyInterfaceImpl<int> myInterfaceImpl = new MyInterfaceImpl<int>();
MyInterface<string, IEnumerable<int>, MyClass> myInterface = myInterfaceImpl;
System.Diagnostics.Debugger.Break();
@ -105,7 +107,7 @@ namespace Debugger.Tests { @@ -105,7 +107,7 @@ namespace Debugger.Tests {
<ProcessStarted />
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>DebugTypes.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break DebugTypes.cs:57,4-57,40</DebuggingPaused>
<DebuggingPaused>Break DebugTypes.cs:59,4-59,40</DebuggingPaused>
<LocalVariables
Capacity="32"
Count="19">
@ -655,7 +657,7 @@ namespace Debugger.Tests { @@ -655,7 +657,7 @@ namespace Debugger.Tests {
ElementType="null"
FullName="System.Int32"
GenericArguments="{}"
Interfaces="{System.IComparable, System.IFormattable, System.IConvertible}"
Interfaces="{System.IComparable, System.IFormattable, System.IConvertible, System.IComparable&lt;System.Int32&gt;, System.IEquatable&lt;System.Int32&gt;}"
Kind="ValueType"
Module="mscorlib.dll"
Name="Int32">
@ -669,23 +671,23 @@ namespace Debugger.Tests { @@ -669,23 +671,23 @@ namespace Debugger.Tests {
ArrayDimensions="{Exception: Value is not an array}"
ArrayLength="{Exception: Value is not an array}"
ArrayRank="{Exception: Value is not an array}"
AsString="{MyInterfaceImpl}"
AsString="{MyInterfaceImpl&lt;System.Int32&gt;}"
Expression="myInterfaceImpl"
IsInvalid="False"
IsNull="False"
IsReference="True"
PrimitiveValue="{Exception: Value is not a primitive type}"
Type="MyInterfaceImpl">
Type="MyInterfaceImpl&lt;System.Int32&gt;">
<Type>
<DebugType
BaseType="System.Object"
ElementType="null"
FullName="MyInterfaceImpl"
GenericArguments="{}"
Interfaces="{MyInterface}"
FullName="MyInterfaceImpl&lt;System.Int32&gt;"
GenericArguments="{System.Int32}"
Interfaces="{MyInterface&lt;System.String,System.Collections.Generic.IEnumerable&lt;System.Int32&gt;,MyClass&gt;}"
Kind="Class"
Module="DebugTypes.exe"
Name="MyInterfaceImpl">
Name="MyInterfaceImpl&lt;Int32&gt;">
<ElementType>null</ElementType>
</DebugType>
</Type>
@ -696,30 +698,30 @@ namespace Debugger.Tests { @@ -696,30 +698,30 @@ namespace Debugger.Tests {
ArrayDimensions="{Exception: Value is not an array}"
ArrayLength="{Exception: Value is not an array}"
ArrayRank="{Exception: Value is not an array}"
AsString="{MyInterfaceImpl}"
AsString="{MyInterfaceImpl&lt;System.Int32&gt;}"
Expression="myInterface"
IsInvalid="False"
IsNull="False"
IsReference="True"
PrimitiveValue="{Exception: Value is not a primitive type}"
Type="MyInterfaceImpl">
Type="MyInterfaceImpl&lt;System.Int32&gt;">
<Type>
<DebugType
BaseType="System.Object"
ElementType="null"
FullName="MyInterfaceImpl"
GenericArguments="{}"
Interfaces="{MyInterface}"
FullName="MyInterfaceImpl&lt;System.Int32&gt;"
GenericArguments="{System.Int32}"
Interfaces="{MyInterface&lt;System.String,System.Collections.Generic.IEnumerable&lt;System.Int32&gt;,MyClass&gt;}"
Kind="Class"
Module="DebugTypes.exe"
Name="MyInterfaceImpl">
Name="MyInterfaceImpl&lt;Int32&gt;">
<ElementType>null</ElementType>
</DebugType>
</Type>
</Value>
</Item>
</LocalVariables>
<DebuggingPaused>Break DebugTypes.cs:74,4-74,40</DebuggingPaused>
<DebuggingPaused>Break DebugTypes.cs:76,4-76,40</DebuggingPaused>
<Arguments
Capacity="16"
Count="15">
@ -1188,7 +1190,7 @@ namespace Debugger.Tests { @@ -1188,7 +1190,7 @@ namespace Debugger.Tests {
ElementType="null"
FullName="System.Int32"
GenericArguments="{}"
Interfaces="{System.IComparable, System.IFormattable, System.IConvertible}"
Interfaces="{System.IComparable, System.IFormattable, System.IConvertible, System.IComparable&lt;System.Int32&gt;, System.IEquatable&lt;System.Int32&gt;}"
Kind="ValueType"
Module="mscorlib.dll"
Name="Int32">
@ -1215,7 +1217,7 @@ namespace Debugger.Tests { @@ -1215,7 +1217,7 @@ namespace Debugger.Tests {
ElementType="null"
FullName="System.Int32"
GenericArguments="{}"
Interfaces="{System.IComparable, System.IFormattable, System.IConvertible}"
Interfaces="{System.IComparable, System.IFormattable, System.IConvertible, System.IComparable&lt;System.Int32&gt;, System.IEquatable&lt;System.Int32&gt;}"
Kind="ValueType"
Module="mscorlib.dll"
Name="Int32">

2
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/GenericDictionary.cs

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbeck<EFBFBD>" email="dsrbecky@gmail.com"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>

Loading…
Cancel
Save