示例#1
0
            public Data(ImmutableArray <ModuleMetadata> modules, PEAssembly assembly)
            {
                Debug.Assert(!modules.IsDefaultOrEmpty && assembly != null);

                this.Modules  = modules;
                this.Assembly = assembly;
            }
示例#2
0
 protected abstract AssemblyData CreateAssemblyDataForFile(
     PEAssembly assembly,
     WeakList <IAssemblySymbol> cachedSymbols,
     DocumentationProvider documentationProvider,
     string sourceAssemblySimpleName,
     MetadataImportOptions importOptions,
     bool embedInteropTypes);
示例#3
0
            public Data(ImmutableArray<ModuleMetadata> modules, PEAssembly assembly)
            {
                Debug.Assert(!modules.IsDefaultOrEmpty && assembly != null);

                this.Modules = modules;
                this.Assembly = assembly;
            }
示例#4
0
        /// <exception cref="BadImageFormatException">The PE image format is invalid.</exception>
        /// <exception cref="IOException">IO error while reading the metadata. See <see cref="Exception.InnerException"/> for details.</exception>
        /// <exception cref="ObjectDisposedException">The object has been disposed.</exception>
        private Data GetOrCreateData()
        {
            if (_lazyData == null)
            {
                ImmutableArray <ModuleMetadata>          modules       = _initialModules;
                ImmutableArray <ModuleMetadata> .Builder?moduleBuilder = null;

                bool createdModulesUsed = false;
                try
                {
                    if (_moduleFactoryOpt != null)
                    {
                        Debug.Assert(_initialModules.Length == 1);

                        var additionalModuleNames = _initialModules[0].GetModuleNames();
                        if (additionalModuleNames.Length > 0)
                        {
                            moduleBuilder = ImmutableArray.CreateBuilder <ModuleMetadata>(
                                1 + additionalModuleNames.Length
                                );
                            moduleBuilder.Add(_initialModules[0]);

                            foreach (string moduleName in additionalModuleNames)
                            {
                                moduleBuilder.Add(_moduleFactoryOpt(moduleName));
                            }

                            modules = moduleBuilder.ToImmutable();
                        }
                    }

                    var assembly = new PEAssembly(this, modules.SelectAsArray(m => m.Module));
                    var newData  = new Data(modules, assembly);

                    createdModulesUsed =
                        Interlocked.CompareExchange(ref _lazyData, newData, null) == null;
                }
                finally
                {
                    if (moduleBuilder != null && !createdModulesUsed)
                    {
                        // dispose unused modules created above:
                        for (int i = _initialModules.Length; i < moduleBuilder.Count; i++)
                        {
                            moduleBuilder[i].Dispose();
                        }
                    }
                }
            }

            if (_lazyData.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(AssemblyMetadata));
            }

            return(_lazyData);
        }
        private bool DetectPortableDependency(PortableExecutableReference peReference, ref string mscorlibPath, ref bool referencesPortableLibrary)
        {
            if (peReference == null)
            {
                return(false);
            }

            DiagnosticBag diagnostics = DiagnosticBag.GetInstance();
            Metadata      metadata    = GetMetadata(peReference, MessageProvider, NoLocation.Singleton, diagnostics);

            // ignore diagnostics, we will report diagnostics again when reading the metadata later:
            diagnostics.Free();

            if (metadata == null)
            {
                return(false);
            }

            var assemblyMetadata = (AssemblyMetadata)metadata;

            if (!assemblyMetadata.IsValidAssembly())
            {
                return(false);
            }

            PEAssembly assembly = assemblyMetadata.Assembly;

            if (IsSystemRuntime(assembly.Identity))
            {
                return(true);
            }

            if (IsMscorlib(assembly.Identity))
            {
                mscorlibPath = peReference.FullPath;
                return(false);
            }

            if (referencesPortableLibrary)
            {
                return(false);
            }

            referencesPortableLibrary |= HasSystemRuntime(assembly.AssemblyReferences);
            return(false);
        }
            private static AssemblyIdentity?TryGetIdentity(MetadataReference metadataReference)
            {
                var peReference = metadataReference as PortableExecutableReference;

                if (peReference == null || peReference.Properties.Kind != MetadataImageKind.Assembly)
                {
                    return(null);
                }

                try
                {
                    PEAssembly assembly = ((AssemblyMetadata)peReference.GetMetadataNoCopy()).GetAssembly() !;
                    return(assembly.Identity);
                }
                catch (Exception e) when(e is BadImageFormatException || e is IOException)
                {
                    // ignore, metadata reading errors are reported by the compiler for the existing references
                    return(null);
                }
            }
示例#7
0
        internal PEAssemblySymbol(PEAssembly assembly, DocumentationProvider documentationProvider, bool isLinked, MetadataImportOptions importOptions)
        {
            Debug.Assert(assembly != null);
            Debug.Assert(documentationProvider != null);

            _assembly = assembly;
            _documentationProvider = documentationProvider;

            var modules = new ModuleSymbol[assembly.Modules.Length];

            for (int i = 0; i < assembly.Modules.Length; i++)
            {
                modules[i] = new PEModuleSymbol(this, assembly.Modules[i], importOptions, i);
            }

            _modules = modules.AsImmutableOrNull();
            _isLinked = isLinked;

            if (IsPchpCor(assembly))
            {
                _specialAssembly = SpecialAssembly.PchpCorLibrary;

                // initialize CoreTypes
                this.PrimaryModule.GlobalNamespace.GetTypeMembers();
            }
            else if (assembly.Identity.Name == "System.Runtime")
            {
                _specialAssembly = SpecialAssembly.CorLibrary;
            }
            else if (assembly.AssemblyReferences.Length == 0 && assembly.DeclaresTheObjectClass)
            {
                _specialAssembly = SpecialAssembly.CorLibrary;
            }
            else
            {
                // extension assembly ?
                //var attrs = this.GetAttributes();
            }
        }
示例#8
0
        /// <summary>
        /// Resolves given metadata references to assemblies and modules.
        /// </summary>
        /// <param name="compilation">The compilation whose references are being resolved.</param>
        /// <param name="assemblyReferencesBySimpleName">
        /// Used to filter out assemblies that have the same strong or weak identity.
        /// Maps simple name to a list of identities. The highest version of each name is the first.
        /// </param>
        /// <param name="references">List where to store resolved references. References from #r directives will follow references passed to the compilation constructor.</param>
        /// <param name="boundReferenceDirectiveMap">Maps #r values to successfully resolved metadata references. Does not contain values that failed to resolve.</param>
        /// <param name="boundReferenceDirectives">Unique metadata references resolved from #r directives.</param>
        /// <param name="assemblies">List where to store information about resolved assemblies to.</param>
        /// <param name="modules">List where to store information about resolved modules to.</param>
        /// <param name="diagnostics">Diagnostic bag where to report resolution errors.</param>
        /// <returns>
        /// Maps index to <paramref name="references"/> to an index of a resolved assembly or module in <paramref name="assemblies"/> or <paramref name="modules"/>, respectively.
        ///</returns>
        protected ImmutableArray <ResolvedReference> ResolveMetadataReferences(
            TCompilation compilation,
            [Out] Dictionary <string, List <ReferencedAssemblyIdentity> > assemblyReferencesBySimpleName,
            out ImmutableArray <MetadataReference> references,
            out IDictionary <ValueTuple <string, string>, MetadataReference> boundReferenceDirectiveMap,
            out ImmutableArray <MetadataReference> boundReferenceDirectives,
            out ImmutableArray <AssemblyData> assemblies,
            out ImmutableArray <PEModule> modules,
            DiagnosticBag diagnostics)
        {
            // Locations of all #r directives in the order they are listed in the references list.
            ImmutableArray <Location> referenceDirectiveLocations;

            GetCompilationReferences(compilation, diagnostics, out references, out boundReferenceDirectiveMap, out referenceDirectiveLocations);

            // References originating from #r directives precede references supplied as arguments of the compilation.
            int referenceCount          = references.Length;
            int referenceDirectiveCount = (referenceDirectiveLocations != null ? referenceDirectiveLocations.Length : 0);

            var referenceMap = new ResolvedReference[referenceCount];

            // Maps references that were added to the reference set (i.e. not filtered out as duplicates) to a set of names that
            // can be used to alias these references. Duplicate assemblies contribute their aliases into this set.
            Dictionary <MetadataReference, MergedAliases> lazyAliasMap = null;

            // Used to filter out duplicate references that reference the same file (resolve to the same full normalized path).
            var boundReferences = new Dictionary <MetadataReference, MetadataReference>(MetadataReferenceEqualityComparer.Instance);

            ArrayBuilder <MetadataReference> uniqueDirectiveReferences = (referenceDirectiveLocations != null) ? ArrayBuilder <MetadataReference> .GetInstance() : null;

            var assembliesBuilder = ArrayBuilder <AssemblyData> .GetInstance();

            ArrayBuilder <PEModule> lazyModulesBuilder = null;

            bool supersedeLowerVersions = compilation.Options.ReferencesSupersedeLowerVersions;

            // When duplicate references with conflicting EmbedInteropTypes flag are encountered,
            // VB uses the flag from the last one, C# reports an error. We need to enumerate in reverse order
            // so that we find the one that matters first.
            for (int referenceIndex = referenceCount - 1; referenceIndex >= 0; referenceIndex--)
            {
                var boundReference = references[referenceIndex];
                if (boundReference == null)
                {
                    continue;
                }

                // add bound reference if it doesn't exist yet, merging aliases:
                MetadataReference existingReference;
                if (boundReferences.TryGetValue(boundReference, out existingReference))
                {
                    // merge properties of compilation-based references if the underlying compilations are the same
                    if ((object)boundReference != existingReference)
                    {
                        MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap);
                    }

                    continue;
                }

                boundReferences.Add(boundReference, boundReference);

                Location location;
                if (referenceIndex < referenceDirectiveCount)
                {
                    location = referenceDirectiveLocations[referenceIndex];
                    uniqueDirectiveReferences.Add(boundReference);
                }
                else
                {
                    location = Location.None;
                }

                // compilation reference

                var compilationReference = boundReference as CompilationReference;
                if (compilationReference != null)
                {
                    switch (compilationReference.Properties.Kind)
                    {
                    case MetadataImageKind.Assembly:
                        existingReference = TryAddAssembly(
                            compilationReference.Compilation.Assembly.Identity,
                            boundReference,
                            -assembliesBuilder.Count - 1,
                            diagnostics,
                            location,
                            assemblyReferencesBySimpleName,
                            supersedeLowerVersions);

                        if (existingReference != null)
                        {
                            MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap);
                            continue;
                        }

                        // Note, if SourceAssemblySymbol hasn't been created for
                        // compilationAssembly.Compilation yet, we want this to happen
                        // right now. Conveniently, this constructor will trigger creation of the
                        // SourceAssemblySymbol.
                        var asmData = CreateAssemblyDataForCompilation(compilationReference);
                        AddAssembly(asmData, referenceIndex, referenceMap, assembliesBuilder);
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(compilationReference.Properties.Kind);
                    }

                    continue;
                }

                // PE reference

                var      peReference = (PortableExecutableReference)boundReference;
                Metadata metadata    = GetMetadata(peReference, MessageProvider, location, diagnostics);
                Debug.Assert(metadata != null || diagnostics.HasAnyErrors());

                if (metadata != null)
                {
                    Debug.Assert(metadata != null);

                    switch (peReference.Properties.Kind)
                    {
                    case MetadataImageKind.Assembly:
                        var assemblyMetadata = (AssemblyMetadata)metadata;
                        WeakList <IAssemblySymbol> cachedSymbols = assemblyMetadata.CachedSymbols;

                        if (assemblyMetadata.IsValidAssembly())
                        {
                            PEAssembly assembly = assemblyMetadata.GetAssembly();
                            existingReference = TryAddAssembly(
                                assembly.Identity,
                                peReference,
                                -assembliesBuilder.Count - 1,
                                diagnostics,
                                location,
                                assemblyReferencesBySimpleName,
                                supersedeLowerVersions);

                            if (existingReference != null)
                            {
                                MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap);
                                continue;
                            }

                            var asmData = CreateAssemblyDataForFile(
                                assembly,
                                cachedSymbols,
                                peReference.DocumentationProvider,
                                SimpleAssemblyName,
                                compilation.Options.MetadataImportOptions,
                                peReference.Properties.EmbedInteropTypes);

                            AddAssembly(asmData, referenceIndex, referenceMap, assembliesBuilder);
                        }
                        else
                        {
                            diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotAssembly, location, peReference.Display));
                        }

                        // asmData keeps strong ref after this point
                        GC.KeepAlive(assemblyMetadata);
                        break;

                    case MetadataImageKind.Module:
                        var moduleMetadata = (ModuleMetadata)metadata;
                        if (moduleMetadata.Module.IsLinkedModule)
                        {
                            // We don't support netmodules since some checks in the compiler need information from the full PE image
                            // (Machine, Bit32Required, PE image hash).
                            if (!moduleMetadata.Module.IsEntireImageAvailable)
                            {
                                diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_LinkedNetmoduleMetadataMustProvideFullPEImage, location, peReference.Display));
                            }

                            AddModule(moduleMetadata.Module, referenceIndex, referenceMap, ref lazyModulesBuilder);
                        }
                        else
                        {
                            diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotModule, location, peReference.Display));
                        }
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(peReference.Properties.Kind);
                    }
                }
            }

            if (uniqueDirectiveReferences != null)
            {
                uniqueDirectiveReferences.ReverseContents();
                boundReferenceDirectives = uniqueDirectiveReferences.ToImmutableAndFree();
            }
            else
            {
                boundReferenceDirectives = ImmutableArray <MetadataReference> .Empty;
            }

            // We enumerated references in reverse order in the above code
            // and thus assemblies and modules in the builders are reversed.
            // Fix up all the indices and reverse the builder content now to get
            // the ordering matching the references.
            //
            // Also fills in aliases.

            for (int i = 0; i < referenceMap.Length; i++)
            {
                if (!referenceMap[i].IsSkipped)
                {
                    int count = (referenceMap[i].Kind == MetadataImageKind.Assembly) ? assembliesBuilder.Count : lazyModulesBuilder?.Count ?? 0;

                    int reversedIndex = count - 1 - referenceMap[i].Index;
                    referenceMap[i] = GetResolvedReferenceAndFreePropertyMapEntry(references[i], reversedIndex, referenceMap[i].Kind, lazyAliasMap);
                }
            }

            assembliesBuilder.ReverseContents();
            assemblies = assembliesBuilder.ToImmutableAndFree();

            if (lazyModulesBuilder == null)
            {
                modules = ImmutableArray <PEModule> .Empty;
            }
            else
            {
                lazyModulesBuilder.ReverseContents();
                modules = lazyModulesBuilder.ToImmutableAndFree();
            }

            return(ImmutableArray.CreateRange(referenceMap));
        }
示例#9
0
 private AssemblyMetadata(ImmutableArray <ModuleMetadata> modules)
 {
     this.Modules  = modules;
     this.Assembly = new PEAssembly(this, modules.SelectAsArray(m => m.Module));
 }
示例#10
0
 private AssemblyMetadata(ModuleMetadata module)
 {
     this.Modules  = ImmutableArray.Create(module);
     this.Assembly = new PEAssembly(this, ImmutableArray.Create(module.Module));
 }
示例#11
0
 private AssemblyMetadata(AssemblyMetadata metadata)
 {
     this.Assembly      = metadata.Assembly;
     this.CachedSymbols = metadata.CachedSymbols;
     this.Modules       = metadata.Modules.SelectAsArray(module => module.Copy());
 }
示例#12
0
 /// <summary>
 /// Determines if it is possible that <paramref name="assembly"/> gives internals
 /// access to assembly <paramref name="compilationName"/>. It does not make a conclusive
 /// determination of visibility because the compilation's strong name key is not supplied.
 /// </summary>
 static internal bool InternalsMayBeVisibleToAssemblyBeingCompiled(string compilationName, PEAssembly assembly)
 {
     return(!assembly.GetInternalsVisibleToPublicKeys(compilationName).IsEmpty());
 }
示例#13
0
        /// <summary>
        /// Used to validate metadata blobs emitted for MarshalAs.
        /// </summary>
        internal static void MarshalAsMetadataValidator(PEAssembly assembly, Func<string, PEAssembly, byte[]> getExpectedBlob, bool isField = true)
        {
            var metadataReader = assembly.GetMetadataReader();

            // no custom attributes should be emitted on parameters, fields or methods:
            foreach (var ca in metadataReader.CustomAttributes)
            {
                Assert.NotEqual("MarshalAsAttribute", GetAttributeName(metadataReader, ca));
            }

            int expectedMarshalCount = 0;

            if (isField)
            {
                // fields
                foreach (var fieldDef in metadataReader.FieldDefinitions)
                {
                    var field = metadataReader.GetFieldDefinition(fieldDef);
                    string fieldName = metadataReader.GetString(field.Name);

                    byte[] expectedBlob = getExpectedBlob(fieldName, assembly);
                    if (expectedBlob != null)
                    {
                        BlobHandle descriptor = metadataReader.GetFieldDefinition(fieldDef).GetMarshallingDescriptor();
                        Assert.False(descriptor.IsNil, "Expecting record in FieldMarshal table");

                        Assert.NotEqual(0, (int)(field.Attributes & FieldAttributes.HasFieldMarshal));
                        expectedMarshalCount++;

                        byte[] actualBlob = metadataReader.GetBlobBytes(descriptor);
                        AssertEx.Equal(expectedBlob, actualBlob);
                    }
                    else
                    {
                        Assert.Equal(0, (int)(field.Attributes & FieldAttributes.HasFieldMarshal));
                    }
                }
            }
            else
            {
                // parameters
                foreach (var methodHandle in metadataReader.MethodDefinitions)
                {
                    var methodDef = metadataReader.GetMethodDefinition(methodHandle);
                    string memberName = metadataReader.GetString(methodDef.Name);
                    foreach (var paramHandle in methodDef.GetParameters())
                    {
                        var paramRow = metadataReader.GetParameter(paramHandle);
                        string paramName = metadataReader.GetString(paramRow.Name);

                        byte[] expectedBlob = getExpectedBlob(memberName + ":" + paramName, assembly);
                        if (expectedBlob != null)
                        {
                            Assert.NotEqual(0, (int)(paramRow.Attributes & ParameterAttributes.HasFieldMarshal));
                            expectedMarshalCount++;

                            BlobHandle descriptor = metadataReader.GetParameter(paramHandle).GetMarshallingDescriptor();
                            Assert.False(descriptor.IsNil, "Expecting record in FieldMarshal table");

                            byte[] actualBlob = metadataReader.GetBlobBytes(descriptor);

                            AssertEx.Equal(expectedBlob, actualBlob);
                        }
                        else
                        {
                            Assert.Equal(0, (int)(paramRow.Attributes & ParameterAttributes.HasFieldMarshal));
                        }
                    }
                }
            }

            Assert.Equal(expectedMarshalCount, metadataReader.GetTableRowCount(TableIndex.FieldMarshal));
        }
示例#14
0
 internal static bool IsPchpCor(PEAssembly ass) => ass.Identity.Name == "Peachpie.Runtime";
示例#15
0
        /// <exception cref="BadImageFormatException">The PE image format is invalid.</exception>
        /// <exception cref="IOException">IO error while reading the metadata. See <see cref="Exception.InnerException"/> for details.</exception>
        /// <exception cref="ObjectDisposedException">The object has been disposed.</exception>
        private Data GetOrCreateData()
        {
            if (_lazyData == null)
            {
                ImmutableArray<ModuleMetadata> modules = _initialModules;
                ImmutableArray<ModuleMetadata>.Builder moduleBuilder = null;

                bool createdModulesUsed = false;
                try
                {
                    if (_moduleFactoryOpt != null)
                    {
                        Debug.Assert(_initialModules.Length == 1);

                        var additionalModuleNames = _initialModules[0].GetModuleNames();
                        if (additionalModuleNames.Length > 0)
                        {
                            moduleBuilder = ImmutableArray.CreateBuilder<ModuleMetadata>(1 + additionalModuleNames.Length);
                            moduleBuilder.Add(_initialModules[0]);

                            foreach (string moduleName in additionalModuleNames)
                            {
                                moduleBuilder.Add(_moduleFactoryOpt(moduleName));
                            }

                            modules = moduleBuilder.ToImmutable();
                        }
                    }

                    var assembly = new PEAssembly(this, modules.SelectAsArray(m => m.Module));
                    var newData = new Data(modules, assembly);

                    createdModulesUsed = Interlocked.CompareExchange(ref _lazyData, newData, null) == null;
                }
                finally
                {
                    if (moduleBuilder != null && !createdModulesUsed)
                    {
                        // dispose unused modules created above:
                        for (int i = _initialModules.Length; i < moduleBuilder.Count; i++)
                        {
                            moduleBuilder[i].Dispose();
                        }
                    }
                }
            }

            if (_lazyData.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(AssemblyMetadata));
            }

            return _lazyData;
        }
示例#16
0
 internal AssemblyMetadata(ImmutableArray<ModuleMetadata> modules)
 {
     this.Modules = modules;
     this.Assembly = new PEAssembly(this, modules.SelectAsArray(m => m.Module));
 }
示例#17
0
 private AssemblyMetadata(ModuleMetadata module)
 {
     this.Modules = ImmutableArray.Create(module);
     this.Assembly = new PEAssembly(this, ImmutableArray.Create(module.Module));
 }
示例#18
0
 private AssemblyMetadata(AssemblyMetadata metadata)
 {
     this.Assembly = metadata.Assembly;
     this.CachedSymbols = metadata.CachedSymbols;
     this.Modules = metadata.Modules.SelectAsArray(module => module.Copy());
 }