public void TestGenericMethodInterfaceMethodImplOverride() { // // Ensure MethodImpl based overriding works for MethodSpecs // MetadataType interfaceType = _testModule.GetType("VirtualFunctionOverride", "IIFaceWithGenericMethod"); MethodDesc interfaceMethod = null; foreach (MethodDesc m in interfaceType.GetMethods()) { if (m.Name == "GenMethod") { interfaceMethod = m; break; } } Assert.NotNull(interfaceMethod); MetadataType objectType = _testModule.GetType("VirtualFunctionOverride", "HasMethodInterfaceOverrideOfGenericMethod"); MethodDesc expectedVirtualMethod = null; foreach (MethodDesc m in objectType.GetMethods()) { if (m.Name.Contains("GenMethod")) { expectedVirtualMethod = m; break; } } Assert.NotNull(expectedVirtualMethod); Assert.Equal(expectedVirtualMethod, VirtualFunctionResolution.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, objectType)); }
public sealed override bool TryGetModuleTokenForExternalType(TypeDesc type, out ModuleToken token) { Debug.Assert(!VersionsWithType(type)); if (_typeRefsInCompilationModuleSet == null) { _typeRefsInCompilationModuleSet = new Dictionary <TypeDesc, ModuleToken>(); foreach (var module in _compilationModuleSet) { EcmaModule ecmaModule = (EcmaModule)module; foreach (var typeRefHandle in ecmaModule.MetadataReader.TypeReferences) { try { TypeDesc typeFromTypeRef = ecmaModule.GetType(typeRefHandle); if (!_typeRefsInCompilationModuleSet.ContainsKey(typeFromTypeRef)) { _typeRefsInCompilationModuleSet.Add(typeFromTypeRef, new ModuleToken(ecmaModule, typeRefHandle)); } } catch (TypeSystemException) { } } } } return(_typeRefsInCompilationModuleSet.TryGetValue(type, out token)); }
private uint LookupIbcTypeToken(EcmaModule externalModule, uint ibcToken, Dictionary <IBCBlobKey, BlobEntry> blobs) { var typeEntry = (BlobEntry.ExternalTypeEntry)blobs[new IBCBlobKey(ibcToken, BlobType.ExternalTypeDef)]; string typeNamespace = null; string typeName = Encoding.UTF8.GetString(typeEntry.Name); TypeDefinitionHandle enclosingType = default; if (!Cor.Macros.IsNilToken(typeEntry.NamespaceToken)) { if (!Cor.Macros.IsNilToken(typeEntry.NestedClassToken)) { // Do not support typedef with namespace that is nested throw new Exception($"Ibc TypeToken {ibcToken:x} has both Namespace and NestedClass tokens"); } uint nameSpaceToken = typeEntry.NamespaceToken; if (Cor.Macros.TypeFromToken(nameSpaceToken) != CorTokenType.ibcExternalNamespace) { throw new Exception($"Ibc TypeToken {ibcToken:x} has Namespace tokens that is not a ibcExternalNamespace"); } var namespaceEntry = (BlobEntry.ExternalNamespaceEntry)blobs[new IBCBlobKey(nameSpaceToken, BlobType.ExternalNamespaceDef)]; typeNamespace = Encoding.UTF8.GetString(namespaceEntry.Name); } else if (!Cor.Macros.IsNilToken(typeEntry.NestedClassToken)) { uint enclosingTypeTokenValue = LookupIbcTypeToken(externalModule, typeEntry.NestedClassToken, blobs); if (Cor.Macros.TypeFromToken(enclosingTypeTokenValue) != CorTokenType.mdtTypeDef) { throw new Exception($"Ibc TypeToken {ibcToken:x} has NestedClass token which does not resolve to a type definition"); } enclosingType = MetadataTokens.TypeDefinitionHandle((int)Cor.Macros.RidFromToken(enclosingTypeTokenValue)); if (enclosingType.IsNil) { throw new Exception($"Ibc TypeToken {ibcToken:x} has NestedClass token which resolves to a nil token"); } } if (enclosingType.IsNil) { return((uint)externalModule.MetadataReader.GetToken(((EcmaType)externalModule.GetType(typeNamespace, typeName)).Handle)); } else { TypeDefinition nestedClassDefinition = externalModule.MetadataReader.GetTypeDefinition(enclosingType); MetadataStringComparer stringComparer = externalModule.MetadataReader.StringComparer; foreach (TypeDefinitionHandle tdNested in nestedClassDefinition.GetNestedTypes()) { TypeDefinition candidateClassDefinition = externalModule.MetadataReader.GetTypeDefinition(tdNested); if (stringComparer.Equals(candidateClassDefinition.Name, typeName)) { return((uint)externalModule.MetadataReader.GetToken(tdNested)); } } throw new Exception($"Ibc TypeToken {ibcToken:x} unable to find nested type '{typeName}' on type '{externalModule.MetadataReader.GetToken(enclosingType):x}'"); } }
public void TestNoPointers() { MetadataType t = _testModule.GetType("StaticFieldLayout", "NoPointers"); foreach (var field in t.GetFields()) { if (!field.IsStatic) { continue; } switch (field.Name) { case "int1": Assert.Equal(0, field.Offset); break; case "byte1": Assert.Equal(4, field.Offset); break; case "char1": Assert.Equal(6, field.Offset); break; default: throw new Exception(field.Name); } } }
public void TestInstanceLayoutDoubleBool() { MetadataType tX64 = _testModuleX64.GetType("Sequential", "ClassDoubleBool"); MetadataType tX86 = _testModuleX86.GetType("Sequential", "ClassDoubleBool"); MetadataType tARM = _testModuleARM.GetType("Sequential", "ClassDoubleBool"); Assert.Equal(0x8, tX64.InstanceByteAlignment); Assert.Equal(0x8, tARM.InstanceByteAlignment); Assert.Equal(0x4, tX86.InstanceByteAlignment); Assert.Equal(0x11, tX64.InstanceByteCountUnaligned); Assert.Equal(0x11, tARM.InstanceByteCountUnaligned); Assert.Equal(0x11, tX86.InstanceByteCountUnaligned); Assert.Equal(0x18, tX64.InstanceByteCount); Assert.Equal(0x18, tARM.InstanceByteCount); Assert.Equal(0x14, tX86.InstanceByteCount); }
private static IEnumerable <VerificationResult> Verify(TestCase testCase) { EcmaModule module = TestDataLoader.GetModuleForTestAssembly(testCase.ModuleName); var typeHandle = (TypeDefinitionHandle)MetadataTokens.EntityHandle(testCase.MetadataToken); var type = (EcmaType)module.GetType(typeHandle); var verifier = new Verifier((ILVerifyTypeSystemContext)type.Context); return(verifier.Verify(module.PEReader, typeHandle)); }
public void SetSystemModule(EcmaModule systemModule) { _systemModule = systemModule; // Sanity check the name table Debug.Assert(s_wellKnownTypeNames[(int)WellKnownType.MulticastDelegate - 1] == "MulticastDelegate"); // Initialize all well known types - it will save us from checking the name for each loaded type for (int typeIndex = 0; typeIndex < _wellKnownTypes.Length; typeIndex++) { MetadataType type = _systemModule.GetType("System", s_wellKnownTypeNames[typeIndex]); type.SetWellKnownType((WellKnownType)(typeIndex + 1)); _wellKnownTypes[typeIndex] = type; } }
private MetadataType LoadTypeFromIBCZapSig(IBCModule ibcModule, EcmaModule ecmaModule, CorElementType typ, ref BlobReader sig) { switch (typ) { case CorElementType.ELEMENT_TYPE_CLASS: case CorElementType.ELEMENT_TYPE_VALUETYPE: uint token = (uint)ibcModule.EcmaModule.MetadataReader.GetToken(sig.ReadTypeHandle()); if (ecmaModule != ibcModule.EcmaModule) { // ibcExternalType tokens are actually encoded as mdtTypeDef tokens in the signature uint rid = Cor.Macros.RidFromToken(token); uint ibcToken = Cor.Macros.TokenFromRid(rid, CorTokenType.ibcExternalType); token = LookupIbcTypeToken(ref ecmaModule, ibcToken, ibcModule.Blobs); } switch (Cor.Macros.TypeFromToken(token)) { case CorTokenType.mdtTypeDef: case CorTokenType.mdtTypeRef: // success break; default: throw new Exception("Invalid token found while parsing IBC ZapSig generic instantiation"); } if (Cor.Macros.IsNilToken(token)) { return(null); } var result = (MetadataType)ecmaModule.GetType(MetadataTokens.EntityHandle((int)token)); if ((typ == CorElementType.ELEMENT_TYPE_VALUETYPE) != result.IsValueType) { if (_logger.IsVerbose) { _logger.Writer.WriteLine("Mismatch between valuetype and reference type in while parsing generic instantiation"); } return(null); } return(result); default: if (_logger.IsVerbose) { _logger.Writer.WriteLine("Unexpected token type parsing ELEMENT_TYPE_GENERICINST"); } return(null); } }
public override bool TryGetModuleTokenForExternalType(TypeDesc type, out ModuleToken token) { Debug.Assert(!VersionsWithType(type)); if (_typeRefsInCompilationModuleSet == null) { _typeRefsInCompilationModuleSet = new Dictionary <TypeDesc, ModuleToken>(); EcmaModule ecmaModule = ((EcmaMethod)_method.GetTypicalMethodDefinition()).Module; foreach (var typeRefHandle in ecmaModule.MetadataReader.TypeReferences) { try { TypeDesc typeFromTypeRef = ecmaModule.GetType(typeRefHandle); _typeRefsInCompilationModuleSet[typeFromTypeRef] = new ModuleToken(ecmaModule, typeRefHandle); } catch (TypeSystemException) { } } } return(_typeRefsInCompilationModuleSet.TryGetValue(type, out token)); }
// LookupIbcTypeToken and (possibly) find the module associated with it. // externalModule may be null if the exact assembly isn't known private uint LookupIbcTypeToken(ref EcmaModule externalModule, uint ibcToken, Dictionary <IBCBlobKey, BlobEntry> blobs) { if (!blobs.TryGetValue(new IBCBlobKey(ibcToken, BlobType.ExternalTypeDef), out BlobEntry externalTypeDefBlob)) { if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} unable to find external typedef"); } return(Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef)); // Nil TypeDef token } var typeEntry = (BlobEntry.ExternalTypeEntry)externalTypeDefBlob; string typeNamespace = ""; string typeName = Encoding.UTF8.GetString(typeEntry.Name, 0, typeEntry.Name.Length - 1 /* these strings are null terminated */); TypeDefinitionHandle enclosingType = default; if (!Cor.Macros.IsNilToken(typeEntry.NamespaceToken)) { if (!Cor.Macros.IsNilToken(typeEntry.NestedClassToken)) { // Do not support typedef with namespace that is nested throw new Exception($"Ibc TypeToken {ibcToken:x} has both Namespace and NestedClass tokens"); } uint nameSpaceToken = typeEntry.NamespaceToken; if (Cor.Macros.TypeFromToken(nameSpaceToken) != CorTokenType.ibcExternalNamespace) { throw new Exception($"Ibc TypeToken {ibcToken:x} has Namespace tokens that is not a ibcExternalNamespace"); } if (!blobs.TryGetValue(new IBCBlobKey(nameSpaceToken, BlobType.ExternalNamespaceDef), out BlobEntry namespaceEntryBlob)) { if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} unable to find external namespace blob '{nameSpaceToken:x}"); } return(Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef)); // Nil TypeDef token } var namespaceEntry = (BlobEntry.ExternalNamespaceEntry)namespaceEntryBlob; typeNamespace = Encoding.UTF8.GetString(namespaceEntry.Name, 0, namespaceEntry.Name.Length - 1 /* these strings are null terminated */); } else if (!Cor.Macros.IsNilToken(typeEntry.NestedClassToken)) { uint enclosingTypeTokenValue = LookupIbcTypeToken(ref externalModule, typeEntry.NestedClassToken, blobs); if (Cor.Macros.TypeFromToken(enclosingTypeTokenValue) != CorTokenType.mdtTypeDef) { throw new Exception($"Ibc TypeToken {ibcToken:x} has NestedClass token which does not resolve to a type definition"); } enclosingType = MetadataTokens.TypeDefinitionHandle((int)Cor.Macros.RidFromToken(enclosingTypeTokenValue)); if (enclosingType.IsNil && _logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} has NestedClass token which resolves to a nil token"); } } if (enclosingType.IsNil) { EcmaType foundType = null; if (externalModule == null) { // Lookup actual module scenario. foreach (ModuleDesc m in _possibleReferenceModules) { if (!(m is EcmaModule)) { continue; } foundType = (EcmaType)m.GetType(typeNamespace, typeName, throwIfNotFound: false); if (foundType != null) { externalModule = foundType.EcmaModule; break; } } } else { foundType = (EcmaType)externalModule.GetType(typeNamespace, typeName, throwIfNotFound: false); } if (foundType == null) { if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} has type token which resolves to a nil token"); } return(Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef)); // Nil TypeDef token } return((uint)externalModule.MetadataReader.GetToken(foundType.Handle)); } else { TypeDefinition nestedClassDefinition = externalModule.MetadataReader.GetTypeDefinition(enclosingType); MetadataStringComparer stringComparer = externalModule.MetadataReader.StringComparer; foreach (TypeDefinitionHandle tdNested in nestedClassDefinition.GetNestedTypes()) { TypeDefinition candidateClassDefinition = externalModule.MetadataReader.GetTypeDefinition(tdNested); if (stringComparer.Equals(candidateClassDefinition.Name, typeName)) { return((uint)externalModule.MetadataReader.GetToken(tdNested)); } } if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} unable to find nested type '{typeName}' on type '{externalModule.MetadataReader.GetToken(enclosingType):x}'"); } return(Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef)); // Nil TypeDef token } }
public TypeDesc ResolveTypeHandle(long handle, bool throwIfNotFound = true) { lock(_lock) { TypeHandleInfo tinfo; if (_types.TryGetValue(handle, out tinfo)) { if (tinfo.Type != null) return tinfo.Type; if ((tinfo.TypeValue.Flags & Microsoft.Diagnostics.Tracing.Parsers.Clr.TypeFlags.Array) != 0) { if (tinfo.TypeValue.TypeParameters.Length != 1) { throw new Exception("Bad format for BulkType"); } TypeDesc elementType = ResolveTypeHandle((long)tinfo.TypeValue.TypeParameters[0], throwIfNotFound); if (elementType == null) return null; if (tinfo.TypeValue.CorElementType == (byte)SignatureTypeCode.SZArray) { tinfo.Type = elementType.MakeArrayType(); } else { int rank = tinfo.TypeValue.Flags.GetArrayRank(); tinfo.Type = elementType.MakeArrayType(rank); } } else if (tinfo.TypeValue.CorElementType == (byte)SignatureTypeCode.ByReference) { if (tinfo.TypeValue.TypeParameters.Length != 1) { throw new Exception("Bad format for BulkType"); } TypeDesc elementType = ResolveTypeHandle((long)tinfo.TypeValue.TypeParameters[0], throwIfNotFound); if (elementType == null) return null; tinfo.Type = elementType.MakeByRefType(); } else if (tinfo.TypeValue.CorElementType == (byte)SignatureTypeCode.Pointer) { if (tinfo.TypeValue.TypeParameters.Length != 1) { throw new Exception("Bad format for BulkType"); } TypeDesc elementType = ResolveTypeHandle((long)tinfo.TypeValue.TypeParameters[0], throwIfNotFound); if (elementType == null) return null; tinfo.Type = elementType.MakePointerType(); } else if (tinfo.TypeValue.CorElementType == (byte)SignatureTypeCode.FunctionPointer) { tinfo.Type = null; } else { // Must be class type or instantiated type. ModuleDesc module = ResolveModuleID((long)tinfo.TypeValue.ModuleID, throwIfNotFound); if (module == null) return null; EcmaModule ecmaModule = module as EcmaModule; if (ecmaModule == null) { if (throwIfNotFound) throw new Exception($"Unable to resolve module for {handle:8x}"); return null; } if ((tinfo.TypeValue.TypeNameID & 0xFF000000) != 0x02000000) { throw new Exception($"Invalid typedef {tinfo.TypeValue.TypeNameID:4x}"); } TypeDefinitionHandle typedef = MetadataTokens.TypeDefinitionHandle(tinfo.TypeValue.TypeNameID & 0xFFFFFF); MetadataType uninstantiatedType = (MetadataType)ecmaModule.GetType(typedef); // Instantiate the type if requested if ((tinfo.TypeValue.TypeParameters.Length != 0) && uninstantiatedType != null) { if (uninstantiatedType.Instantiation.Length != tinfo.TypeValue.TypeParameters.Length) { throw new Exception($"Invalid TypeParameterCount {tinfo.TypeValue.TypeParameters.Length} expected {uninstantiatedType.Instantiation.Length} as needed by '{uninstantiatedType}'"); } TypeDesc[] instantiation = new TypeDesc[tinfo.TypeValue.TypeParameters.Length]; for (int i = 0; i < instantiation.Length; i++) { instantiation[i] = ResolveTypeHandle((long)tinfo.TypeValue.TypeParameters[i], throwIfNotFound); if (instantiation[i] == null) return null; } tinfo.Type = uninstantiatedType.Context.GetInstantiatedType(uninstantiatedType, new Instantiation(instantiation)); } else { if ((uninstantiatedType.Name == "__Canon") && uninstantiatedType.Namespace == "System" && (uninstantiatedType.Module == uninstantiatedType.Context.SystemModule)) { tinfo.Type = uninstantiatedType.Context.CanonType; } else { tinfo.Type = uninstantiatedType; } } } if (tinfo.Type == null) { if (throwIfNotFound) throw new Exception("Unknown typeHandle value"); return null; } return tinfo.Type; } else { if (throwIfNotFound) throw new Exception("Unknown typeHandle value"); return null; } } }
public override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForNonPointerArrayType(ArrayType type) { if (_arrayOfTRuntimeInterfacesAlgorithm == null) { _arrayOfTRuntimeInterfacesAlgorithm = new ArrayOfTRuntimeInterfacesAlgorithm(_systemModule.GetType("System", "Array`1")); } return(_arrayOfTRuntimeInterfacesAlgorithm); }
public void TestExplicitLayout() { MetadataType t = _testModule.GetType("Explicit", "Class1"); // With 64bit, there should be 8 bytes for the System.Object EE data pointer + // 10 bytes up until the offset of the char field + the char size of 2 + we // round up the whole instance size to the next pointer size (+4) = 24 Assert.Equal(24, t.InstanceByteCount); foreach (var field in t.GetFields()) { if (field.IsStatic) { continue; } if (field.Name == "Bar") { // Bar has explicit offset 4 and is in a class (with S.O size overhead of <pointer size>) // Therefore it should have offset 4 + 8 = 12 Assert.Equal(12, field.Offset); } else if (field.Name == "Baz") { // Baz has explicit offset 10. 10 + 8 = 18 Assert.Equal(18, field.Offset); } else { Assert.True(false); } } }
public void TestSingleDimensionalArrays() { MetadataType systemArrayType = _context.GetWellKnownType(WellKnownType.Array); MetadataType systemIListOfTType = _testModule.GetType("System.Collections.Generic", "IList`1"); TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object); ArrayType objectArray = (ArrayType)_context.GetArrayType(objectType); // The set of interfaces on an array shall start with the same set that exists on System.Array for (int i = 0; i < systemArrayType.RuntimeInterfaces.Length; i++) { Assert.Equal(systemArrayType.RuntimeInterfaces[i], objectArray.RuntimeInterfaces[i]); } // The set of interfaces on an array of type T shall include IList<T> TypeDesc ilistOfObject = _context.GetInstantiatedType(systemIListOfTType, new Instantiation(new TypeDesc[] { objectType })); Assert.Contains(ilistOfObject, objectArray.RuntimeInterfaces); }