internal Assembly GetOrLoad(ModuleData moduleData, bool reflectionOnly) { var cache = reflectionOnly ? _reflectionOnlyAssemblyCache : _assemblyCache; lock (s_guard) { Assembly assembly; if (cache.TryGetValue(moduleData.Mvid, out assembly)) { return assembly; } var loadedAssembly = RuntimeAssemblyManager.LoadAsAssembly(moduleData.SimpleName, moduleData.Image, reflectionOnly); // Validate the loaded assembly matches the value that we now have in the cache. if (!cache.TryGetValue(moduleData.Mvid, out assembly)) { throw new Exception("Explicit assembly load didn't update the proper cache"); } if (loadedAssembly != assembly) { throw new Exception("Cache entry doesn't match result of load"); } return assembly; } }
private void CreateAssemblyManager(IEnumerable<ModuleData> compilationDependencies, ModuleData mainModule) { var allModules = compilationDependencies; if (additionalDependencies != null) { allModules = allModules.Concat(additionalDependencies); } // We need to add the main module so that it gets checked against already loaded assembly names. // If an assembly is loaded directly via PEVerify(image) another assembly of the same full name // can't be loaded as a dependency (via Assembly.ReflectionOnlyLoad) in the same domain. if (mainModule != null) { allModules = allModules.Concat(new[] { mainModule }); } allModules = allModules.ToArray(); string conflict = DetectNameCollision(allModules); if (conflict != null) { Type appDomainProxyType = typeof(RuntimeAssemblyManager); Assembly thisAssembly = appDomainProxyType.Assembly; AppDomain appDomain = null; RuntimeAssemblyManager manager; try { appDomain = AppDomain.CreateDomain("HostedRuntimeEnvironment", null, AppDomain.CurrentDomain.BaseDirectory, null, false); manager = (RuntimeAssemblyManager)appDomain.CreateInstanceAndUnwrap(thisAssembly.FullName, appDomainProxyType.FullName); } catch { if (appDomain != null) { AppDomain.Unload(appDomain); } throw; } this.domain = appDomain; this.assemblyManager = manager; } else { this.assemblyManager = new RuntimeAssemblyManager(); } this.assemblyManager.AddModuleData(allModules); if (mainModule != null) { this.assemblyManager.AddMainModuleMvid(mainModule.Mvid); } }
/// <summary> /// Emit all of the references which are not directly or indirectly a <see cref="Compilation"/> value. /// </summary> internal static void EmitReferences(Compilation compilation, HashSet<string> fullNameSet, List<ModuleData> dependencies, DiagnosticBag diagnostics) { // NOTE: specifically don't need to consider previous submissions since they will always be compilations. foreach (var metadataReference in compilation.References) { if (metadataReference is CompilationReference) { continue; } var peRef = (PortableExecutableReference)metadataReference; var metadata = peRef.GetMetadataNoCopy(); var isManifestModule = peRef.Properties.Kind == MetadataImageKind.Assembly; var identity = isManifestModule ? ((AssemblyMetadata)metadata).GetAssembly().Identity : null; // If this is an indirect reference to a Compilation then it is already been emitted // so no more work to be done. if (isManifestModule && fullNameSet.Contains(identity.GetDisplayName())) { continue; } foreach (var module in EnumerateModules(metadata)) { ImmutableArray<byte> bytes = module.Module.PEReaderOpt.GetEntireImage().GetContent(); ModuleData moduleData; if (isManifestModule) { fullNameSet.Add(identity.GetDisplayName()); moduleData = new ModuleData(identity, OutputKind.DynamicallyLinkedLibrary, bytes, pdb: default(ImmutableArray<byte>), inMemoryModule: true); } else { moduleData = new ModuleData(module.Name, bytes, pdb: default(ImmutableArray<byte>), inMemoryModule: true); } dependencies.Add(moduleData); isManifestModule = false; } } }
internal static EmitOutput? EmitCompilation( Compilation compilation, IEnumerable<ResourceDescription> manifestResources, List<ModuleData> dependencies, DiagnosticBag diagnostics, CompilationTestData testData ) { // A Compilation can appear multiple times in a depnedency graph as both a Compilation and as a MetadataReference // value. Iterate the Compilations eagerly so they are always emitted directly and later references can re-use // the value. This gives better, and consistent, diagostic information. var referencedCompilations = FindReferencedCompilations(compilation); var fullNameSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (var referencedCompilation in referencedCompilations) { var emitData = RuntimeUtilities.EmitCompilationCore(referencedCompilation, null, diagnostics, null); if (emitData.HasValue) { var moduleData = new ModuleData(referencedCompilation.Assembly.Identity, OutputKind.DynamicallyLinkedLibrary, emitData.Value.Assembly, pdb: default(ImmutableArray<byte>), inMemoryModule: true); fullNameSet.Add(moduleData.Id.FullName); dependencies.Add(moduleData); } } // Now that the Compilation values have been emitted, emit the non-compilation references foreach (var current in (new[] { compilation }).Concat(referencedCompilations)) { EmitReferences(current, fullNameSet, dependencies, diagnostics); } return RuntimeUtilities.EmitCompilationCore(compilation, manifestResources, diagnostics, testData); }
public void Emit(Compilation mainCompilation, IEnumerable<ResourceDescription> manifestResources, bool emitPdb) { var diagnostics = DiagnosticBag.GetInstance(); var dependencies = new List<ModuleData>(); testData.Methods.Clear(); ImmutableArray<byte> mainImage, mainPdb; bool succeeded = EmitCompilation(mainCompilation, manifestResources, dependencies, diagnostics, emitPdb, testData, out mainImage, out mainPdb); this.lazyDiagnostics = diagnostics.ToReadOnlyAndFree(); if (succeeded) { this.mainModule = new ModuleData(mainCompilation.Assembly.Identity, mainCompilation.Options.OutputKind, mainImage, mainPdb, inMemoryModule: true); this.allModuleData = dependencies; this.allModuleData.Insert(0, mainModule); this.assemblyManager = CreateAssemblyManager(dependencies, mainModule); } else { string dumpDir; RuntimeAssemblyManager.DumpAssemblyData(dependencies, out dumpDir); // This method MUST throw if compilation did not succeed. If compilation succeeded and there were errors, that is bad. // Please see KevinH if you intend to change this behavior as many tests expect the Exception to indicate failure. throw new EmitException(this.lazyDiagnostics, dumpDir); // ToArray for serializability. } }
internal AssemblyData(ModuleData moduleData) { ModuleData = moduleData; Assembly = null; }
public SerializableModuleData(ModuleData moduleData) { _moduleData = moduleData; }
private void CreateAssemblyManager(IEnumerable <ModuleData> compilationDependencies, ModuleData mainModule) { var allModules = compilationDependencies; if (_additionalDependencies != null) { allModules = allModules.Concat(_additionalDependencies); } // We need to add the main module so that it gets checked against already loaded assembly names. // If an assembly is loaded directly via PEVerify(image) another assembly of the same full name // can't be loaded as a dependency (via Assembly.ReflectionOnlyLoad) in the same domain. if (mainModule != null) { allModules = allModules.Concat(new[] { mainModule }); } allModules = allModules.ToArray(); string conflict = DetectNameCollision(allModules); if (conflict != null && !CLRHelpers.IsRunningOnMono()) { Type appDomainProxyType = typeof(RuntimeAssemblyManager); Assembly thisAssembly = appDomainProxyType.Assembly; AppDomain appDomain = null; RuntimeAssemblyManager manager; try { appDomain = AppDomain.CreateDomain("HostedRuntimeEnvironment", null, AppDomain.CurrentDomain.BaseDirectory, null, false); manager = (RuntimeAssemblyManager)appDomain.CreateInstanceAndUnwrap(thisAssembly.FullName, appDomainProxyType.FullName); } catch { if (appDomain != null) { AppDomain.Unload(appDomain); } throw; } _domain = appDomain; _assemblyManager = manager; } else { _assemblyManager = new RuntimeAssemblyManager(); } _assemblyManager.AddModuleData(allModules); if (mainModule != null) { _assemblyManager.AddMainModuleMvid(mainModule.Mvid); } }
private RuntimeAssemblyManager CreateAssemblyManager(IEnumerable <ModuleData> compilationDependencies, ModuleData mainModule) { var allModules = compilationDependencies; if (additionalDependencies != null) { allModules = allModules.Concat(additionalDependencies); } // We need to add the main module so that it gets checked against already loaded assembly names. // If an assembly is loaded directly via PEVerify(image) another assembly of the same full name // can't be loaded as a dependency (via Assembly.ReflectionOnlyLoad) in the same domain. if (mainModule != null) { allModules = allModules.Concat(new[] { mainModule }); } allModules = allModules.ToArray(); string conflict = DetectNameCollision(allModules); RuntimeAssemblyManager manager; if (conflict != null) { Type appDomainProxyType = typeof(RuntimeAssemblyManager); Assembly thisAssembly = appDomainProxyType.Assembly; this.domain = AppDomain.CreateDomain("HostedRuntimeEnvironment", null, Environment.CurrentDirectory, null, false); manager = (RuntimeAssemblyManager)domain.CreateInstanceAndUnwrap(thisAssembly.FullName, appDomainProxyType.FullName); } else { manager = new RuntimeAssemblyManager(); } manager.AddModuleData(allModules); if (mainModule != null) { manager.AddMainModuleMvid(mainModule.Mvid); } return(manager); }