예제 #1
0
        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 }));
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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;
                }
            }
        }
예제 #6
0
        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());
        }
예제 #7
0
        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();
                }
            }
        }
예제 #8
0
        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());
        }
예제 #9
0
        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());
        }
예제 #10
0
        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);
        }
예제 #11
0
        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();
        }
예제 #12
0
        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);
        }
예제 #13
0
        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));
                }
            }
        }
예제 #14
0
        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));
                }
            }
        }