private List <CustomAttribute> HandleCustomAttributes(Cts.Ecma.EcmaModule module, Ecma.CustomAttributeHandleCollection attributes) { List <CustomAttribute> customAttributes = new List <CustomAttribute>(attributes.Count); var attributeTypeProvider = new Cts.Ecma.CustomAttributeTypeProvider(module); foreach (var attributeHandle in attributes) { Ecma.MetadataReader reader = module.MetadataReader; Ecma.CustomAttribute attribute = reader.GetCustomAttribute(attributeHandle); // TODO-NICE: We can intern the attributes based on the CA constructor and blob bytes Cts.MethodDesc constructor = module.GetMethod(attribute.Constructor); var decodedValue = attribute.DecodeValue(attributeTypeProvider); if (IsBlockedCustomAttribute(constructor, decodedValue)) { continue; } customAttributes.Add(HandleCustomAttribute(constructor, decodedValue)); } return(customAttributes); }
private void InitializeTypeForwarder(ForwarderKey key, TypeForwarder record) { Cts.Ecma.EcmaModule module = key.Module; Ecma.MetadataReader reader = module.MetadataReader; Ecma.ExportedType exportedType = reader.GetExportedType(key.ExportedType); record.Name = HandleString(reader.GetString(exportedType.Name)); switch (exportedType.Implementation.Kind) { case Ecma.HandleKind.AssemblyReference: { string ns = reader.GetString(exportedType.Namespace); NamespaceDefinition namespaceDefinition = HandleNamespaceDefinition(module, ns); Ecma.AssemblyReference assemblyRef = reader.GetAssemblyReference((Ecma.AssemblyReferenceHandle)exportedType.Implementation); AssemblyName refName = new AssemblyName { ContentType = (AssemblyContentType)((int)(assemblyRef.Flags & AssemblyFlags.ContentTypeMask) >> 9), Flags = (AssemblyNameFlags)(assemblyRef.Flags & ~AssemblyFlags.ContentTypeMask), CultureName = reader.GetString(assemblyRef.Culture), Name = reader.GetString(assemblyRef.Name), Version = assemblyRef.Version, }; if ((assemblyRef.Flags & AssemblyFlags.PublicKey) != 0) { refName.SetPublicKey(reader.GetBlobBytes(assemblyRef.PublicKeyOrToken)); } else { refName.SetPublicKeyToken(reader.GetBlobBytes(assemblyRef.PublicKeyOrToken)); } record.Scope = HandleScopeReference(refName); namespaceDefinition.TypeForwarders.Add(record); } break; case Ecma.HandleKind.ExportedType: { TypeForwarder scope = HandleTypeForwarder(module, (Ecma.ExportedTypeHandle)exportedType.Implementation); record.Scope = scope.Scope; scope.NestedTypes.Add(record); } break; default: throw new BadImageFormatException(); } }
private TypeForwarder HandleTypeForwarder(Cts.Ecma.EcmaModule module, Ecma.ExportedType exportedType) { Ecma.MetadataReader reader = module.MetadataReader; string name = reader.GetString(exportedType.Name); TypeForwarder result; switch (exportedType.Implementation.Kind) { case Ecma.HandleKind.AssemblyReference: { string ns = reader.GetString(exportedType.Namespace); NamespaceDefinition namespaceDefinition = HandleNamespaceDefinition(module, ns); Ecma.AssemblyReference assemblyRef = reader.GetAssemblyReference((Ecma.AssemblyReferenceHandle)exportedType.Implementation); AssemblyName refName = new AssemblyName { ContentType = (AssemblyContentType)((int)(assemblyRef.Flags & AssemblyFlags.ContentTypeMask) >> 9), Flags = (AssemblyNameFlags)(assemblyRef.Flags & ~AssemblyFlags.ContentTypeMask), CultureName = reader.GetString(assemblyRef.Culture), Name = reader.GetString(assemblyRef.Name), Version = assemblyRef.Version, }; result = new TypeForwarder { Name = HandleString(name), Scope = HandleScopeReference(refName), }; namespaceDefinition.TypeForwarders.Add(result); } break; case Ecma.HandleKind.ExportedType: { TypeForwarder scope = HandleTypeForwarder(module, reader.GetExportedType((Ecma.ExportedTypeHandle)exportedType.Implementation)); result = new TypeForwarder { Name = HandleString(name), Scope = scope.Scope, }; scope.NestedTypes.Add(result); } break; default: throw new BadImageFormatException(); } return(result); }
private void InitializeScopeDefinition(Cts.ModuleDesc module, ScopeDefinition scopeDefinition) { // Make sure we're expected to create a scope definition here. If the assert fires, the metadata // policy should have directed us to create a scope reference (or the list of inputs was incomplete). Debug.Assert(_modulesToTransform.Contains(module), "Incomplete list of input modules with respect to metadata policy"); var assemblyDesc = module as Cts.IAssemblyDesc; if (assemblyDesc != null) { var assemblyName = assemblyDesc.GetName(); scopeDefinition.Name = HandleString(assemblyName.Name); #if NETFX_45 // With NET 4.5 contract System.Reflection 4.0.0.0 EcmaModule has no way // to set Culture in its AssemblyName. scopeDefinition.Culture = HandleString(assemblyName.CultureName ?? ""); #else scopeDefinition.Culture = HandleString(assemblyName.CultureName); #endif scopeDefinition.MajorVersion = checked ((ushort)assemblyName.Version.Major); scopeDefinition.MinorVersion = checked ((ushort)assemblyName.Version.Minor); scopeDefinition.BuildNumber = checked ((ushort)assemblyName.Version.Build); scopeDefinition.RevisionNumber = checked ((ushort)assemblyName.Version.Revision); Debug.Assert((int)AssemblyFlags.PublicKey == (int)AssemblyNameFlags.PublicKey); Debug.Assert((int)AssemblyFlags.Retargetable == (int)AssemblyNameFlags.Retargetable); scopeDefinition.Flags = (AssemblyFlags)assemblyName.Flags; if (assemblyName.ContentType == AssemblyContentType.WindowsRuntime) { scopeDefinition.Flags |= (AssemblyFlags)((int)AssemblyContentType.WindowsRuntime << 9); } scopeDefinition.PublicKey = assemblyName.GetPublicKey(); Cts.Ecma.EcmaModule ecmaModule = module as Cts.Ecma.EcmaModule; if (ecmaModule != null) { Ecma.CustomAttributeHandleCollection customAttributes = ecmaModule.AssemblyDefinition.GetCustomAttributes(); if (customAttributes.Count > 0) { scopeDefinition.CustomAttributes = HandleCustomAttributes(ecmaModule, customAttributes); } } } else { throw new NotSupportedException("Multi-module assemblies"); } }
private void HandleTypeForwarders(Cts.Ecma.EcmaModule module) { foreach (var exportedTypeHandle in module.MetadataReader.ExportedTypes) { Ecma.ExportedType exportedType = module.MetadataReader.GetExportedType(exportedTypeHandle); if (exportedType.IsForwarder || exportedType.Implementation.Kind == Ecma.HandleKind.ExportedType) { HandleTypeForwarder(module, exportedType); } else { Debug.Assert(false, "Multi-module assemblies"); } } }
private Property HandleProperty(Cts.Ecma.EcmaModule module, Ecma.PropertyDefinitionHandle property) { Ecma.MetadataReader reader = module.MetadataReader; Ecma.PropertyDefinition propDef = reader.GetPropertyDefinition(property); Ecma.PropertyAccessors acc = propDef.GetAccessors(); Cts.MethodDesc getterMethod = acc.Getter.IsNil ? null : module.GetMethod(acc.Getter); Cts.MethodDesc setterMethod = acc.Setter.IsNil ? null : module.GetMethod(acc.Setter); bool getterHasMetadata = getterMethod != null && _policy.GeneratesMetadata(getterMethod); bool setterHasMetadata = setterMethod != null && _policy.GeneratesMetadata(setterMethod); // Policy: If neither the getter nor setter have metadata, property doesn't have metadata if (!getterHasMetadata && !setterHasMetadata) { return(null); } Ecma.BlobReader sigBlobReader = reader.GetBlobReader(propDef.Signature); Cts.PropertySignature sig = new Cts.Ecma.EcmaSignatureParser(module, sigBlobReader, Cts.NotFoundBehavior.Throw).ParsePropertySignature(); Property result = new Property { Name = HandleString(reader.GetString(propDef.Name)), Flags = propDef.Attributes, Signature = new PropertySignature { CallingConvention = sig.IsStatic ? CallingConventions.Standard : CallingConventions.HasThis, Type = HandleType(sig.ReturnType) }, }; result.Signature.Parameters.Capacity = sig.Length; for (int i = 0; i < sig.Length; i++) { result.Signature.Parameters.Add(HandleType(sig[i])); } if (getterHasMetadata) { result.MethodSemantics.Add(new MethodSemantics { Attributes = MethodSemanticsAttributes.Getter, Method = HandleMethodDefinition(getterMethod), }); } if (setterHasMetadata) { result.MethodSemantics.Add(new MethodSemantics { Attributes = MethodSemanticsAttributes.Setter, Method = HandleMethodDefinition(setterMethod), }); } Ecma.ConstantHandle defaultValue = propDef.GetDefaultValue(); if (!defaultValue.IsNil) { result.DefaultValue = HandleConstant(module, defaultValue); } Ecma.CustomAttributeHandleCollection customAttributes = propDef.GetCustomAttributes(); if (customAttributes.Count > 0) { result.CustomAttributes = HandleCustomAttributes(module, customAttributes); } return(result); }
private MetadataRecord HandleConstant(Cts.Ecma.EcmaModule module, Ecma.ConstantHandle constantHandle) { Ecma.MetadataReader reader = module.MetadataReader; Ecma.Constant constant = reader.GetConstant(constantHandle); Ecma.BlobReader blob = reader.GetBlobReader(constant.Value); switch (constant.TypeCode) { case ConstantTypeCode.Boolean: return(new ConstantBooleanValue { Value = blob.ReadBoolean() }); case ConstantTypeCode.Byte: return(new ConstantByteValue { Value = blob.ReadByte() }); case ConstantTypeCode.Char: return(new ConstantCharValue { Value = blob.ReadChar() }); case ConstantTypeCode.Double: return(new ConstantDoubleValue { Value = blob.ReadDouble() }); case ConstantTypeCode.Int16: return(new ConstantInt16Value { Value = blob.ReadInt16() }); case ConstantTypeCode.Int32: return(new ConstantInt32Value { Value = blob.ReadInt32() }); case ConstantTypeCode.Int64: return(new ConstantInt64Value { Value = blob.ReadInt64() }); case ConstantTypeCode.SByte: return(new ConstantSByteValue { Value = blob.ReadSByte() }); case ConstantTypeCode.Single: return(new ConstantSingleValue { Value = blob.ReadSingle() }); case ConstantTypeCode.String: return(HandleString(blob.ReadUTF16(blob.Length))); case ConstantTypeCode.UInt16: return(new ConstantUInt16Value { Value = blob.ReadUInt16() }); case ConstantTypeCode.UInt32: return(new ConstantUInt32Value { Value = blob.ReadUInt32() }); case ConstantTypeCode.UInt64: return(new ConstantUInt64Value { Value = blob.ReadUInt64() }); case ConstantTypeCode.NullReference: return(new ConstantReferenceValue()); default: throw new BadImageFormatException(); } }
private Event HandleEvent(Cts.Ecma.EcmaModule module, Ecma.EventDefinitionHandle eventHandle) { Ecma.MetadataReader reader = module.MetadataReader; Ecma.EventDefinition eventDef = reader.GetEventDefinition(eventHandle); Ecma.EventAccessors acc = eventDef.GetAccessors(); Cts.MethodDesc adderMethod = acc.Adder.IsNil ? null : module.GetMethod(acc.Adder); Cts.MethodDesc raiserMethod = acc.Raiser.IsNil ? null : module.GetMethod(acc.Raiser); Cts.MethodDesc removerMethod = acc.Remover.IsNil ? null : module.GetMethod(acc.Remover); bool adderHasMetadata = adderMethod != null && _policy.GeneratesMetadata(adderMethod); bool raiserHasMetadata = raiserMethod != null && _policy.GeneratesMetadata(raiserMethod); bool removerHasMetadata = removerMethod != null && _policy.GeneratesMetadata(removerMethod); // Policy: If none of the accessors has metadata, event doesn't have metadata if (!adderHasMetadata && !raiserHasMetadata && !removerHasMetadata) { return(null); } Event result = new Event { Name = HandleString(reader.GetString(eventDef.Name)), Flags = eventDef.Attributes, Type = HandleType(module.GetType(eventDef.Type)), }; if (adderHasMetadata) { result.MethodSemantics.Add(new MethodSemantics { Attributes = MethodSemanticsAttributes.AddOn, Method = HandleMethodDefinition(adderMethod), }); } if (raiserHasMetadata) { result.MethodSemantics.Add(new MethodSemantics { Attributes = MethodSemanticsAttributes.Fire, Method = HandleMethodDefinition(raiserMethod), }); } if (removerHasMetadata) { result.MethodSemantics.Add(new MethodSemantics { Attributes = MethodSemanticsAttributes.RemoveOn, Method = HandleMethodDefinition(removerMethod), }); } Ecma.CustomAttributeHandleCollection customAttributes = eventDef.GetCustomAttributes(); if (customAttributes.Count > 0) { result.CustomAttributes = HandleCustomAttributes(module, customAttributes); } return(result); }
private Property HandleProperty(Cts.Ecma.EcmaModule module, Ecma.PropertyDefinitionHandle property) { Ecma.MetadataReader reader = module.MetadataReader; Ecma.PropertyDefinition propDef = reader.GetPropertyDefinition(property); Ecma.PropertyAccessors acc = propDef.GetAccessors(); Cts.MethodDesc getterMethod = acc.Getter.IsNil ? null : module.GetMethod(acc.Getter); Cts.MethodDesc setterMethod = acc.Setter.IsNil ? null : module.GetMethod(acc.Setter); bool getterHasMetadata = getterMethod != null && _policy.GeneratesMetadata(getterMethod); bool setterHasMetadata = setterMethod != null && _policy.GeneratesMetadata(setterMethod); // Policy: If neither the getter nor setter have metadata, property doesn't have metadata if (!getterHasMetadata && !setterHasMetadata) { return(null); } Ecma.BlobReader sigBlobReader = reader.GetBlobReader(propDef.Signature); Cts.PropertySignature sig = new Cts.Ecma.EcmaSignatureParser(module, sigBlobReader).ParsePropertySignature(); List <ParameterTypeSignature> parameters; if (sig.Length == 0) { parameters = null; } else { parameters = new List <ParameterTypeSignature>(sig.Length); for (int i = 0; i < parameters.Count; i++) { parameters.Add(HandleParameterTypeSignature(sig[i])); } } Property result = new Property { Name = HandleString(reader.GetString(propDef.Name)), Flags = propDef.Attributes, Signature = new PropertySignature { CallingConvention = sig.IsStatic ? CallingConventions.Standard : CallingConventions.HasThis, // TODO: CustomModifiers Type = HandleType(sig.ReturnType), Parameters = parameters, }, }; if (getterHasMetadata) { result.MethodSemantics.Add(new MethodSemantics { Attributes = MethodSemanticsAttributes.Getter, Method = HandleMethodDefinition(getterMethod), }); } if (setterHasMetadata) { result.MethodSemantics.Add(new MethodSemantics { Attributes = MethodSemanticsAttributes.Setter, Method = HandleMethodDefinition(setterMethod), }); } // TODO: DefaultValue // TODO: CustomAttributes return(result); }
private TypeForwarder HandleTypeForwarder(Cts.Ecma.EcmaModule module, Ecma.ExportedTypeHandle handle) { return(_forwarders.GetOrCreate(new ForwarderKey(module, handle), _initForwarder ?? (_initForwarder = InitializeTypeForwarder))); }
public ForwarderKey(Cts.Ecma.EcmaModule module, Ecma.ExportedTypeHandle exportedType) => (Module, ExportedType) = (module, exportedType);