public static object GetRuntimeInterfaceAsObject(Guid clsid, Guid riid) { // This API isn't available on Mono hence we must use reflection to access it. Debug.Assert(!MonoHelpers.IsRunningOnMono()); var getRuntimeInterfaceAsObject = typeof(RuntimeEnvironment).GetMethod("GetRuntimeInterfaceAsObject", BindingFlags.Public | BindingFlags.Static); return(getRuntimeInterfaceAsObject.Invoke(null, new object[] { clsid, riid })); }
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 && !MonoHelpers.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); } }
internal static bool EmitCompilation( Compilation compilation, IEnumerable <ResourceDescription> manifestResources, List <ModuleData> dependencies, DiagnosticBag diagnostics, CompilationTestData testData, out ImmutableArray <byte> assembly, out ImmutableArray <byte> pdb ) { assembly = default(ImmutableArray <byte>); pdb = default(ImmutableArray <byte>); EmitReferences(compilation, dependencies, diagnostics); using (var executableStream = new MemoryStream()) { MemoryStream pdbStream = MonoHelpers.IsRunningOnMono() ? null : new MemoryStream(); EmitResult result; try { result = compilation.Emit( executableStream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: manifestResources, options: EmitOptions.Default, debugEntryPoint: null, testData: testData, getHostDiagnostics: null, cancellationToken: default(CancellationToken)); } finally { if (pdbStream != null) { pdb = pdbStream.ToImmutable(); pdbStream.Dispose(); } } diagnostics.AddRange(result.Diagnostics); assembly = executableStream.ToImmutable(); return(result.Success); } }
private static EmitOutput?EmitCompilationCore( Compilation compilation, IEnumerable <ResourceDescription> manifestResources, DiagnosticBag diagnostics, CompilationTestData testData ) { using (var executableStream = new MemoryStream()) { var pdb = default(ImmutableArray <byte>); var assembly = default(ImmutableArray <byte>); var pdbStream = MonoHelpers.IsRunningOnMono() ? null : new MemoryStream(); EmitResult result; try { result = compilation.Emit( executableStream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: manifestResources, options: EmitOptions.Default, debugEntryPoint: null, testData: testData, getHostDiagnostics: null, cancellationToken: default(CancellationToken)); } finally { if (pdbStream != null) { pdb = pdbStream.ToImmutable(); pdbStream.Dispose(); } } diagnostics.AddRange(result.Diagnostics); assembly = executableStream.ToImmutable(); if (result.Success) { return(new EmitOutput(assembly, pdb)); } return(null); } }
private void AssemblyLoad(object sender, AssemblyLoadEventArgs args) { var assembly = args.LoadedAssembly; // ModuleResolve needs to be hooked up for the main assembly once its loaded. // We won't get an AssemblyResolve event for the main assembly so we need to do it here. if (_mainMvids.Contains(assembly.ManifestModule.ModuleVersionId) && _loadedAssemblies.Add(assembly)) { if (!MonoHelpers.IsRunningOnMono()) { assembly.ModuleResolve += ModuleResolve; } } }
internal static ImmutableArray <byte> EmitToArray( this Compilation compilation, EmitOptions options = null, CompilationTestData testData = null, DiagnosticDescription[] expectedWarnings = null, Stream pdbStream = null, IMethodSymbol debugEntryPoint = null, Stream sourceLinkStream = null, IEnumerable <EmbeddedText> embeddedTexts = null, IEnumerable <ResourceDescription> manifestResources = null, Stream metadataPEStream = null) { var peStream = new MemoryStream(); if (pdbStream == null && compilation.Options.OptimizationLevel == OptimizationLevel.Debug && options?.DebugInformationFormat != DebugInformationFormat.Embedded) { if (MonoHelpers.IsRunningOnMono() || PathUtilities.IsUnixLikePlatform) { options = (options ?? EmitOptions.Default).WithDebugInformationFormat(DebugInformationFormat.PortablePdb); } var discretePdb = (object)options != null && options.DebugInformationFormat != DebugInformationFormat.Embedded; pdbStream = discretePdb ? new MemoryStream() : null; } var emitResult = compilation.Emit( peStream: peStream, metadataPEStream: metadataPEStream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: manifestResources, options: options, debugEntryPoint: debugEntryPoint, sourceLinkStream: sourceLinkStream, embeddedTexts: embeddedTexts, pdbOptionsBlobReader: null, testData: testData, cancellationToken: default(CancellationToken)); Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } return(peStream.ToImmutable()); }
private static string[] PeVerify(byte[] peImage, int domainId, string assemblyPath) { if (MonoHelpers.IsRunningOnMono()) { // PEverify is currently unsupported on Mono hence return an empty // set of messages return(new string[0]); } lock (s_guard) { GCHandle pinned = GCHandle.Alloc(peImage, GCHandleType.Pinned); try { IntPtr buffer = pinned.AddrOfPinnedObject(); ICLRValidator validator = (ICLRValidator)GetRuntimeInterfaceAsObject(s_clsIdClrRuntimeHost, typeof(ICLRRuntimeHost).GUID); ValidationErrorHandler errorHandler = new ValidationErrorHandler(validator); IMetaDataDispenser dispenser = (IMetaDataDispenser)GetRuntimeInterfaceAsObject(s_clsIdCorMetaDataDispenser, typeof(IMetaDataDispenser).GUID); // the buffer needs to be pinned during validation Guid riid = typeof(IMetaDataImport).GUID; object metaDataImport = null; if (assemblyPath != null) { dispenser.OpenScope(assemblyPath, CorOpenFlags.ofRead, ref riid, out metaDataImport); } else { dispenser.OpenScopeOnMemory(buffer, (uint)peImage.Length, CorOpenFlags.ofRead, ref riid, out metaDataImport); } IMetaDataValidate metaDataValidate = (IMetaDataValidate)metaDataImport; metaDataValidate.ValidatorInit(CorValidatorModuleType.ValidatorModuleTypePE, errorHandler); metaDataValidate.ValidateMetaData(); validator.Validate(errorHandler, (uint)domainId, ValidatorFlags.VALIDATOR_EXTRA_VERBOSE, ulMaxError: 10, token: 0, fileName: assemblyPath, pe: buffer, ulSize: (uint)peImage.Length); return(errorHandler.GetOutput()); } finally { pinned.Free(); } } }
private static RuntimeData GetOrCreateRuntimeData(IEnumerable <ModuleData> modules) { // Mono doesn't support AppDomains to the degree we use them for our tests and as a result many of // the checks are disabled. Create an instance in this domain since it's not actually used. if (MonoHelpers.IsRunningOnMono()) { return(new RuntimeData(new RuntimeAssemblyManager(), null)); } var data = TryGetCachedRuntimeData(modules); if (data != null) { return(data); } return(CreateRuntimeData()); }
internal static ImmutableArray <byte> EmitToArray( this Compilation compilation, EmitOptions options = null, CompilationTestData testData = null, DiagnosticDescription[] expectedWarnings = null, Stream pdbStream = null, IMethodSymbol debugEntryPoint = null) { var stream = new MemoryStream(); if (pdbStream == null && compilation.Options.OptimizationLevel == OptimizationLevel.Debug) { if (MonoHelpers.IsRunningOnMono()) { options = (options ?? EmitOptions.Default).WithDebugInformationFormat(DebugInformationFormat.PortablePdb); } pdbStream = new MemoryStream(); } var emitResult = compilation.Emit( peStream: stream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: null, options: options, debugEntryPoint: debugEntryPoint, testData: testData, getHostDiagnostics: null, cancellationToken: default(CancellationToken)); Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } return(stream.ToImmutable()); }
internal Assembly GetAssembly(string fullName, bool reflectionOnly) { ModuleData data; if (!_modules.TryGetValue(fullName, out data)) { return(null); } ConcurrentDictionary <Guid, Assembly> cache = reflectionOnly ? s_domainReflectionOnlyAssemblyCache : s_domainAssemblyCache; var assembly = cache.GetOrAdd(data.Mvid, _ => LoadAsAssembly(data.Image, reflectionOnly)); if (!MonoHelpers.IsRunningOnMono()) { assembly.ModuleResolve += ModuleResolve; } _loadedAssemblies.Add(assembly); return(assembly); }
public void Dispose() { // clean up our handlers, so that they don't accumulate AppDomain.CurrentDomain.AssemblyResolve -= AssemblyResolve; AppDomain.CurrentDomain.AssemblyLoad -= AssemblyLoad; CLRHelpers.ReflectionOnlyAssemblyResolve -= ReflectionOnlyAssemblyResolve; foreach (var assembly in _loadedAssemblies) { if (!MonoHelpers.IsRunningOnMono()) { assembly.ModuleResolve -= ModuleResolve; } } //EDMAURER Some RuntimeAssemblyManagers are created via reflection in an AppDomain of our creation. //Sometimes those AppDomains are not released. I don't fully understand how that appdomain roots //a RuntimeAssemblyManager, but according to heap dumps, it does. Even though the appdomain is not //unloaded, its RuntimeAssemblyManager is explicitly disposed. So make sure that it cleans up this //memory hog - the modules dictionary. _modules.Clear(); }
internal Assembly GetAssembly(string fullName, bool reflectionOnly) { AssemblyData data; if (!_fullNameToAssemblyDataMap.TryGetValue(fullName, out data)) { return(null); } Assembly assembly; switch (data.Kind) { case Kind.Assembly: assembly = data.Assembly; if (reflectionOnly && !assembly.ReflectionOnly) { assembly = Assembly.ReflectionOnlyLoad(assembly.FullName); } break; case Kind.ModuleData: assembly = _assemblyCache.GetOrLoad(data.ModuleData, reflectionOnly); break; default: throw new InvalidOperationException(); } if (!MonoHelpers.IsRunningOnMono()) { assembly.ModuleResolve += ModuleResolve; } _loadedAssemblies.Add(assembly); return(assembly); }
public static void IlasmTempAssembly(string declarations, bool appendDefaultHeader, bool includePdb, out string assemblyPath, out string pdbPath) { if (declarations == null) { throw new ArgumentNullException(nameof(declarations)); } using (var sourceFile = new DisposableFile(extension: ".il")) { string sourceFileName = Path.GetFileNameWithoutExtension(sourceFile.Path); assemblyPath = Path.Combine( TempRoot.Root, Path.ChangeExtension(Path.GetFileName(sourceFile.Path), "dll")); string completeIL; if (appendDefaultHeader) { const string corLibName = "mscorlib"; const string corLibVersion = "4:0:0:0"; const string corLibKey = "B7 7A 5C 56 19 34 E0 89"; completeIL = $@".assembly '{sourceFileName}' {{}} .assembly extern {corLibName} {{ .publickeytoken = ({corLibKey}) .ver {corLibVersion} }} {declarations}"; } else { completeIL = declarations.Replace("<<GeneratedFileName>>", sourceFileName); } sourceFile.WriteAllText(completeIL); var arguments = $"\"{sourceFile.Path}\" -DLL -out=\"{assemblyPath}\""; if (includePdb && !MonoHelpers.IsRunningOnMono()) { pdbPath = Path.ChangeExtension(assemblyPath, "pdb"); arguments += string.Format(" -PDB=\"{0}\"", pdbPath); } else { pdbPath = null; } var result = ProcessUtilities.Run(IlasmPath, arguments); if (result.ContainsErrors) { throw new ArgumentException( "The provided IL cannot be compiled." + Environment.NewLine + IlasmPath + " " + arguments + Environment.NewLine + result, nameof(declarations)); } } }
public static void IlasmTempAssembly(string declarations, bool appendDefaultHeader, bool includePdb, out string assemblyPath, out string pdbPath) { if (declarations == null) { throw new ArgumentNullException(nameof(declarations)); } using (var sourceFile = new DisposableFile(extension: ".il")) { string sourceFileName = Path.GetFileNameWithoutExtension(sourceFile.Path); assemblyPath = Path.Combine( TempRoot.Root, Path.ChangeExtension(Path.GetFileName(sourceFile.Path), "dll")); string completeIL; if (appendDefaultHeader) { completeIL = string.Format( @".assembly '{0}' {{}} .assembly extern mscorlib {{ .publickeytoken = (B7 7A 5C 56 19 34 E0 89) .ver 4:0:0:0 }} {1}", sourceFileName, declarations); } else { completeIL = declarations.Replace("<<GeneratedFileName>>", sourceFileName); } sourceFile.WriteAllText(completeIL); var ilasmPath = Path.Combine( Path.GetDirectoryName(typeof(object).Assembly.Location), "ilasm.exe"); var arguments = string.Format( "\"{0}\" /DLL /OUT=\"{1}\"", sourceFile.Path, assemblyPath); if (includePdb && !MonoHelpers.IsRunningOnMono()) { pdbPath = Path.ChangeExtension(assemblyPath, "pdb"); arguments += string.Format(" /PDB=\"{0}\"", pdbPath); } else { pdbPath = null; } var program = ilasmPath; if (MonoHelpers.IsRunningOnMono()) { arguments = string.Format("{0} {1}", ilasmPath, arguments); arguments = arguments.Replace("\"", ""); arguments = arguments.Replace("=", ":"); program = "mono"; } var result = ProcessUtilities.Run(program, arguments); if (result.ContainsErrors) { throw new ArgumentException( "The provided IL cannot be compiled." + Environment.NewLine + program + " " + arguments + Environment.NewLine + result, nameof(declarations)); } } }