Example #1
0
        public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
        {
            var typeDefHandle = PEFile.GetTypeDefinition(topLevelTypeName);

            if (typeDefHandle.IsNil)
            {
                var forwarderHandle = PEFile.GetTypeForwarder(topLevelTypeName);
                if (!forwarderHandle.IsNil)
                {
                    var forwarder = metadata.GetExportedType(forwarderHandle);
                    return(ResolveForwardedType(forwarder).GetDefinition());
                }
            }
            return(GetDefinition(typeDefHandle));
        }
Example #2
0
        private Object ResolveExportedType(ExportedTypeHandle handle)
        {
            ExportedType exportedType = _metadataReader.GetExportedType(handle);

            var implementation = GetObject(exportedType.Implementation, NotFoundBehavior.ReturnResolutionFailure);

            if (implementation is ModuleDesc)
            {
                var    module    = (ModuleDesc)implementation;
                string nameSpace = _metadataReader.GetString(exportedType.Namespace);
                string name      = _metadataReader.GetString(exportedType.Name);
                return(module.GetType(nameSpace, name, NotFoundBehavior.ReturnResolutionFailure));
            }
            else
            if (implementation is MetadataType)
            {
                var    type       = (MetadataType)implementation;
                string name       = _metadataReader.GetString(exportedType.Name);
                var    nestedType = type.GetNestedType(name);
                if (nestedType == null)
                {
                    return(ResolutionFailure.GetTypeLoadResolutionFailure(name, this));
                }
                return(nestedType);
            }
            else if (implementation is ResolutionFailure)
            {
                return(implementation);
            }
            else
            {
                ThrowHelper.ThrowBadImageFormatException();
                return(null);
            }
        }
        public static AssemblyReference GetAssemblyReferenceForExportedType(MetadataReader metaReader, ExportedType exportedType)
        {
            if (exportedType.Implementation.Kind == HandleKind.AssemblyReference)
            {
                return(metaReader.GetAssemblyReference((AssemblyReferenceHandle)exportedType.Implementation));
            }
            else if (exportedType.Implementation.Kind == HandleKind.ExportedType)
            {
                // this means we have an exported nested type.

                /*
                 * .class extern forwarder System.TimeZoneInfo
                 * {
                 *  .assembly extern mscorlib
                 * }
                 * .class extern AdjustmentRule
                 * {
                 *  .class extern System.TimeZoneInfo
                 * }
                 */
                return(GetAssemblyReferenceForExportedType(metaReader, metaReader.GetExportedType(((ExportedTypeHandle)exportedType.Implementation))));
            }

            return(default(AssemblyReference));
        }
Example #4
0
        private static IEnumerable <string> GetPublicVisibleTypes(string assembly, bool includeTypeForwards = false)
        {
            using (var peReader = new PEReader(new FileStream(assembly, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read)))
            {
                if (peReader.HasMetadata)
                {
                    MetadataReader reader = peReader.GetMetadataReader();

                    // Enumerating typeDefinatons
                    foreach (var typeDefinationHandle in reader.TypeDefinitions)
                    {
                        TypeDefinition typeDefination = reader.GetTypeDefinition(typeDefinationHandle);

                        // Ignoring Nested types
                        if (!typeDefination.IsNested && IsPublic(typeDefination))
                        {
                            yield return(GetTypeName(typeDefination.Namespace, typeDefination.Name, reader));
                        }
                    }

                    if (includeTypeForwards)
                    {
                        // Enumerating typeforwards
                        foreach (var exportedTypeHandle in reader.ExportedTypes)
                        {
                            ExportedType exportedType = reader.GetExportedType(exportedTypeHandle);
                            if (exportedType.IsForwarder)
                            {
                                yield return(GetTypeName(exportedType.Namespace, exportedType.Name, reader));
                            }
                        }
                    }
                }
            }
        }
Example #5
0
        public IReadOnlyList <string> GetExportedTypeNames()
        {
            // Force load System.Design into the appdomain
            DesignSurface designSurface = new();
            IDesigner     designer      = designSurface.CreateDesigner(new Control(), true);

            Assert.NotNull(designer);

            Assembly systemDesign = AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "System.Design");

            using var fs       = new FileStream(systemDesign.Location, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            using var peReader = new PEReader(fs);

            MetadataReader metadataReader = peReader.GetMetadataReader();
            List <string>  typeNames      = new();

            foreach (ExportedTypeHandle typeHandle in metadataReader.ExportedTypes)
            {
                ExportedType type = metadataReader.GetExportedType(typeHandle);

                string ns   = metadataReader.GetString(type.Namespace);
                string name = metadataReader.GetString(type.Name);

                typeNames.Add($"{ns}.{name}");
            }

            return(typeNames);
        }
Example #6
0
        public sealed override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
        {
            var stringComparer = _metadataReader.StringComparer;

            // TODO: More efficient implementation?
            foreach (var typeDefinitionHandle in _metadataReader.TypeDefinitions)
            {
                var typeDefinition = _metadataReader.GetTypeDefinition(typeDefinitionHandle);
                if (stringComparer.Equals(typeDefinition.Name, name) &&
                    stringComparer.Equals(typeDefinition.Namespace, nameSpace))
                {
                    return((MetadataType)GetType((EntityHandle)typeDefinitionHandle));
                }
            }

            foreach (var exportedTypeHandle in _metadataReader.ExportedTypes)
            {
                var exportedType = _metadataReader.GetExportedType(exportedTypeHandle);
                if (stringComparer.Equals(exportedType.Name, name) &&
                    stringComparer.Equals(exportedType.Namespace, nameSpace))
                {
                    if (exportedType.IsForwarder)
                    {
                        Object implementation = GetObject(exportedType.Implementation);

                        if (implementation is ModuleDesc)
                        {
                            return(((ModuleDesc)(implementation)).GetType(nameSpace, name));
                        }

                        // TODO
                        throw new NotImplementedException();
                    }
                    // TODO:
                    throw new NotImplementedException();
                }
            }

            if (throwIfNotFound)
            {
                throw new TypeSystemException.TypeLoadException(nameSpace, name, this);
            }

            return(null);
        }
Example #7
0
        internal static IEnumerable <string> GetExportedTypesFullNames(MetadataReader metadataReader)
        {
            foreach (var typeDefHandle in metadataReader.ExportedTypes)
            {
                var typeDef = metadataReader.GetExportedType(typeDefHandle);
                var ns      = metadataReader.GetString(typeDef.Namespace);
                var name    = metadataReader.GetString(typeDef.Name);

                yield return((ns.Length == 0) ? name : (ns + "." + name));
            }
        }
Example #8
0
 private static string GetAssemblyName(MetadataReader reader, ExportedType type)
 {
     Debug.Assert(type.IsForwarder);
     if (type.Implementation.Kind == HandleKind.AssemblyReference)
     {
         return(reader.GetString(reader.GetAssemblyReference((AssemblyReferenceHandle)type.Implementation).Name));
     }
     if (type.Implementation.Kind == HandleKind.ExportedType)
     {
         return(GetAssemblyName(reader, reader.GetExportedType((ExportedTypeHandle)type.Implementation)));
     }
     throw new NotSupportedException(type.Implementation.Kind.ToString());
 }
Example #9
0
            private MetadataTypeReference GetTypeReferenceForForwardedType(NameSpec fullName)
            {
                if (assemblyReferencesByForwardedType == null)
                {
                    assemblyReferencesByForwardedType = new Dictionary <NameSpec, AssemblyReferenceHandle>();

                    foreach (var handle in reader.ExportedTypes)
                    {
                        var exportedType = reader.GetExportedType(handle);
                        if (!exportedType.IsForwarder)
                        {
                            continue;
                        }

                        if (exportedType.Implementation.Kind != HandleKind.AssemblyReference)
                        {
                            throw new NotImplementedException(exportedType.Implementation.Kind.ToString());
                        }

                        assemblyReferencesByForwardedType.Add(
                            new NameSpec(
                                reader.GetString(exportedType.Namespace),
                                reader.GetString(exportedType.Name),
                                nestedNames: null),
                            (AssemblyReferenceHandle)exportedType.Implementation);
                    }
                }

                if (assemblyReferencesByForwardedType.TryGetValue(new NameSpec(fullName.Namespace, fullName.TopLevelName, null), out var assemblyReferenceHandle))
                {
                    var current = (MetadataTypeReference) new TopLevelTypeReference(
                        reader
                        .GetAssemblyReference(assemblyReferenceHandle)
                        .GetAssemblyName(reader),
                        fullName.Namespace,
                        fullName.TopLevelName);

                    if (fullName.NestedNames != null)
                    {
                        foreach (var nestedName in fullName.NestedNames)
                        {
                            current = new NestedTypeReference(current, nestedName);
                        }
                    }

                    return(current);
                }

                return(null);
            }
        public static string GetTypeName(MetadataReader metaReader, ExportedType expTp)
        {
            string name = metaReader.GetString(expTp.Name);
            string ns   = metaReader.GetString(expTp.Namespace);
            string id   = string.IsNullOrEmpty(ns) ? name : $"{ns}.{name}";

            if (expTp.Implementation.Kind == HandleKind.ExportedType)
            {
                // we need to get the type of the parent as well.
                return(GetTypeName(metaReader, metaReader.GetExportedType(((ExportedTypeHandle)expTp.Implementation))) + "." + id);
            }

            return(id);
        }
Example #11
0
        bool ModuleForwardsScopeType(MetadataReader metadata, string typeScopeName, string typeScopeNamespace)
        {
            bool hasForward = false;

            foreach (var h in metadata.ExportedTypes)
            {
                var exportedType = metadata.GetExportedType(h);
                if (exportedType.IsForwarder && metadata.StringComparer.Equals(exportedType.Name, typeScopeName) && metadata.StringComparer.Equals(exportedType.Namespace, typeScopeNamespace))
                {
                    hasForward = true;
                    break;
                }
            }
            return(hasForward);
        }
Example #12
0
        public static FullTypeName GetFullTypeName(this ExportedType type, MetadataReader metadata)
        {
            string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(type.Name), out int typeParameterCount);

            if (type.Implementation.Kind == HandleKind.ExportedType)
            {
                var outerType = metadata.GetExportedType((ExportedTypeHandle)type.Implementation);
                return(outerType.GetFullTypeName(metadata).NestedType(name, typeParameterCount));
            }
            else
            {
                string ns = type.Namespace.IsNil ? "" : metadata.GetString(type.Namespace);
                return(new TopLevelTypeName(ns, name, typeParameterCount));
            }
        }
Example #13
0
        /// <summary>
        /// Get the full name of an ExportedType, including namespace
        /// </summary>
        private static string GetExportedTypeFullName(MetadataReader mdReader, ExportedTypeHandle handle)
        {
            string typeNamespace = "";
            string typeStr       = "";

            try
            {
                ExportedType exportedType = mdReader.GetExportedType(handle);
                typeStr       = "." + mdReader.GetString(exportedType.Name) + typeStr;
                typeNamespace = mdReader.GetString(exportedType.Namespace);
            }
            catch (BadImageFormatException)
            {
                return(null);
            }
            return(typeNamespace + typeStr);
        }
Example #14
0
 private static string GetFullName(MetadataReader reader, ExportedType type)
 {
     Debug.Assert(type.IsForwarder);
     if (type.Implementation.Kind == HandleKind.AssemblyReference)
     {
         var name     = reader.GetString(type.Name);
         var ns       = type.Namespace.IsNil ? null : reader.GetString(type.Namespace);
         var fullName = string.IsNullOrEmpty(ns) ? name : ns + "." + name;
         return(fullName);
     }
     if (type.Implementation.Kind == HandleKind.ExportedType)
     {
         var name = reader.GetString(type.Name);
         Debug.Assert(type.Namespace.IsNil);
         return(GetFullName(reader, reader.GetExportedType((ExportedTypeHandle)type.Implementation)) + "." + name);
     }
     throw new NotSupportedException(type.Implementation.Kind.ToString());
 }
Example #15
0
        public string GetTypeForwards()
        {
            // Don't generate type forwards for netstandard
            if (this.ShortTfm.StartsWith("netstandard"))
            {
                return("");
            }
            string result          = "";
            string typeForwardDecl = "[assembly: TypeForwardedTo(typeof({0}))]\n";

            using (var fileStream = new FileStream(this.DllPath, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read))
            {
                try
                {
                    using (PEReader pereader = new PEReader(fileStream, PEStreamOptions.LeaveOpen))
                    {
                        if (pereader.HasMetadata)
                        {
                            MetadataReader reader = pereader.GetMetadataReader();
                            if (reader.IsAssembly)
                            {
                                foreach (var exportedTypeHandle in reader.ExportedTypes)
                                {
                                    var exportedType = reader.GetExportedType(exportedTypeHandle);
                                    if (exportedType.IsForwarder)
                                    {
                                        var typeName = reader.GetString(exportedType.Name);
                                        var ns       = reader.GetString(exportedType.Namespace);
                                        typeName = typeName == "Void" ? "void" : ns + "." + ConvertGeneric(typeName);
                                        result  += string.Format(typeForwardDecl, typeName);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (BadImageFormatException)
                {
                    throw new ArgumentException($"Assembly {this.DllPath} has incorrect format", nameof(this.DllPath));
                }
            }
            return(result);
        }
Example #16
0
        public List <string> GetAdditionalUsings()
        {
            List <string> result    = new List <string>();
            string        usingDecl = "using {0};";

            using (var fileStream = new FileStream(this.DllPath, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read))
            {
                try
                {
                    using (PEReader pereader = new PEReader(fileStream, PEStreamOptions.LeaveOpen))
                    {
                        if (pereader.HasMetadata)
                        {
                            MetadataReader reader = pereader.GetMetadataReader();
                            if (reader.IsAssembly)
                            {
                                foreach (var exportedTypeHandle in reader.ExportedTypes)
                                {
                                    var exportedType = reader.GetExportedType(exportedTypeHandle);

                                    if (exportedType.IsForwarder)
                                    {
                                        result.Add(string.Format(usingDecl, reader.GetString(exportedType.Namespace)));
                                    }
                                }
                            }
                        }
                    }
                }
                catch (BadImageFormatException)
                {
                    throw new ArgumentException($"Assembly {this.DllPath} has incorrect format", nameof(this.DllPath));
                }
            }
            return(result);
        }
Example #17
0
        protected sealed override void IterateTypeForwards(TypeForwardHandler handler)
        {
            MetadataReader reader = Reader;

            foreach (ExportedTypeHandle exportedTypeHandle in reader.ExportedTypes)
            {
                ExportedType exportedType = reader.GetExportedType(exportedTypeHandle);
                if (!exportedType.IsForwarder)
                {
                    continue;
                }

                EntityHandle implementation = exportedType.Implementation;
                if (implementation.Kind != HandleKind.AssemblyReference) // This check also weeds out nested types. This is intentional.
                {
                    continue;
                }

                RoAssembly          redirectedAssembly = ((AssemblyReferenceHandle)implementation).ResolveToAssemblyOrExceptionAssembly(GetEcmaManifestModule());
                ReadOnlySpan <byte> ns   = exportedType.Namespace.AsReadOnlySpan(reader);
                ReadOnlySpan <byte> name = exportedType.Name.AsReadOnlySpan(reader);
                handler(redirectedAssembly, ns, name);
            }
        }
Example #18
0
        /// <summary>
        /// Helper method that will validate that a NamespaceDefinition (and all NamespaceDefinitions considered children
        /// of it) report correct values for their child namespaces, types, etc. All namespaces in the module are expected
        /// to be listed in the allNamespaces array. Additionally, the global namespace is expected to have type definitions
        /// for GlobalClassA, GlobalClassB, and Module. No type forwarder declarations are expected.
        /// 
        /// All namespaces that aren't the global NS are expected to have type definitions equal to the array
        /// @namespaceName.Split('.')
        /// So, ns1.Ns2.NS3 is expected to have type definitions
        /// {"ns1", "Ns2", "NS3"}.
        /// 
        /// definitionExceptions and forwarderExceptions may be used to override the default expectations. Pass in 
        /// namespace (key) and what is expected (list of strings) for each exception.
        /// </summary>
        private void ValidateNamespaceChildren(
            MetadataReader reader,
            NamespaceDefinitionHandle initHandle,
            string[] allNamespaces,
            IReadOnlyDictionary<string, IList<string>> definitionExceptions = null,
            IReadOnlyDictionary<string, IList<string>> forwarderExceptions = null)
        {
            // Don't want to have to deal with null.
            if (definitionExceptions == null)
            {
                definitionExceptions = new Dictionary<string, IList<string>>();
            }

            if (forwarderExceptions == null)
            {
                forwarderExceptions = new Dictionary<string, IList<string>>();
            }

            var rootNamespaceDefinition = reader.GetNamespaceDefinition(initHandle);
            string rootNamespaceName = reader.GetString(initHandle);

            // We need to be in the table of all namespaces...
            Assert.Contains(rootNamespaceName, allNamespaces);

            // Cool. Now check to make sure that .Name only returns the last bit of our namespace name.
            var expNamespaceNameSegment = rootNamespaceName.Split('.').Last();
            var rootNamespaceNameSegment = reader.GetString(rootNamespaceDefinition.Name);
            Assert.Equal(expNamespaceNameSegment, rootNamespaceNameSegment);

            bool isGlobalNamespace = rootNamespaceName.Length == 0;
            string[] expTypeDefinitions = null;
            // Special case: Global NS has GlobalClassA, GlobalClassB. Others just have autogenerated classes.
            if (definitionExceptions.ContainsKey(rootNamespaceName))
            {
                expTypeDefinitions = definitionExceptions[rootNamespaceName].ToArray();
            }
            else if (isGlobalNamespace)
            {
                expTypeDefinitions = new[] { "GlobalClassA", "GlobalClassB", "<Module>" };
            }
            else
            {
                expTypeDefinitions = rootNamespaceName.Split('.');
            }

            // Validating type definitions inside the namespace...
            int numberOfTypeDefinitions = 0;
            foreach (var definitionHandle in rootNamespaceDefinition.TypeDefinitions)
            {
                var definition = reader.GetTypeDefinition(definitionHandle);
                var definitionName = reader.GetString(definition.Name);
                var definitionFullNamespaceName = reader.GetString(definition.Namespace);
                Assert.Equal(rootNamespaceName, definitionFullNamespaceName);
                Assert.Contains(definitionName, expTypeDefinitions);
                numberOfTypeDefinitions += 1;
            }

            // Guarantee that there are no extra unexpected members...
            Assert.Equal(numberOfTypeDefinitions, expTypeDefinitions.Length);

            string[] expTypeForwarders = null;
            if (forwarderExceptions.ContainsKey(rootNamespaceName))
            {
                expTypeForwarders = forwarderExceptions[rootNamespaceName].ToArray();
            }
            else
            {
                expTypeForwarders = new string[] { };
            }

            int numberOfTypeForwarders = 0;
            foreach (var forwarderHandle in rootNamespaceDefinition.ExportedTypes)
            {
                var forwarder = reader.GetExportedType(forwarderHandle);
                Assert.True(reader.StringComparer.Equals(forwarder.Namespace, rootNamespaceName));
                var forwarderName = reader.GetString(forwarder.Name);
                Assert.Contains(forwarderName, expTypeForwarders);
                numberOfTypeForwarders += 1;
            }
            Assert.Equal(expTypeForwarders.Length, numberOfTypeForwarders);

            // Validate sub-namespaces

            // If the last index of '.' in a namespace name is == the current name's length, then
            // that ns is a direct child of the current one!
            IList<String> expChildren = null;

            // Special case: Global NS's children won't have .s in them.
            if (isGlobalNamespace)
            {
                expChildren = allNamespaces.Where(ns => !String.IsNullOrEmpty(ns) && !ns.Contains('.')).ToList();
            }
            else
            {
                expChildren = allNamespaces
                    .Where(ns => ns.StartsWith(rootNamespaceName) && ns.LastIndexOf('.') == rootNamespaceName.Length)
                    .ToList();
            }

            int numberOfSubNamespaces = 0;
            foreach (var subNamespaceHandle in rootNamespaceDefinition.NamespaceDefinitions)
            {
                Assert.False(subNamespaceHandle.IsNil);
                string subNamespaceFullName = reader.GetString(subNamespaceHandle);
                NamespaceDefinition subNamespace = reader.GetNamespaceDefinition(subNamespaceHandle);

                string subNamespaceName = subNamespaceFullName.Split('.').Last();
                Assert.Equal(subNamespaceName, reader.GetString(subNamespace.Name));
                Assert.True(reader.StringComparer.Equals(subNamespace.Name, subNamespaceName));
                Assert.True(reader.StringComparer.StartsWith(subNamespace.Name, subNamespaceName));
                Assert.True(reader.StringComparer.StartsWith(subNamespace.Name, subNamespaceName.Substring(0, subNamespaceName.Length - 1)));

                Assert.Equal(subNamespace.Parent, initHandle);
                Assert.Contains(subNamespaceFullName, expChildren);
                ValidateNamespaceChildren(reader, subNamespaceHandle, allNamespaces, definitionExceptions, forwarderExceptions);
                numberOfSubNamespaces += 1;
            }
            // Guarantee no extra unexpected namespaces...
            Assert.Equal(expChildren.Count, numberOfSubNamespaces);
        }
Example #19
0
        public sealed override MetadataType GetType(string nameSpace, string name, NotFoundBehavior notFoundBehavior)
        {
            var stringComparer = _metadataReader.StringComparer;

            // TODO: More efficient implementation?
            foreach (var typeDefinitionHandle in _metadataReader.TypeDefinitions)
            {
                var typeDefinition = _metadataReader.GetTypeDefinition(typeDefinitionHandle);
                if (stringComparer.Equals(typeDefinition.Name, name) &&
                    stringComparer.Equals(typeDefinition.Namespace, nameSpace))
                {
                    return((MetadataType)GetType((EntityHandle)typeDefinitionHandle));
                }
            }

            foreach (var exportedTypeHandle in _metadataReader.ExportedTypes)
            {
                var exportedType = _metadataReader.GetExportedType(exportedTypeHandle);
                if (stringComparer.Equals(exportedType.Name, name) &&
                    stringComparer.Equals(exportedType.Namespace, nameSpace))
                {
                    if (exportedType.IsForwarder)
                    {
                        Object implementation = GetObject(exportedType.Implementation, notFoundBehavior);

                        if (implementation == null)
                        {
                            return(null);
                        }

                        if (implementation is ModuleDesc)
                        {
                            return(((ModuleDesc)(implementation)).GetType(nameSpace, name));
                        }
                        else if (implementation is ResolutionFailure failure)
                        {
                            ModuleDesc.GetTypeResolutionFailure = failure;
                            return(null);
                        }

                        // TODO
                        throw new NotImplementedException();
                    }
                    // TODO:
                    throw new NotImplementedException();
                }
            }

            if (notFoundBehavior != NotFoundBehavior.ReturnNull)
            {
                var failure = ResolutionFailure.GetTypeLoadResolutionFailure(nameSpace, name, this);
                if (notFoundBehavior == NotFoundBehavior.Throw)
                {
                    failure.Throw();
                }

                ModuleDesc.GetTypeResolutionFailure = failure;
                return(null);
            }

            return(null);
        }
Example #20
0
 public static ExportedType GetExportedType(this ExportedTypeHandle handle, MetadataReader reader) => reader.GetExportedType(handle);
Example #21
0
 public static string ToString(this MetadataReader reader, ExportedTypeHandle x) => reader.ToString(reader.GetExportedType(x));