From e2c1ff9f33431c6534ec64e9364d90bad8ec3964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Sat, 20 Jun 2009 11:50:48 +0000 Subject: [PATCH] Some support for creating debug types form signature blobs git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4332 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/Interop/Enums/CorElementType.cs | 4 +- .../Project/Src/Metadata/DebugType.cs | 117 ++++++++++++++++-- .../Src/Wrappers/MetaData/MetaDataImport.cs | 2 +- .../Project/Src/TestPrograms/DebugTypes.cs | 48 +++---- .../Src/TestPrograms/GenericDictionary.cs | 2 +- 5 files changed, 134 insertions(+), 39 deletions(-) diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/Enums/CorElementType.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/Enums/CorElementType.cs index d21d72d554..8bd93447ac 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/Enums/CorElementType.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/Enums/CorElementType.cs @@ -32,9 +32,9 @@ namespace Debugger.Wrappers.CorDebug // Please use VALUETYPE. VALUECLASS is deprecated. VALUETYPE = 0x11, // VALUETYPE CLASS = 0x12, // CLASS - + VAR = 0x13, ARRAY = 0x14, // MDARRAY ... ... - + GENERICINST = 0x15, TYPEDBYREF = 0x16, // This is a simple type. I = 0x18, // native integer size diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs index 145cc495af..6d7f91d658 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs @@ -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 sig = new Queue(typeSpecBlob.GetData()); + return Create(module, sig, signatureContext); } else { throw new DebuggerException("Unknown token type"); } + } + + public static DebugType Create(Module module, Queue sig) + { + return Create(module, sig, null); + } + + /// Type definition to use to resolve numbered generic references + public static DebugType Create(Module module, Queue 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().GetParameterizedType((uint)classOrValueType, genArgs); + return Create(module.Process, genInstance); + } + + throw new NotImplementedException(); + } + + static uint ReadTypeDefOrRefEncoded(Queue 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 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 } } + // 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 { // 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 diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaDataImport.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaDataImport.cs index f0053e5dae..2686c88393 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaDataImport.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaDataImport.cs @@ -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); diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs index fb05913cdf..4aaef957eb 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs @@ -6,6 +6,7 @@ // using System; +using System.Collections.Generic; namespace Debugger.Tests.TestPrograms { @@ -16,14 +17,15 @@ namespace Debugger.Tests.TestPrograms } - public interface MyInterface + public interface MyInterface { - + K ItemKey { get; } } - public class MyInterfaceImpl: MyInterface + public class MyInterfaceImpl : MyInterface, 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 Point locStruct; Point* locStructPtr = &locStruct; object box = 40; - MyInterfaceImpl myInterfaceImpl = new MyInterfaceImpl(); - MyInterface myInterface = myInterfaceImpl; + MyInterfaceImpl myInterfaceImpl = new MyInterfaceImpl(); + MyInterface, MyClass> myInterface = myInterfaceImpl; System.Diagnostics.Debugger.Break(); @@ -105,7 +107,7 @@ namespace Debugger.Tests { mscorlib.dll (No symbols) DebugTypes.exe (Has symbols) - Break DebugTypes.cs:57,4-57,40 + Break DebugTypes.cs:59,4-59,40 @@ -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<System.Int32>, System.IEquatable<System.Int32>}" Kind="ValueType" Module="mscorlib.dll" Name="Int32"> @@ -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<System.Int32>}" Expression="myInterfaceImpl" IsInvalid="False" IsNull="False" IsReference="True" PrimitiveValue="{Exception: Value is not a primitive type}" - Type="MyInterfaceImpl"> + Type="MyInterfaceImpl<System.Int32>"> + Name="MyInterfaceImpl<Int32>"> null @@ -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<System.Int32>}" Expression="myInterface" IsInvalid="False" IsNull="False" IsReference="True" PrimitiveValue="{Exception: Value is not a primitive type}" - Type="MyInterfaceImpl"> + Type="MyInterfaceImpl<System.Int32>"> + Name="MyInterfaceImpl<Int32>"> null - Break DebugTypes.cs:74,4-74,40 + Break DebugTypes.cs:76,4-76,40 @@ -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<System.Int32>, System.IEquatable<System.Int32>}" Kind="ValueType" Module="mscorlib.dll" Name="Int32"> @@ -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<System.Int32>, System.IEquatable<System.Int32>}" Kind="ValueType" Module="mscorlib.dll" Name="Int32"> diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/GenericDictionary.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/GenericDictionary.cs index 0cdd064fcb..24f28988ff 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/GenericDictionary.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/GenericDictionary.cs @@ -1,7 +1,7 @@ // // // -// +// // $Revision$ //