Example #1
0
        public MethodSemanticsLookup(MetadataReader metadata, MethodSemanticsAttributes filter = csharpAccessors)
        {
            if ((filter & MethodSemanticsAttributes.Other) != 0)
            {
                throw new NotSupportedException("SRM doesn't provide access to 'other' accessors");
            }
            entries = new List <Entry>(metadata.GetTableRowCount(TableIndex.MethodSemantics));
            foreach (var propHandle in metadata.PropertyDefinitions)
            {
                var prop      = metadata.GetPropertyDefinition(propHandle);
                var accessors = prop.GetAccessors();
                AddEntry(MethodSemanticsAttributes.Getter, accessors.Getter, propHandle);
                AddEntry(MethodSemanticsAttributes.Setter, accessors.Setter, propHandle);
            }
            foreach (var eventHandle in metadata.EventDefinitions)
            {
                var ev        = metadata.GetEventDefinition(eventHandle);
                var accessors = ev.GetAccessors();
                AddEntry(MethodSemanticsAttributes.Adder, accessors.Adder, eventHandle);
                AddEntry(MethodSemanticsAttributes.Remover, accessors.Remover, eventHandle);
                AddEntry(MethodSemanticsAttributes.Raiser, accessors.Raiser, eventHandle);
            }
            entries.Sort();

            void AddEntry(MethodSemanticsAttributes semantics, MethodDefinitionHandle method, EntityHandle association)
            {
                if ((semantics & filter) == 0 || method.IsNil)
                {
                    return;
                }
                entries.Add(new Entry(semantics, method, association));
            }
        }
Example #2
0
        public static TypeDefinitionHandle GetDeclaringType(this EntityHandle entity, MetadataReader metadata)
        {
            switch (entity.Kind)
            {
            case HandleKind.TypeDefinition:
                var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity);
                return(td.GetDeclaringType());

            case HandleKind.FieldDefinition:
                var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity);
                return(fd.GetDeclaringType());

            case HandleKind.MethodDefinition:
                var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity);
                return(md.GetDeclaringType());

            case HandleKind.EventDefinition:
                var ed = metadata.GetEventDefinition((EventDefinitionHandle)entity);
                return(metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType());

            case HandleKind.PropertyDefinition:
                var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)entity);
                return(metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType());

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Example #3
0
        /// <summary>
        /// This should produce a string representation of the entity for search to match search strings against.
        /// </summary>
        public virtual string GetEntityName(PEFile module, EntityHandle handle, bool fullName)
        {
            MetadataReader metadata = module.Metadata;

            switch (handle.Kind)
            {
            case HandleKind.TypeDefinition:
                if (fullName)
                {
                    return(((TypeDefinitionHandle)handle).GetFullTypeName(metadata).ToILNameString());
                }
                var td = metadata.GetTypeDefinition((TypeDefinitionHandle)handle);
                return(metadata.GetString(td.Name));

            case HandleKind.FieldDefinition:
                var fd            = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
                var declaringType = fd.GetDeclaringType();
                if (fullName)
                {
                    return(fd.GetDeclaringType().GetFullTypeName(metadata).ToILNameString() + "." + metadata.GetString(fd.Name));
                }
                return(metadata.GetString(fd.Name));

            case HandleKind.MethodDefinition:
                var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
                declaringType = md.GetDeclaringType();
                string methodName        = metadata.GetString(md.Name);
                int    genericParamCount = md.GetGenericParameters().Count;
                if (genericParamCount > 0)
                {
                    methodName += "``" + genericParamCount;
                }
                if (fullName)
                {
                    return(md.GetDeclaringType().GetFullTypeName(metadata).ToILNameString() + "." + methodName);
                }
                return(methodName);

            case HandleKind.EventDefinition:
                var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(declaringType.GetFullTypeName(metadata).ToILNameString() + "." + metadata.GetString(ed.Name));
                }
                return(metadata.GetString(ed.Name));

            case HandleKind.PropertyDefinition:
                var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(declaringType.GetFullTypeName(metadata).ToILNameString() + "." + metadata.GetString(pd.Name));
                }
                return(metadata.GetString(pd.Name));

            default:
                return(null);
            }
        }
        private Mapping <ConstantHandle> MapConstantImpl(ConstantHandle handle)
        {
            Constant         constant = _sourceMetadata.GetConstant(handle);
            Mapping <Handle> parent   = MapHandle(constant.Parent);

            if (parent.Target.IsNil)
            {
                return(new Mapping <ConstantHandle>());
            }

            ConstantHandle targetHandle;

            switch (parent.Target.Kind)
            {
            case HandleKind.Parameter:
                Parameter targetParameter = _targetMetadata.GetParameter((ParameterHandle)parent.Target);
                targetHandle = targetParameter.GetDefaultValue();
                break;

            case HandleKind.FieldDefinition:
                FieldDefinition targetFieldDefinition = _targetMetadata.GetFieldDefinition((FieldDefinitionHandle)parent.Target);
                targetHandle = targetFieldDefinition.GetDefaultValue();
                break;

            case HandleKind.PropertyDefinition:
                PropertyDefinition targetPropertyDefinition = _targetMetadata.GetPropertyDefinition((PropertyDefinitionHandle)parent.Target);
                targetHandle = targetPropertyDefinition.GetDefaultValue();
                break;

            default:
                throw new InvalidOperationException();
            }

            if (targetHandle.IsNil)
            {
                return(new Mapping <ConstantHandle>());
            }

            Constant targetConstant = _targetMetadata.GetConstant(targetHandle);

            if (constant.TypeCode != targetConstant.TypeCode)
            {
                var candidateTargets = ImmutableArray.Create(targetHandle);
                var candidateReasons = ImmutableArray.Create("Mapped constant has a different type.");
                return(new Mapping <ConstantHandle>(candidateTargets, candidateReasons));
            }

            ImmutableArray <byte> sourceContent = _sourceMetadata.GetBlobContent(constant.Value);
            ImmutableArray <byte> targetContent = _targetMetadata.GetBlobContent(targetConstant.Value);

            if (!sourceContent.SequenceEqual(targetContent))
            {
                var candidateTargets = ImmutableArray.Create(targetHandle);
                var candidateReasons = ImmutableArray.Create("Mapped constant has a different value.");
                return(new Mapping <ConstantHandle>(candidateTargets, candidateReasons));
            }

            return(new Mapping <ConstantHandle>(targetHandle));
        }
Example #5
0
 public PropertyDefEntry(PEFile module, PropertyDefinitionHandle handle)
 {
     this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
     this.module         = module;
     this.metadata       = module.Metadata;
     this.handle         = handle;
     this.propertyDef    = metadata.GetPropertyDefinition(handle);
 }
        public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaMethod method)
        {
            MetadataReader         reader       = method.MetadataReader;
            MethodDefinitionHandle methodHandle = method.Handle;
            MethodDefinition       methodDef    = reader.GetMethodDefinition(methodHandle);

            // Handle custom attributes on the method
            AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, methodDef.GetCustomAttributes());

            // Handle custom attributes on method parameters
            foreach (ParameterHandle parameterHandle in methodDef.GetParameters())
            {
                Parameter parameter = reader.GetParameter(parameterHandle);
                AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, parameter.GetCustomAttributes());
            }

            // Handle custom attributes on generic method parameters
            foreach (GenericParameterHandle genericParameterHandle in methodDef.GetGenericParameters())
            {
                GenericParameter parameter = reader.GetGenericParameter(genericParameterHandle);
                AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, parameter.GetCustomAttributes());
            }

            // We don't model properties and events as separate entities within the compiler, so ensuring
            // we can generate custom attributes for the associated events and properties from here
            // is as good as any other place.
            //
            // As a performance optimization, we look for associated events and properties only
            // if the method is SpecialName. This is required for CLS compliance and compilers we
            // care about emit accessors like this.
            if ((methodDef.Attributes & MethodAttributes.SpecialName) != 0)
            {
                TypeDefinition declaringType = reader.GetTypeDefinition(methodDef.GetDeclaringType());

                foreach (PropertyDefinitionHandle propertyHandle in declaringType.GetProperties())
                {
                    PropertyDefinition property  = reader.GetPropertyDefinition(propertyHandle);
                    PropertyAccessors  accessors = property.GetAccessors();

                    if (accessors.Getter == methodHandle || accessors.Setter == methodHandle)
                    {
                        AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, property.GetCustomAttributes());
                    }
                }

                foreach (EventDefinitionHandle eventHandle in declaringType.GetEvents())
                {
                    EventDefinition @event    = reader.GetEventDefinition(eventHandle);
                    EventAccessors  accessors = @event.GetAccessors();

                    if (accessors.Adder == methodHandle || accessors.Remover == methodHandle || accessors.Raiser == methodHandle)
                    {
                        AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, @event.GetCustomAttributes());
                    }
                }
            }
        }
        internal sealed override IEnumerable <PropertyInfo> CoreGetDeclaredProperties(NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType, RuntimeTypeInfo contextTypeInfo)
        {
            MetadataReader reader = Reader;

            foreach (PropertyDefinitionHandle propertyHandle in DeclaredPropertyHandles)
            {
                if (optionalNameFilter == null || optionalNameFilter.Matches(reader.GetPropertyDefinition(propertyHandle).Name, reader))
                {
                    yield return(EcmaFormatRuntimePropertyInfo.GetRuntimePropertyInfo(propertyHandle, this, contextTypeInfo, reflectedType));
                }
            }
        }
Example #8
0
        internal void Resolve(TRequest request, RequestSignature signature)
        {
            QualifiedName           qualifiedTypeName;
            ImmutableArray <string> memberTypeParameters;

            GetNameAndTypeParameters(signature.MemberName, out qualifiedTypeName, out memberTypeParameters);

            var typeName         = qualifiedTypeName.Qualifier;
            var memberName       = qualifiedTypeName.Name;
            var memberParameters = signature.Parameters;

            var allTypeParameters = GetAllGenericTypeParameters(typeName);

            foreach (var typeHandle in _reader.TypeDefinitions)
            {
                var typeDef         = _reader.GetTypeDefinition(typeHandle);
                int containingArity = CompareToTypeDefinition(typeDef, typeName);
                if (containingArity < 0)
                {
                    continue;
                }
                // Visit methods.
                foreach (var methodHandle in typeDef.GetMethods())
                {
                    var methodDef = _reader.GetMethodDefinition(methodHandle);
                    if (!IsResolvableMethod(methodDef))
                    {
                        continue;
                    }
                    if (MatchesMethod(typeDef, methodDef, typeName, memberName, allTypeParameters, containingArity, memberTypeParameters, memberParameters))
                    {
                        OnFunctionResolved(request, methodHandle);
                    }
                }
                if (memberTypeParameters.IsEmpty)
                {
                    // Visit properties.
                    foreach (var propertyHandle in typeDef.GetProperties())
                    {
                        var propertyDef = _reader.GetPropertyDefinition(propertyHandle);
                        if (MatchesProperty(typeDef, propertyDef, typeName, memberName, allTypeParameters, containingArity, memberParameters))
                        {
                            var accessors = propertyDef.GetAccessors();
                            OnAccessorResolved(request, accessors.Getter);
                            OnAccessorResolved(request, accessors.Setter);
                        }
                    }
                }
            }
        }
Example #9
0
        private static void Main(string[] args)
        {
            string assemblyPath = args[0];

            using (PEReader peReader = new PEReader(File.OpenRead(assemblyPath), PEStreamOptions.PrefetchMetadata))
            {
                ISet <AssemblyName> exposedDependencies = new HashSet <AssemblyName>(new AssemblyNameEqualityComparer());

                MetadataReader metadataReader = peReader.GetMetadataReader();
                foreach (var type in metadataReader.TypeDefinitions)
                {
                    TypeDefinition typeDefinition = metadataReader.GetTypeDefinition(type);
                    if (!IsExposedType(metadataReader, typeDefinition))
                    {
                        continue;
                    }

                    Console.WriteLine("Exposed type: {0}", GetFullName(metadataReader, typeDefinition));

                    CheckType(metadataReader, typeDefinition, exposedDependencies);

                    foreach (var eventDefinitionHandle in typeDefinition.GetEvents())
                    {
                        CheckEvent(metadataReader, metadataReader.GetEventDefinition(eventDefinitionHandle), exposedDependencies);
                    }

                    foreach (var methodDefinitionHandle in typeDefinition.GetMethods())
                    {
                        CheckMethod(metadataReader, metadataReader.GetMethodDefinition(methodDefinitionHandle), exposedDependencies);
                    }

                    foreach (var propertyDefinitionHandle in typeDefinition.GetProperties())
                    {
                        CheckProperty(metadataReader, metadataReader.GetPropertyDefinition(propertyDefinitionHandle), exposedDependencies);
                    }

                    foreach (var fieldDefinitionHandle in typeDefinition.GetFields())
                    {
                        CheckField(metadataReader, metadataReader.GetFieldDefinition(fieldDefinitionHandle), exposedDependencies);
                    }
                }

                Console.WriteLine();
                Console.WriteLine("Exposed Dependencies ({0}):", Path.GetFileName(args[0]));
                foreach (AssemblyName dependency in exposedDependencies.OrderBy(i => i.FullName, StringComparer.OrdinalIgnoreCase))
                {
                    Console.WriteLine("  {0}", dependency.FullName);
                }
            }
        }
        private static bool AddDependenciesFromPropertySetter(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, string propertyName)
        {
            EcmaType attributeTypeDefinition = (EcmaType)attributeType.GetTypeDefinition();

            MetadataReader reader         = attributeTypeDefinition.MetadataReader;
            var            typeDefinition = reader.GetTypeDefinition(attributeTypeDefinition.Handle);

            foreach (PropertyDefinitionHandle propDefHandle in typeDefinition.GetProperties())
            {
                PropertyDefinition propDef = reader.GetPropertyDefinition(propDefHandle);
                if (reader.StringComparer.Equals(propDef.Name, propertyName))
                {
                    PropertyAccessors accessors = propDef.GetAccessors();

                    if (!accessors.Setter.IsNil)
                    {
                        MethodDesc setterMethod = (MethodDesc)attributeTypeDefinition.EcmaModule.GetObject(accessors.Setter);
                        if (factory.MetadataManager.IsReflectionBlocked(setterMethod))
                        {
                            return(false);
                        }

                        // Method on a generic attribute
                        if (attributeType != attributeTypeDefinition)
                        {
                            setterMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(setterMethod, (InstantiatedType)attributeType);
                        }

                        // TODO: what if the setter is virtual/abstract?
                        dependencies.Add(factory.CanonicalEntrypoint(setterMethod), "Custom attribute blob");
                    }

                    return(true);
                }
            }

            // Haven't found it in current type. Check the base type.
            TypeDesc baseType = attributeType.BaseType;

            if (baseType != null)
            {
                return(AddDependenciesFromPropertySetter(dependencies, factory, baseType, propertyName));
            }

            // Not found. This is bad metadata that will result in a runtime failure, but we shouldn't fail the compilation.
            return(true);
        }
Example #11
0
        /// <summary>
        /// Get the information for a property.
        /// </summary>
        /// <param name="reader">The metadata reader.</param>
        /// <param name="handle">The property definition to read.</param>
        /// <returns>The property's information.</returns>
        public static PropertyInfo GetPropertyInfo(this MetadataReader reader, PropertyDefinitionHandle handle)
        {
            var propertyDefinition = reader.GetPropertyDefinition(handle);
            var accessors          = propertyDefinition.GetAccessors();
            var signature          = propertyDefinition.DecodeSignature(new SignatureTypeProvider(reader), null);

            return(new PropertyInfo
            {
                Name = reader.GetString(propertyDefinition.Name),

                Type = signature.ReturnType,

                HasGetter = !accessors.Getter.IsNil,
                HasSetter = !accessors.Setter.IsNil,

                Attributes = propertyDefinition.Attributes,
            });
        }
        public void WrongSignatureType()
        {
            using (FileStream stream = File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(typeof(VarArgsToDecode).GetTypeInfo().Assembly)))
                using (var peReader = new PEReader(stream))
                {
                    MetadataReader reader   = peReader.GetMetadataReader();
                    var            provider = new DisassemblingTypeProvider();
                    var            decoder  = new SignatureDecoder <string, DisassemblingGenericContext>(provider, reader, genericContext: null);

                    BlobReader fieldSignature    = reader.GetBlobReader(reader.GetFieldDefinition(MetadataTokens.FieldDefinitionHandle(1)).Signature);
                    BlobReader methodSignature   = reader.GetBlobReader(reader.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle(1)).Signature);
                    BlobReader propertySignature = reader.GetBlobReader(reader.GetPropertyDefinition(MetadataTokens.PropertyDefinitionHandle(1)).Signature);

                    Assert.Throws <BadImageFormatException>(() => decoder.DecodeMethodSignature(ref fieldSignature));
                    Assert.Throws <BadImageFormatException>(() => decoder.DecodeFieldSignature(ref methodSignature));
                    Assert.Throws <BadImageFormatException>(() => decoder.DecodeLocalSignature(ref propertySignature));
                }
        }
Example #13
0
        private static void ProcessPropertyDef(PropertyDefinitionHandle propertyDefHandle, MetadataReader dllReader, MetadataReader pdbReader, HashSet <DocumentHandle> docList)
        {
            var propertyDef = dllReader.GetPropertyDefinition(propertyDefHandle);
            var accessors   = propertyDef.GetAccessors();

            if (!accessors.Getter.IsNil)
            {
                ProcessMethodDef(accessors.Getter, dllReader, pdbReader, docList, processDeclaringType: true);
            }

            if (!accessors.Setter.IsNil)
            {
                ProcessMethodDef(accessors.Setter, dllReader, pdbReader, docList, processDeclaringType: true);
            }

            foreach (var other in accessors.Others)
            {
                ProcessMethodDef(other, dllReader, pdbReader, docList, processDeclaringType: true);
            }
        }
Example #14
0
        private void WalkProperty(MetadataReader mdReader, PropertyDefinitionHandle handle, MutableSymbol parent)
        {
            PropertyDefinition prop = mdReader.GetPropertyDefinition(handle);

            MutableSymbol result = new MutableSymbol(mdReader.GetString(prop.Name), SymbolType.Property);

            // Use the accessibility and location of the getter [or setter, if write only property]
            // Not identical to Roslyn PEPropertyDeclaration but much simpler
            MethodDefinitionHandle getterOrSetterHandle = prop.GetAccessors().Getter;

            if (getterOrSetterHandle.IsNil)
            {
                getterOrSetterHandle = prop.GetAccessors().Setter;
            }

            // If we couldn't retrieve a getter or setter, exclude this property
            if (getterOrSetterHandle.IsNil)
            {
                return;
            }

            MethodDefinition getterOrSetter = mdReader.GetMethodDefinition(getterOrSetterHandle);

            AddModifiers(getterOrSetter.Attributes, result);
            AddLocation(getterOrSetterHandle, result);
            AddParameters(mdReader, getterOrSetter, result);

            // If this is an Indexer, rename it and retype it
            // Roslyn PEPropertySymbol.IsIndexer is also just based on the name.
            if (result.Name == "Item")
            {
                result.Name = "this[]";
                result.Type = SymbolType.Indexer;
            }

            if (IsExcluded(result))
            {
                return;
            }
            parent.AddChild(result);
        }
Example #15
0
        public override string GetEntityName(PEFile module, EntityHandle handle, bool fullName)
        {
            MetadataReader metadata = module.Metadata;

            switch (handle.Kind)
            {
            case HandleKind.TypeDefinition:
                return(ToCSharpString(metadata, (TypeDefinitionHandle)handle, fullName));

            case HandleKind.FieldDefinition:
                var fd            = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
                var declaringType = fd.GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(fd.Name));
                }
                return(metadata.GetString(fd.Name));

            case HandleKind.MethodDefinition:
                var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
                declaringType = md.GetDeclaringType();
                string methodName = metadata.GetString(md.Name);
                switch (methodName)
                {
                case ".ctor":
                case ".cctor":
                    var td = metadata.GetTypeDefinition(declaringType);
                    methodName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(td.Name));
                    break;

                case "Finalize":
                    const MethodAttributes finalizerAttributes = (MethodAttributes.Virtual | MethodAttributes.Family | MethodAttributes.HideBySig);
                    if ((md.Attributes & finalizerAttributes) != finalizerAttributes)
                    {
                        goto default;
                    }
                    MethodSignature <IType> methodSignature = md.DecodeSignature(MetadataExtensions.MinimalSignatureTypeProvider, default);
                    if (methodSignature.GenericParameterCount != 0 || methodSignature.ParameterTypes.Length != 0)
                    {
                        goto default;
                    }
                    td         = metadata.GetTypeDefinition(declaringType);
                    methodName = "~" + ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(td.Name));
                    break;

                default:
                    var genericParams = md.GetGenericParameters();
                    if (genericParams.Count > 0)
                    {
                        methodName += "<";
                        int i = 0;
                        foreach (var h in genericParams)
                        {
                            if (i > 0)
                            {
                                methodName += ",";
                            }
                            var gp = metadata.GetGenericParameter(h);
                            methodName += metadata.GetString(gp.Name);
                        }
                        methodName += ">";
                    }
                    break;
                }
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + methodName);
                }
                return(methodName);

            case HandleKind.EventDefinition:
                var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(ed.Name));
                }
                return(metadata.GetString(ed.Name));

            case HandleKind.PropertyDefinition:
                var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(pd.Name));
                }
                return(metadata.GetString(pd.Name));

            default:
                return(null);
            }
        }
        public void SimpleSignatureProviderCoverage()
        {
            using (FileStream stream = File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(typeof(SignaturesToDecode <>).GetTypeInfo().Assembly)))
                using (var peReader = new PEReader(stream))
                {
                    MetadataReader       reader     = peReader.GetMetadataReader();
                    var                  provider   = new DisassemblingTypeProvider();
                    TypeDefinitionHandle typeHandle = TestMetadataResolver.FindTestType(reader, typeof(SignaturesToDecode <>));
                    Assert.Equal("System.Reflection.Metadata.Decoding.Tests.SignatureDecoderTests/SignaturesToDecode`1", provider.GetTypeFromHandle(reader, genericContext: null, handle: typeHandle));

                    TypeDefinition type = reader.GetTypeDefinition(typeHandle);
                    Dictionary <string, string> expectedFields        = GetExpectedFieldSignatures();
                    ImmutableArray <string>     genericTypeParameters = type.GetGenericParameters().Select(h => reader.GetString(reader.GetGenericParameter(h).Name)).ToImmutableArray();

                    var genericTypeContext = new DisassemblingGenericContext(genericTypeParameters, ImmutableArray <string> .Empty);

                    foreach (var fieldHandle in type.GetFields())
                    {
                        FieldDefinition field     = reader.GetFieldDefinition(fieldHandle);
                        string          fieldName = reader.GetString(field.Name);
                        string          expected;
                        Assert.True(expectedFields.TryGetValue(fieldName, out expected), "Unexpected field: " + fieldName);
                        Assert.Equal(expected, field.DecodeSignature(provider, genericTypeContext));
                    }

                    Dictionary <string, string> expectedMethods = GetExpectedMethodSignatures();
                    foreach (var methodHandle in type.GetMethods())
                    {
                        MethodDefinition method = reader.GetMethodDefinition(methodHandle);

                        ImmutableArray <string> genericMethodParameters = method.GetGenericParameters().Select(h => reader.GetString(reader.GetGenericParameter(h).Name)).ToImmutableArray();
                        var genericMethodContext = new DisassemblingGenericContext(genericTypeParameters, genericMethodParameters);

                        string methodName = reader.GetString(method.Name);
                        string expected;
                        Assert.True(expectedMethods.TryGetValue(methodName, out expected), "Unexpected method: " + methodName);
                        MethodSignature <string> signature = method.DecodeSignature(provider, genericMethodContext);
                        Assert.True(signature.Header.Kind == SignatureKind.Method);

                        if (methodName.StartsWith("Generic"))
                        {
                            Assert.Equal(1, signature.GenericParameterCount);
                        }
                        else
                        {
                            Assert.Equal(0, signature.GenericParameterCount);
                        }

                        Assert.True(signature.GenericParameterCount <= 1 && (methodName != "GenericMethodParameter" || signature.GenericParameterCount == 1));
                        Assert.Equal(expected, provider.GetFunctionPointerType(signature));
                    }

                    Dictionary <string, string> expectedProperties = GetExpectedPropertySignatures();
                    foreach (var propertyHandle in type.GetProperties())
                    {
                        PropertyDefinition property     = reader.GetPropertyDefinition(propertyHandle);
                        string             propertyName = reader.GetString(property.Name);
                        string             expected;
                        Assert.True(expectedProperties.TryGetValue(propertyName, out expected), "Unexpected property: " + propertyName);
                        MethodSignature <string> signature = property.DecodeSignature(provider, genericTypeContext);
                        Assert.True(signature.Header.Kind == SignatureKind.Property);
                        Assert.Equal(expected, provider.GetFunctionPointerType(signature));
                    }

                    Dictionary <string, string> expectedEvents = GetExpectedEventSignatures();
                    foreach (var eventHandle in type.GetEvents())
                    {
                        EventDefinition @event    = reader.GetEventDefinition(eventHandle);
                        string          eventName = reader.GetString(@event.Name);
                        string          expected;
                        Assert.True(expectedEvents.TryGetValue(eventName, out expected), "Unexpected event: " + eventName);

                        Assert.Equal(expected, provider.GetTypeFromHandle(reader, genericTypeContext, @event.Type));
                    }

                    Assert.Equal($"[{CollectionsAssemblyName}]System.Collections.Generic.List`1<!T>", provider.GetTypeFromHandle(reader, genericTypeContext, handle: type.BaseType));
                }
        }
Example #17
0
 public static PropertyDefinition GetPropertyDefinition(this PropertyDefinitionHandle handle, MetadataReader reader) => reader.GetPropertyDefinition(handle);
Example #18
0
 public static string ToString(this MetadataReader reader, PropertyDefinitionHandle x) => reader.ToString(reader.GetPropertyDefinition(x));
Example #19
0
        public override string GetEntityName(PEFile module, EntityHandle handle, bool fullName)
        {
            MetadataReader metadata = module.Metadata;

            switch (handle.Kind)
            {
            case HandleKind.TypeDefinition:
                return(ToCSharpString(metadata, (TypeDefinitionHandle)handle, fullName));

            case HandleKind.FieldDefinition:
                var fd            = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
                var declaringType = fd.GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(fd.Name));
                }
                return(metadata.GetString(fd.Name));

            case HandleKind.MethodDefinition:
                var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
                declaringType = md.GetDeclaringType();
                string methodName = metadata.GetString(md.Name);
                if (methodName == ".ctor" || methodName == ".cctor")
                {
                    var td = metadata.GetTypeDefinition(declaringType);
                    methodName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(td.Name));
                }
                else
                {
                    var genericParams = md.GetGenericParameters();
                    if (genericParams.Count > 0)
                    {
                        methodName += "<";
                        int i = 0;
                        foreach (var h in genericParams)
                        {
                            if (i > 0)
                            {
                                methodName += ",";
                            }
                            var gp = metadata.GetGenericParameter(h);
                            methodName += metadata.GetString(gp.Name);
                        }
                        methodName += ">";
                    }
                }
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + methodName);
                }
                return(methodName);

            case HandleKind.EventDefinition:
                var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(ed.Name));
                }
                return(metadata.GetString(ed.Name));

            case HandleKind.PropertyDefinition:
                var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(pd.Name));
                }
                return(metadata.GetString(pd.Name));

            default:
                return(null);
            }
        }
Example #20
0
 public static StringHandle[] GetPropertyDefNames(this MetadataReader reader)
 {
     return(reader.PropertyDefinitions.Select(handle => reader.GetPropertyDefinition(handle).Name).ToArray());
 }
Example #21
0
        /// <summary>
        /// PropertyMap Table Columns:
        ///     Parent (RID to TypeDef)
        ///     PropertyList (RID to EventTable)
        /// ===========================================
        /// Property Table Columns:
        ///     Name (offset to #String)
        ///     PropFlags (2 byte unsigned)
        ///     Type (offset to #blob - Signature)
        /// </summary>
        private void ValidateProperty(MetadataReader reader, uint rowId, uint startIndex, uint count, bool isVBMod = false)
        {
            if (0 == count)
            {
                return;
            }

            // ModuleCS01
            var expNames = new string[]
            {
                "AppProp", "P01", "Item", "P01", "Item",
                "CS1IGoo<System.Linq.Expressions.Expression,System.Object>.P01",
                "CS1IGoo<System.Linq.Expressions.Expression,System.Object>.Item",
            };
            var expSigs = new byte[][]
            {
                new byte[] { 0x28, 00, 0x15, 0x12, 0x21, 0x02, 0x12, 0x19, 0x1c }, new byte[] { 0x28, 00, 0x13, 00 },
                new byte[] { 0x28, 01, 0x1c, 0x13, 00 }, new byte[] { 0x28, 0x00, 0x13, 00 }, new byte[] { 0x28, 0x01, 0x1c, 0x13, 00 },
                new byte[] { 0x28, 00, 0x12, 0x19 }, new byte[] { 0x28, 01, 0x1c, 0x12, 0x19 }
            };

            // ModuleVB01
            // Prop: 0:0000, 1:string#13c, 2:blob#70 | 0:0000, 1:string#14d, 2:blob#75
            var modNames = new string[]
            {
                "ModVBDefaultProp", "ModVBProp",
            };
            var modSigs = new byte[][]
            {
                new byte[] { 0x28, 01, 0x0e, 0x08 }, new byte[] { 0x28, 00, 0x11, 0x09 },
            };

            // Validity Rules
            uint zeroBased = startIndex - 1;
            uint delta = count;

            // Last one
            if (0xF0000000 == count)
            {
                delta = (uint)reader.PropertyTable.NumberOfRows - zeroBased;
                if (0 == delta)
                {
                    return;
                }
            }

            Assert.InRange((uint)reader.PropertyTable.NumberOfRows, zeroBased + count, uint.MaxValue);
            for (uint i = zeroBased; i < zeroBased + count; i++)
            {
                var handle = PropertyDefinitionHandle.FromRowId((int)i + 1);
                var row = reader.GetPropertyDefinition(handle);

                // Name
                if (isVBMod)
                {
                    Assert.Equal(modNames[i], reader.GetString(row.Name));
                }
                else
                {
                    Assert.Equal(expNames[i], reader.GetString(row.Name));
                }

                Assert.Equal(0, (ushort)row.Attributes);

                var sig = reader.GetBlobBytes(row.Signature);
                Assert.Equal(40, sig[0]);
                byte[] exp;
                if (isVBMod)
                {
                    exp = modSigs[i];
                }
                else
                {
                    exp = expSigs[i];
                }

                for (int j = 0; j < exp.Length; j++)
                {
                    Assert.Equal(exp[j], sig[j]);
                }
            } // for
        }
Example #22
0
            protected override TypeAnnotations CreateValueFromKey(TypeDesc key)
            {
                // We scan the entire type at this point; the reason for doing that is properties.
                //
                // We allow annotating properties, but those annotations need to flow onto individual get/set methods
                // and backing fields. Without scanning all properties, we can't answer questions about fields/methods.
                // And if we're going over all properties, we might as well go over everything else to keep things simple.

                Debug.Assert(key.IsTypeDefinition);
                if (key is not EcmaType ecmaType)
                {
                    return(new TypeAnnotations(key, DynamicallyAccessedMemberTypes.None, null, null, null));
                }

                MetadataReader reader = ecmaType.MetadataReader;

                // class, interface, struct can have annotations
                TypeDefinition typeDef = reader.GetTypeDefinition(ecmaType.Handle);
                DynamicallyAccessedMemberTypes typeAnnotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, typeDef.GetCustomAttributes());

                try
                {
                    // Also inherit annotation from bases
                    TypeDesc baseType = key.BaseType;
                    while (baseType != null)
                    {
                        TypeDefinition baseTypeDef = reader.GetTypeDefinition(((EcmaType)baseType.GetTypeDefinition()).Handle);
                        typeAnnotation |= GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, baseTypeDef.GetCustomAttributes());
                        baseType        = baseType.BaseType;
                    }

                    // And inherit them from interfaces
                    foreach (DefType runtimeInterface in key.RuntimeInterfaces)
                    {
                        TypeDefinition interfaceTypeDef = reader.GetTypeDefinition(((EcmaType)runtimeInterface.GetTypeDefinition()).Handle);
                        typeAnnotation |= GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, interfaceTypeDef.GetCustomAttributes());
                    }
                }
                catch (TypeSystemException)
                {
                    // If the class hierarchy is not walkable, just stop collecting the annotations.
                }

                var annotatedFields = new ArrayBuilder <FieldAnnotation>();

                // First go over all fields with an explicit annotation
                foreach (EcmaField field in ecmaType.GetFields())
                {
                    FieldDefinition fieldDef = reader.GetFieldDefinition(field.Handle);
                    DynamicallyAccessedMemberTypes annotation =
                        GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, fieldDef.GetCustomAttributes());
                    if (annotation == DynamicallyAccessedMemberTypes.None)
                    {
                        continue;
                    }

                    if (!IsTypeInterestingForDataflow(field.FieldType))
                    {
                        // Already know that there's a non-empty annotation on a field which is not System.Type/String and we're about to ignore it
                        _logger.LogWarning(field, DiagnosticId.DynamicallyAccessedMembersOnFieldCanOnlyApplyToTypesOrStrings, field.GetDisplayName());
                        continue;
                    }

                    annotatedFields.Add(new FieldAnnotation(field, annotation));
                }

                var annotatedMethods = new ArrayBuilder <MethodAnnotations>();

                // Next go over all methods with an explicit annotation
                foreach (EcmaMethod method in ecmaType.GetMethods())
                {
                    DynamicallyAccessedMemberTypes[]? paramAnnotations = null;

                    // We convert indices from metadata space to IL space here.
                    // IL space assigns index 0 to the `this` parameter on instance methods.

                    DynamicallyAccessedMemberTypes methodMemberTypes =
                        GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, reader.GetMethodDefinition(method.Handle).GetCustomAttributes());

                    MethodSignature signature;
                    try
                    {
                        signature = method.Signature;
                    }
                    catch (TypeSystemException)
                    {
                        // If we cannot resolve things in the signature, just move along.
                        continue;
                    }

                    int offset;
                    if (!signature.IsStatic)
                    {
                        offset = 1;
                    }
                    else
                    {
                        offset = 0;
                    }

                    // If there's an annotation on the method itself and it's one of the special types (System.Type for example)
                    // treat that annotation as annotating the "this" parameter.
                    if (methodMemberTypes != DynamicallyAccessedMemberTypes.None)
                    {
                        if (IsTypeInterestingForDataflow(method.OwningType) && !signature.IsStatic)
                        {
                            paramAnnotations    = new DynamicallyAccessedMemberTypes[signature.Length + offset];
                            paramAnnotations[0] = methodMemberTypes;
                        }
                        else
                        {
                            _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersIsNotAllowedOnMethods);
                        }
                    }

                    MethodDefinition          methodDef        = reader.GetMethodDefinition(method.Handle);
                    ParameterHandleCollection parameterHandles = methodDef.GetParameters();

                    DynamicallyAccessedMemberTypes returnAnnotation = DynamicallyAccessedMemberTypes.None;

                    foreach (ParameterHandle parameterHandle in parameterHandles)
                    {
                        Parameter parameter = reader.GetParameter(parameterHandle);

                        if (parameter.SequenceNumber == 0)
                        {
                            // this is the return parameter
                            returnAnnotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, parameter.GetCustomAttributes());
                            if (returnAnnotation != DynamicallyAccessedMemberTypes.None && !IsTypeInterestingForDataflow(signature.ReturnType))
                            {
                                _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings, method.GetDisplayName());
                            }
                        }
                        else
                        {
                            DynamicallyAccessedMemberTypes pa = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, parameter.GetCustomAttributes());
                            if (pa == DynamicallyAccessedMemberTypes.None)
                            {
                                continue;
                            }

                            if (!IsTypeInterestingForDataflow(signature[parameter.SequenceNumber - 1]))
                            {
                                _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersOnMethodParameterCanOnlyApplyToTypesOrStrings, DiagnosticUtilities.GetParameterNameForErrorMessage(method, parameter.SequenceNumber - 1), method.GetDisplayName());
                                continue;
                            }

                            if (paramAnnotations == null)
                            {
                                paramAnnotations = new DynamicallyAccessedMemberTypes[signature.Length + offset];
                            }
                            paramAnnotations[parameter.SequenceNumber - 1 + offset] = pa;
                        }
                    }

                    DynamicallyAccessedMemberTypes[]? genericParameterAnnotations = null;
                    foreach (EcmaGenericParameter genericParameter in method.Instantiation)
                    {
                        GenericParameter genericParameterDef = reader.GetGenericParameter(genericParameter.Handle);
                        var annotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, genericParameterDef.GetCustomAttributes());
                        if (annotation != DynamicallyAccessedMemberTypes.None)
                        {
                            if (genericParameterAnnotations == null)
                            {
                                genericParameterAnnotations = new DynamicallyAccessedMemberTypes[method.Instantiation.Length];
                            }
                            genericParameterAnnotations[genericParameter.Index] = annotation;
                        }
                    }

                    if (returnAnnotation != DynamicallyAccessedMemberTypes.None || paramAnnotations != null || genericParameterAnnotations != null)
                    {
                        annotatedMethods.Add(new MethodAnnotations(method, paramAnnotations, returnAnnotation, genericParameterAnnotations));
                    }
                }

                // Next up are properties. Annotations on properties are kind of meta because we need to
                // map them to annotations on methods/fields. They're syntactic sugar - what they do is expressible
                // by placing attribute on the accessor/backing field. For complex properties, that's what people
                // will need to do anyway. Like so:
                //
                // [field: Attribute]
                // Type MyProperty
                // {
                //     [return: Attribute]
                //     get;
                //     [value: Attribute]
                //     set;
                //  }

                foreach (PropertyDefinitionHandle propertyHandle in reader.GetTypeDefinition(ecmaType.Handle).GetProperties())
                {
                    DynamicallyAccessedMemberTypes annotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(
                        reader, reader.GetPropertyDefinition(propertyHandle).GetCustomAttributes());
                    if (annotation == DynamicallyAccessedMemberTypes.None)
                    {
                        continue;
                    }

                    PropertyPseudoDesc property = new PropertyPseudoDesc(ecmaType, propertyHandle);

                    if (!IsTypeInterestingForDataflow(property.Signature.ReturnType))
                    {
                        _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersOnPropertyCanOnlyApplyToTypesOrStrings, property.GetDisplayName());
                        continue;
                    }

                    FieldDesc?backingFieldFromSetter = null;

                    // Propagate the annotation to the setter method
                    MethodDesc setMethod = property.SetMethod;
                    if (setMethod != null)
                    {
                        // Abstract property backing field propagation doesn't make sense, and any derived property will be validated
                        // to have the exact same annotations on getter/setter, and thus if it has a detectable backing field that will be validated as well.
                        MethodIL methodBody = _ilProvider.GetMethodIL(setMethod);
                        if (methodBody != null)
                        {
                            // Look for the compiler generated backing field. If it doesn't work out simply move on. In such case we would still
                            // propagate the annotation to the setter/getter and later on when analyzing the setter/getter we will warn
                            // that the field (which ever it is) must be annotated as well.
                            ScanMethodBodyForFieldAccess(methodBody, write: true, out backingFieldFromSetter);
                        }

                        if (annotatedMethods.Any(a => a.Method == setMethod))
                        {
                            _logger.LogWarning(setMethod, DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor, property.GetDisplayName(), setMethod.GetDisplayName());
                        }
                        else
                        {
                            int offset = setMethod.Signature.IsStatic ? 0 : 1;
                            if (setMethod.Signature.Length > 0)
                            {
                                DynamicallyAccessedMemberTypes[] paramAnnotations = new DynamicallyAccessedMemberTypes[setMethod.Signature.Length + offset];
                                paramAnnotations[paramAnnotations.Length - 1] = annotation;
                                annotatedMethods.Add(new MethodAnnotations(setMethod, paramAnnotations, DynamicallyAccessedMemberTypes.None, null));
                            }
                        }
                    }

                    FieldDesc?backingFieldFromGetter = null;

                    // Propagate the annotation to the getter method
                    MethodDesc getMethod = property.GetMethod;
                    if (getMethod != null)
                    {
                        // Abstract property backing field propagation doesn't make sense, and any derived property will be validated
                        // to have the exact same annotations on getter/setter, and thus if it has a detectable backing field that will be validated as well.
                        MethodIL methodBody = _ilProvider.GetMethodIL(getMethod);
                        if (methodBody != null)
                        {
                            // Look for the compiler generated backing field. If it doesn't work out simply move on. In such case we would still
                            // propagate the annotation to the setter/getter and later on when analyzing the setter/getter we will warn
                            // that the field (which ever it is) must be annotated as well.
                            ScanMethodBodyForFieldAccess(methodBody, write: false, out backingFieldFromGetter);
                        }

                        if (annotatedMethods.Any(a => a.Method == getMethod))
                        {
                            _logger.LogWarning(getMethod, DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor, property.GetDisplayName(), getMethod.GetDisplayName());
                        }
                        else
                        {
                            annotatedMethods.Add(new MethodAnnotations(getMethod, null, annotation, null));
                        }
                    }

                    FieldDesc?backingField;
                    if (backingFieldFromGetter != null && backingFieldFromSetter != null &&
                        backingFieldFromGetter != backingFieldFromSetter)
                    {
                        _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName());
                        backingField = null;
                    }
                    else
                    {
                        backingField = backingFieldFromGetter ?? backingFieldFromSetter;
                    }

                    if (backingField != null)
                    {
                        if (annotatedFields.Any(a => a.Field == backingField))
                        {
                            _logger.LogWarning(backingField, DiagnosticId.DynamicallyAccessedMembersOnPropertyConflictsWithBackingField, property.GetDisplayName(), backingField.GetDisplayName());
                        }
                        else
                        {
                            annotatedFields.Add(new FieldAnnotation(backingField, annotation));
                        }
                    }
                }

                DynamicallyAccessedMemberTypes[]? typeGenericParameterAnnotations = null;
                foreach (EcmaGenericParameter genericParameter in ecmaType.Instantiation)
                {
                    GenericParameter genericParameterDef = reader.GetGenericParameter(genericParameter.Handle);

                    var annotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, genericParameterDef.GetCustomAttributes());
                    if (annotation != DynamicallyAccessedMemberTypes.None)
                    {
                        if (typeGenericParameterAnnotations == null)
                        {
                            typeGenericParameterAnnotations = new DynamicallyAccessedMemberTypes[ecmaType.Instantiation.Length];
                        }
                        typeGenericParameterAnnotations[genericParameter.Index] = annotation;
                    }
                }

                return(new TypeAnnotations(ecmaType, typeAnnotation, annotatedMethods.ToArray(), annotatedFields.ToArray(), typeGenericParameterAnnotations));
            }