Пример #1
0
        public unsafe ExecutionResult Execute(Assembly assembly, RuntimeGuardToken guardToken, IWorkSession session)
        {
            try {
                Output.Reset();
                Flow.Reset();
                Console.SetOut(Output.Writer);

                var main = assembly.EntryPoint;
                if (main == null)
                {
                    throw new ArgumentException("Entry point not found in " + assembly, nameof(assembly));
                }
                using (guardToken.Scope(NewRuntimeGuardSettings())) {
                    var args = main.GetParameters().Length > 0 ? new object[] { new string[0] } : null;

                    PerformanceLog.Checkpoint("Executor.Invoke.Start");
                    var result = main.Invoke(null, args);
                    PerformanceLog.Checkpoint("Executor.Invoke.End");

                    if (main.ReturnType != typeof(void))
                    {
                        result.Inspect("Return");
                    }
                    return(new ExecutionResult(Output.Stream, Flow.Steps));
                }
            }
            catch (Exception ex) {
                PerformanceLog.Checkpoint("Executor.Invoke.Exception");
                if (ex is TargetInvocationException invocationEx)
                {
                    ex = invocationEx.InnerException ?? ex;
                }

                if (ex is RegexMatchTimeoutException)
                {
                    ex = new TimeGuardException("Time limit reached while evaluating a Regex.\r\nNote that timeout was added by SharpLab — in real code this would not throw, but might run for a very long time.", ex);
                }

                if (ex is StackGuardException sgex)
                {
                    throw new Exception($"{sgex.Message} {sgex.StackBaseline} {sgex.StackOffset} {sgex.StackLimit} {sgex.StackSize}");
                }

                Flow.ReportException(ex);
                Output.Write(new SimpleInspection("Exception", ex.ToString()));
                if (ShouldMonitorException(ex))
                {
                    _monitor.Exception(ex !, session);
                }
                return(new ExecutionResult(Output.Stream, Flow.Steps));
            }
        }
        private void AddToCaches(IReadOnlyCollection <string> assemblyPaths)
        {
            PerformanceLog.Checkpoint("PreCachedAssemblyResolver.AddToCaches.Start");
            foreach (var path in assemblyPaths)
            {
                var file = new PEFile(path);
                _peFileCache.TryAdd(file.Name, file);

                var definition = AssemblyDefinition.ReadAssembly(path);
                _cecilCache.TryAdd(definition.Name.Name, definition);
            }
            PerformanceLog.Checkpoint("PreCachedAssemblyResolver.AddToCaches.End");
        }
Пример #3
0
        public static MirrorSharpOptions CreateMirrorSharpOptions(ILifetimeScope container)
        {
            var options = new MirrorSharpOptions {
                IncludeExceptionDetails = true
            };
            var languages = container.Resolve <ILanguageAdapter[]>();

            foreach (var language in languages)
            {
                language.SlowSetup(options);
            }
            PerformanceLog.Checkpoint("Startup.CreateMirrorSharpOptions.End");
            return(options);
        }
Пример #4
0
        public static MirrorSharpOptions CreateMirrorSharpOptions(ILifetimeScope container)
        {
            var options = new MirrorSharpOptions {
                SetOptionsFromClient    = container.Resolve <ISetOptionsFromClientExtension>(),
                SlowUpdate              = container.Resolve <ISlowUpdateExtension>(),
                IncludeExceptionDetails = true,
                ExceptionLogger         = container.Resolve <IExceptionLogger>()
            };
            var languages = container.Resolve <ILanguageAdapter[]>();

            foreach (var language in languages)
            {
                language.SlowSetup(options);
            }
            PerformanceLog.Checkpoint("Startup.CreateMirrorSharpOptions.End");
            return(options);
        }
Пример #5
0
        public ExecutionResult Execute(CompilationStreamPair streams, IWorkSession session)
        {
            var readerParameters = new ReaderParameters {
                ReadSymbols          = streams.SymbolStream != null,
                SymbolStream         = streams.SymbolStream,
                AssemblyResolver     = _assemblyResolver,
                SymbolReaderProvider = streams.SymbolStream != null ? _symbolReaderProvider : null
            };

            using (streams)
                using (var definition = AssemblyDefinition.ReadAssembly(streams.AssemblyStream, readerParameters)) {
                    foreach (var rewriter in _rewriters)
                    {
                        rewriter.Rewrite(definition, session);
                    }
                    PerformanceLog.Checkpoint("Executor.Rewrite.Flow.End");

                    AssemblyLog.Log("2.WithFlow", definition);
                    if (definition.EntryPoint == null)
                    {
                        Output.Reset();
                        Flow.Reset();
                        Output.WriteWarning("Could not find any code to run (either a Main method or any top level code).");
                        return(new ExecutionResult(Output.Stream, Flow.Steps));
                    }

                    var guardToken = AssemblyGuard.Rewrite(definition, _guardSettings);
                    using (var rewrittenStream = _memoryStreamManager.GetStream()) {
                        definition.Write(rewrittenStream);

                        AssemblyLog.Log("3.Unbreakable", definition);

                        rewrittenStream.Seek(0, SeekOrigin.Begin);
                        PerformanceLog.Checkpoint("Executor.Rewrite.Unbreakable.End");
                        using (var context = new CustomAssemblyLoadContext(shouldShareAssembly: ShouldShareAssembly)) {
                            var assembly = context.LoadFromStream(rewrittenStream);
                            PerformanceLog.Checkpoint("Executor.AssemblyLoad.End");

                            return(Execute(assembly, guardToken, session));
                        }
                    }
                }
        }
Пример #6
0
        public ExecutionResult Execute(CompilationStreamPair streams, IWorkSession session)
        {
            var readerParameters = new ReaderParameters {
                ReadSymbols          = streams.SymbolStream != null,
                SymbolStream         = streams.SymbolStream,
                AssemblyResolver     = _assemblyResolver,
                SymbolReaderProvider = streams.SymbolStream != null ? _symbolReaderProvider : null
            };

            using (streams)
                using (var definition = AssemblyDefinition.ReadAssembly(streams.AssemblyStream, readerParameters)) {
                    AssemblyLog.Log("1.Initial", definition);

                    foreach (var rewriter in _rewriters)
                    {
                        rewriter.Rewrite(definition, session);
                    }
                    PerformanceLog.Checkpoint("Executor.Rewrite.Flow.End");

                    AssemblyLog.Log("2.WithFlow", definition);
                    if (definition.EntryPoint == null)
                    {
                        throw new ArgumentException("Failed to find an entry point (Main?) in assembly.", nameof(streams));
                    }

                    var guardToken = AssemblyGuard.Rewrite(definition, _guardSettings);
                    using (var rewrittenStream = _memoryStreamManager.GetStream()) {
                        definition.Write(rewrittenStream);

                        AssemblyLog.Log("3.Unbreakable", definition);

                        rewrittenStream.Seek(0, SeekOrigin.Begin);
                        PerformanceLog.Checkpoint("Executor.Rewrite.Unbreakable.End");
                        using (var context = new CustomAssemblyLoadContext(shouldShareAssembly: ShouldShareAssembly)) {
                            var assembly = context.LoadFromStream(rewrittenStream);
                            PerformanceLog.Checkpoint("Executor.AssemblyLoad.End");

                            return(Execute(assembly, guardToken, session));
                        }
                    }
                }
        }
Пример #7
0
        public async Task <(bool assembly, bool symbols)> TryCompileToStreamAsync(MemoryStream assemblyStream, MemoryStream?symbolStream, IWorkSession session, IList <Diagnostic> diagnostics, CancellationToken cancellationToken)
        {
            PerformanceLog.Checkpoint("Compiler.TryCompileToStreamAsync.Start");
            if (session.IsFSharp())
            {
                var compiled = await TryCompileFSharpToStreamAsync(assemblyStream, session, diagnostics, cancellationToken).ConfigureAwait(false);

                return(compiled, false);
            }

            #warning TODO: Revisit after https://github.com/dotnet/docs/issues/14784
            var compilation = (await session.Roslyn.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false)) !;
            var emitResult  = compilation.Emit(assemblyStream, pdbStream: symbolStream, options: RoslynEmitOptions);
            PerformanceLog.Checkpoint("Compiler.TryCompileToStreamAsync.Emit.End");
            if (!emitResult.Success)
            {
                foreach (var diagnostic in emitResult.Diagnostics)
                {
                    diagnostics.Add(diagnostic);
                }
                return(false, false);
            }
            return(true, true);
        }
Пример #8
0
        public async Task <object?> ProcessAsync(IWorkSession session, IList <Diagnostic> diagnostics, CancellationToken cancellationToken)
        {
            PerformanceLog.Checkpoint("SlowUpdate.ProcessAsync.Start");
            var targetName = GetAndEnsureTargetName(session);

            if (targetName == TargetNames.Ast || targetName == TargetNames.Explain)
            {
                var astTarget = _astTargets[session.LanguageName];
                var ast       = await astTarget.GetAstAsync(session, cancellationToken).ConfigureAwait(false);

                if (targetName == TargetNames.Explain)
                {
                    return(await _explainer.ExplainAsync(ast, session, cancellationToken).ConfigureAwait(false));
                }
                return(ast);
            }

            if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error))
            {
                return(null);
            }

            if (targetName == LanguageNames.VisualBasic)
            {
                return(VisualBasicNotAvailable);
            }

            if (targetName != TargetNames.Run && targetName != TargetNames.Verify && !_decompilers.ContainsKey(targetName))
            {
                throw new NotSupportedException($"Target '{targetName}' is not (yet?) supported by this branch.");
            }

            MemoryStream?assemblyStream = null;
            MemoryStream?symbolStream   = null;

            try {
                assemblyStream = _memoryStreamManager.GetStream();
                if (targetName == TargetNames.Run || targetName == TargetNames.IL)
                {
                    symbolStream = _memoryStreamManager.GetStream();
                }

                var compiled = await _compiler.TryCompileToStreamAsync(assemblyStream, symbolStream, session, diagnostics, cancellationToken).ConfigureAwait(false);

                if (!compiled.assembly)
                {
                    assemblyStream.Dispose();
                    symbolStream?.Dispose();
                    return(null);
                }

                if (targetName == TargetNames.Verify)
                {
                    assemblyStream.Dispose();
                    symbolStream?.Dispose();
                    return("✔️ Compilation completed.");
                }

                assemblyStream.Seek(0, SeekOrigin.Begin);
                symbolStream?.Seek(0, SeekOrigin.Begin);
                var streams = new CompilationStreamPair(assemblyStream, compiled.symbols ? symbolStream : null);
                if (targetName == TargetNames.Run)
                {
                    return(_executor.Execute(streams, session));
                }

                // it's fine not to Dispose() here -- MirrorSharp will dispose it after calling WriteResult()
                return(streams);
            }
            catch {
                assemblyStream?.Dispose();
                symbolStream?.Dispose();
                throw;
            }
        }
Пример #9
0
        public async Task <object?> ProcessAsync(IWorkSession session, IList <Diagnostic> diagnostics, CancellationToken cancellationToken)
        {
            PerformanceLog.Checkpoint("SlowUpdate.ProcessAsync.Start");
            var targetName = GetAndEnsureTargetName(session);

            _topLevelProgramSupport.UpdateOutputKind(session, diagnostics);

            if (targetName is TargetNames.Ast or TargetNames.Explain)
            {
                var astTarget = _astTargets[session.LanguageName];
                var ast       = await astTarget.GetAstAsync(session, cancellationToken).ConfigureAwait(false);

                if (targetName == TargetNames.Explain)
                {
                    return(await _explainer.ExplainAsync(ast, session, cancellationToken).ConfigureAwait(false));
                }
                return(ast);
            }

            if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error))
            {
                return(null);
            }

            if (targetName == LanguageNames.VisualBasic)
            {
                return(VisualBasicNotAvailable);
            }

            if (targetName is not(TargetNames.Run or TargetNames.Verify) && !_decompilers.ContainsKey(targetName))
            {
                throw new NotSupportedException($"Target '{targetName}' is not (yet?) supported by this branch.");
            }

            MemoryStream?assemblyStream = null;
            MemoryStream?symbolStream   = null;

            try {
                assemblyStream = _memoryStreamManager.GetStream();
                if (targetName is TargetNames.Run or TargetNames.IL)
                {
                    symbolStream = _memoryStreamManager.GetStream();
                }

                var compilationStopwatch = session.ShouldReportPerformance() ? Stopwatch.StartNew() : null;
                var compiled             = await _compiler.TryCompileToStreamAsync(assemblyStream, symbolStream, session, diagnostics, cancellationToken).ConfigureAwait(false);

                compilationStopwatch?.Stop();
                if (!compiled.assembly)
                {
                    assemblyStream.Dispose();
                    symbolStream?.Dispose();
                    return(null);
                }

                if (targetName == TargetNames.Verify)
                {
                    assemblyStream.Dispose();
                    symbolStream?.Dispose();
                    return("✔️ Compilation completed.");
                }

                assemblyStream.Seek(0, SeekOrigin.Begin);
                symbolStream?.Seek(0, SeekOrigin.Begin);
                AssemblyLog.Log("1.Compiled", assemblyStream, compiled.symbols ? symbolStream : null);

                var streams = new CompilationStreamPair(assemblyStream, compiled.symbols ? symbolStream : null);
                if (targetName == TargetNames.Run)
                {
                    if (!session.HasContainerExperimentFailed())
                    {
                        try {
                            var output = await _containerExecutor.ExecuteAsync(streams, session, cancellationToken);

                            if (compilationStopwatch != null)
                            {
                                // TODO: Prettify
                                output += $"\n  COMPILATION: {compilationStopwatch.ElapsedMilliseconds,15}ms";
                            }
                            streams.Dispose();
                            _monitor.Metric(ContainerExperimentMetrics.ContainerRunCount, 1);
                            return(output);
                        }
                        catch (Exception ex) {
                            _monitor.Metric(ContainerExperimentMetrics.ContainerFailureCount, 1);
                            _monitor.Exception(ex, session);
                            session.SetContainerExperimentException(ex);
                            assemblyStream.Seek(0, SeekOrigin.Begin);
                            symbolStream?.Seek(0, SeekOrigin.Begin);
                        }
                    }

                    _monitor.Metric(ContainerExperimentMetrics.LegacyRunCount, 1);
                    return(_executor.Execute(streams, session));
                }

                // it's fine not to Dispose() here -- MirrorSharp will dispose it after calling WriteResult()
                return(streams);
            }
            catch {
                assemblyStream?.Dispose();
                symbolStream?.Dispose();
                throw;
            }
        }