Beispiel #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));
        }
        /// <summary>
        /// Resolves the type reference within the context of the given PE file.
        /// </summary>
        /// <returns>Either TypeDefinitionHandle, if the type is defined in the module or ExportedTypeHandle,
        /// if the module contains a type forwarder. Returns a nil handle, if the type was not found.</returns>
        public EntityHandle ResolveInPEFile(PEFile module)
        {
            string[] parts = typeName.Split('.');
            for (int i = parts.Length - 1; i >= 0; i--)
            {
                string ns           = string.Join(".", parts, 0, i);
                string name         = parts[i];
                int    topLevelTPC  = (i == parts.Length - 1 ? typeParameterCount : 0);
                var    topLevelName = new TopLevelTypeName(ns, name, topLevelTPC);
                var    typeHandle   = module.GetTypeDefinition(topLevelName);

                for (int j = i + 1; j < parts.Length && !typeHandle.IsNil; j++)
                {
                    int    tpc        = (j == parts.Length - 1 ? typeParameterCount : 0);
                    var    typeDef    = module.Metadata.GetTypeDefinition(typeHandle);
                    string lookupName = parts[j] + (tpc > 0 ? "`" + tpc : "");
                    typeHandle = typeDef.GetNestedTypes().FirstOrDefault(n => IsEqualShortName(n, module.Metadata, lookupName));
                }

                if (!typeHandle.IsNil)
                {
                    return(typeHandle);
                }
                FullTypeName typeName = topLevelName;
                for (int j = i + 1; j < parts.Length; j++)
                {
                    int tpc = (j == parts.Length - 1 ? typeParameterCount : 0);
                    typeName = typeName.NestedType(parts[j], tpc);
                }

                var exportedType = module.GetTypeForwarder(typeName);
                if (!exportedType.IsNil)
                {
                    return(exportedType);
                }
            }

            return(default);
Beispiel #3
0
            public BamlDecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver)
            {
                if (mainModule == null)
                {
                    throw new ArgumentNullException(nameof(mainModule));
                }
                if (assemblyResolver == null)
                {
                    throw new ArgumentNullException(nameof(assemblyResolver));
                }
                // Load referenced assemblies and type-forwarder references.
                // This is necessary to make .NET Core/PCL binaries work better.
                var referencedAssemblies   = new List <PEFile>();
                var assemblyReferenceQueue = new Queue <(bool IsAssembly, PEFile MainModule, object Reference)>();
                var mainMetadata           = mainModule.Metadata;

                foreach (var h in mainMetadata.GetModuleReferences())
                {
                    var moduleRef  = mainMetadata.GetModuleReference(h);
                    var moduleName = mainMetadata.GetString(moduleRef.Name);
                    foreach (var fileHandle in mainMetadata.AssemblyFiles)
                    {
                        var file = mainMetadata.GetAssemblyFile(fileHandle);
                        if (mainMetadata.StringComparer.Equals(file.Name, moduleName) && file.ContainsMetadata)
                        {
                            assemblyReferenceQueue.Enqueue((false, mainModule, moduleName));
                            break;
                        }
                    }
                }
                foreach (var refs in mainModule.AssemblyReferences)
                {
                    assemblyReferenceQueue.Enqueue((true, mainModule, refs));
                }
                foreach (var bamlReference in defaultBamlReferences)
                {
                    assemblyReferenceQueue.Enqueue((true, mainModule, AssemblyNameReference.Parse(bamlReference)));
                }
                var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference)reference) =>
                                                  reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName :
                                                  "M:" + reference.Reference);
                var processedAssemblyReferences = new HashSet <(bool IsAssembly, PEFile Parent, object Reference)>(comparer);

                while (assemblyReferenceQueue.Count > 0)
                {
                    var asmRef = assemblyReferenceQueue.Dequeue();
                    if (!processedAssemblyReferences.Add(asmRef))
                    {
                        continue;
                    }
                    PEFile asm;
                    if (asmRef.IsAssembly)
                    {
                        asm = assemblyResolver.Resolve((IAssemblyReference)asmRef.Reference);
                    }
                    else
                    {
                        asm = assemblyResolver.ResolveModule(asmRef.MainModule, (string)asmRef.Reference);
                    }
                    if (asm != null)
                    {
                        referencedAssemblies.Add(asm);
                        var metadata = asm.Metadata;
                        foreach (var h in metadata.ExportedTypes)
                        {
                            var exportedType = metadata.GetExportedType(h);
                            switch (exportedType.Implementation.Kind)
                            {
                            case SRM.HandleKind.AssemblyReference:
                                assemblyReferenceQueue.Enqueue((true, asm, new AssemblyReference(asm, (SRM.AssemblyReferenceHandle)exportedType.Implementation)));
                                break;

                            case SRM.HandleKind.AssemblyFile:
                                var file = metadata.GetAssemblyFile((SRM.AssemblyFileHandle)exportedType.Implementation);
                                assemblyReferenceQueue.Enqueue((false, asm, metadata.GetString(file.Name)));
                                break;
                            }
                        }
                    }
                }
                var mainModuleWithOptions           = mainModule.WithOptions(TypeSystemOptions.Default);
                var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(TypeSystemOptions.Default));

                // Primitive types are necessary to avoid assertions in ILReader.
                // Fallback to MinimalCorlib to provide the primitive types.
                if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32))
                {
                    Init(mainModule.WithOptions(TypeSystemOptions.Default), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.Instance }));
                }
                else
                {
                    Init(mainModuleWithOptions, referencedAssembliesWithOptions);
                }
                this.MainModule = (MetadataModule)base.MainModule;

                bool HasType(KnownTypeCode code)
                {
                    TopLevelTypeName name = KnownTypeReference.Get(code).TypeName;

                    if (mainModule.GetTypeDefinition(name) != null)
                    {
                        return(true);
                    }
                    foreach (var file in referencedAssemblies)
                    {
                        if (file.GetTypeDefinition(name) != null)
                        {
                            return(true);
                        }
                    }
                    return(false);
                }
            }