public Data(ImmutableArray <ModuleMetadata> modules, PEAssembly assembly) { Debug.Assert(!modules.IsDefaultOrEmpty && assembly != null); this.Modules = modules; this.Assembly = assembly; }
protected abstract AssemblyData CreateAssemblyDataForFile( PEAssembly assembly, WeakList <IAssemblySymbol> cachedSymbols, DocumentationProvider documentationProvider, string sourceAssemblySimpleName, MetadataImportOptions importOptions, bool embedInteropTypes);
public Data(ImmutableArray<ModuleMetadata> modules, PEAssembly assembly) { Debug.Assert(!modules.IsDefaultOrEmpty && assembly != null); this.Modules = modules; this.Assembly = assembly; }
/// <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); } }
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(); } }
/// <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)); }
private AssemblyMetadata(ImmutableArray <ModuleMetadata> modules) { this.Modules = modules; this.Assembly = new PEAssembly(this, modules.SelectAsArray(m => m.Module)); }
private AssemblyMetadata(ModuleMetadata module) { this.Modules = ImmutableArray.Create(module); this.Assembly = new PEAssembly(this, ImmutableArray.Create(module.Module)); }
private AssemblyMetadata(AssemblyMetadata metadata) { this.Assembly = metadata.Assembly; this.CachedSymbols = metadata.CachedSymbols; this.Modules = metadata.Modules.SelectAsArray(module => module.Copy()); }
/// <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()); }
/// <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)); }
internal static bool IsPchpCor(PEAssembly ass) => ass.Identity.Name == "Peachpie.Runtime";
/// <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; }
internal AssemblyMetadata(ImmutableArray<ModuleMetadata> modules) { this.Modules = modules; this.Assembly = new PEAssembly(this, modules.SelectAsArray(m => m.Module)); }