List <DiagnosticMessage> RunILPostProcessors(ScriptAssembly assembly, string outputTempPath) { Profiler.BeginSample("CompilationPipeline.RunILPostProcessors"); var assemblyPath = Path.Combine(outputTempPath, assembly.Filename); var resultMessages = new List <DiagnosticMessage>(); if (!File.Exists(assemblyPath)) { resultMessages.Add(new DiagnosticMessage { File = assemblyPath, MessageData = $"Could not find {assemblyPath} for post processing", DiagnosticType = DiagnosticType.Error, }); } bool isILProcessed = false; var ilPostProcessCompiledAssembly = new ILPostProcessCompiledAssembly(assembly, outputTempPath); InMemoryAssembly postProcessedInMemoryAssembly = null; foreach (var ilPostProcessor in ILPostProcessors) { Profiler.BeginSample($"{ilPostProcessor.GetType().FullName}.Process({assembly.Filename})"); var stopwatch = new Stopwatch(); stopwatch.Start(); Console.WriteLine($" - Starting ILPostProcessor '{ilPostProcessor.GetType().FullName}' on {assembly.Filename}"); var ilPostProcessorInstance = ilPostProcessor.GetInstance(); var ilPostProcessResult = ilPostProcessorInstance.Process(ilPostProcessCompiledAssembly); stopwatch.Stop(); Profiler.EndSample(); var elapsed = stopwatch.Elapsed; Console.WriteLine($" - Finished ILPostProcessor '{ilPostProcessor.GetType().FullName}' on {assembly.Filename} in {elapsed.TotalSeconds:0.######} seconds"); postProcessedInMemoryAssembly = ilPostProcessResult?.InMemoryAssembly; if (ilPostProcessResult?.InMemoryAssembly != null) { isILProcessed = true; ilPostProcessCompiledAssembly.InMemoryAssembly = postProcessedInMemoryAssembly; } if (ilPostProcessResult?.Diagnostics != null) { resultMessages.AddRange(ilPostProcessResult.Diagnostics); } } if (isILProcessed) { ilPostProcessCompiledAssembly.WriteAssembly(); } Profiler.EndSample(); return(resultMessages); }
public CompiledAssemblyFromFile(string assemblyPath) { this.assemblyPath = assemblyPath; byte[] peData = File.ReadAllBytes(assemblyPath); string pdbFileName = Path.GetFileNameWithoutExtension(assemblyPath) + ".pdb"; byte[] pdbData = File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(assemblyPath), pdbFileName)); InMemoryAssembly = new InMemoryAssembly(peData, pdbData); }
public ILPostProcessResult PostProcessInternal(ICompiledAssembly compiledAssembly) { AssemblyDefinition assemblyDefinition; #if MEDICINE_IL_DEBUG using (NonAlloc.Benchmark.Start($"GetAssemblyDefinition ({compiledAssembly.Name})")) #endif assemblyDefinition = PostProcessorAssemblyResolver.GetAssemblyDefinitionFor(compiledAssembly); try { CecilExtensions.CurrentModule = assemblyDefinition.MainModule; PostProcessorContext context; #if MEDICINE_IL_DEBUG using (NonAlloc.Benchmark.Start($"CreatePostProcessorContext ({compiledAssembly.Name})")) #endif context = new PostProcessorContext(assemblyDefinition.MainModule); #if MEDICINE_IL_DEBUG using (NonAlloc.Benchmark.Start($"MedicineInjection ({compiledAssembly.Name})")) #endif new InjectionPostProcessor(context).ProcessAssembly(); var pe = new MemoryStream(capacity: 1024 * 64); var pdb = new MemoryStream(capacity: 1024 * 16); var writerParameters = new WriterParameters { SymbolWriterProvider = new PortablePdbWriterProvider(), SymbolStream = pdb, WriteSymbols = true, }; assemblyDefinition.Write(pe, writerParameters); var inMemoryAssembly = new InMemoryAssembly(pe.ToArray(), pdb.ToArray()); return(new ILPostProcessResult(inMemoryAssembly, context.DiagnosticMessages)); } catch (Exception ex) { var error = new DiagnosticMessage { MessageData = $"Unexpected exception while post-processing assembly {compiledAssembly.Name}:\n{ex}", DiagnosticType = DiagnosticType.Error, }; return(new ILPostProcessResult(compiledAssembly.InMemoryAssembly, new List <DiagnosticMessage> { error })); } finally { CecilExtensions.CurrentModule.Dispose(); CecilExtensions.CurrentModule = null; } }
private InMemoryAssembly CreateOrGetInMemoryAssembly() { if (m_InMemoryAssembly != null) { return(m_InMemoryAssembly); } byte[] peData = File.ReadAllBytes(Path.Combine(m_OutputPath, m_AssemblyFilename)); var pdbFileName = Path.GetFileNameWithoutExtension(m_AssemblyFilename) + ".pdb"; byte[] pdbData = File.ReadAllBytes(Path.Combine(m_OutputPath, pdbFileName)); m_InMemoryAssembly = new InMemoryAssembly(peData, pdbData); return(m_InMemoryAssembly); }
public CompiledAssembly(string asmPath, string[] referencePaths, string[] defines) { var peData = File.ReadAllBytes(asmPath); byte[] pdbData = null; var pdbPath = Path.ChangeExtension(asmPath, "pdb"); if (File.Exists(pdbPath)) { pdbData = File.ReadAllBytes(pdbPath); } Name = Path.GetFileNameWithoutExtension(asmPath); References = referencePaths; InMemoryAssembly = new InMemoryAssembly(peData, pdbData); Defines = defines; }
public void AddAssembly(InMemoryAssembly assembly) { Assembly.Load(assembly.Data, null, SecurityContextSource.CurrentAppDomain); }
public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) { //Log.Warning($"Processing {compiledAssembly.Name}"); // load the InMemoryAssembly peData into a MemoryStream byte[] peData = compiledAssembly.InMemoryAssembly.PeData; //LogDiagnostics($" peData.Length={peData.Length} bytes"); using (MemoryStream stream = new MemoryStream(peData)) using (ILPostProcessorAssemblyResolver asmResolver = new ILPostProcessorAssemblyResolver(compiledAssembly, Log)) { // we need to load symbols. otherwise we get: // "(0,0): error Mono.CecilX.Cil.SymbolsNotFoundException: No symbol found for file: " using (MemoryStream symbols = new MemoryStream(compiledAssembly.InMemoryAssembly.PdbData)) { ReaderParameters readerParameters = new ReaderParameters { SymbolStream = symbols, ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver, // custom reflection importer to fix System.Private.CoreLib // not being found in custom assembly resolver above. ReflectionImporterProvider = new ILPostProcessorReflectionImporterProvider() }; using (AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(stream, readerParameters)) { // resolving a Mirror.dll type like NetworkServer while // weaving Mirror.dll does not work. it throws a // NullReferenceException in WeaverTypes.ctor // when Resolve() is called on the first Mirror type. // need to add the AssemblyDefinition itself to use. asmResolver.SetAssemblyDefinitionForCompiledAssembly(asmDef); // weave this assembly. Weaver weaver = new Weaver(Log); if (weaver.Weave(asmDef, asmResolver, out bool modified)) { //Log.Warning($"Weaving succeeded for: {compiledAssembly.Name}"); // write if modified if (modified) { // when weaving Mirror.dll with ILPostProcessor, // Weave() -> WeaverTypes -> resolving the first // type in Mirror.dll adds a reference to // Mirror.dll even though we are in Mirror.dll. // -> this would throw an exception: // "Mirror references itself" and not compile // -> need to detect and fix manually here if (asmDef.MainModule.AssemblyReferences.Any(r => r.Name == asmDef.Name.Name)) { asmDef.MainModule.AssemblyReferences.Remove(asmDef.MainModule.AssemblyReferences.First(r => r.Name == asmDef.Name.Name)); //Log.Warning($"fixed self referencing Assembly: {asmDef.Name.Name}"); } MemoryStream peOut = new MemoryStream(); MemoryStream pdbOut = new MemoryStream(); WriterParameters writerParameters = new WriterParameters { SymbolWriterProvider = new PortablePdbWriterProvider(), SymbolStream = pdbOut, WriteSymbols = true }; asmDef.Write(peOut, writerParameters); InMemoryAssembly inMemory = new InMemoryAssembly(peOut.ToArray(), pdbOut.ToArray()); return(new ILPostProcessResult(inMemory, Log.Logs)); } } // if anything during Weave() fails, we log an error. // don't need to indicate 'weaving failed' again. // in fact, this would break tests only expecting certain errors. //else Log.Error($"Weaving failed for: {compiledAssembly.Name}"); } } } // always return an ILPostProcessResult with Logs. // otherwise we won't see Logs if weaving failed. return(new ILPostProcessResult(compiledAssembly.InMemoryAssembly, Log.Logs)); }
internal void Save(string fileName, bool throwOnError) { //It is very tempting to use XmlSerializer but it adds 200 ms to the //application startup time. Whereas current startup delay for cscs.exe is just a 100 ms. try { XmlDocument doc = new XmlDocument(); doc.LoadXml("<CSSConfig/>"); //write the all most important elements and less important ones only if they have non-default values. doc.DocumentElement.AppendChild(doc.CreateElement("defaultArguments")).AppendChild(doc.CreateTextNode(DefaultArguments)); doc.DocumentElement.AppendChild(doc.CreateElement("defaultRefAssemblies")).AppendChild(doc.CreateTextNode(DefaultRefAssemblies)); doc.DocumentElement.AppendChild(doc.CreateElement("searchDirs")).AppendChild(doc.CreateTextNode(SearchDirs)); doc.DocumentElement.AppendChild(doc.CreateElement("useAlternativeCompiler")).AppendChild(doc.CreateTextNode(UseAlternativeCompiler)); doc.DocumentElement.AppendChild(doc.CreateElement("roslynDir")).AppendChild(doc.CreateTextNode(RoslynDir)); doc.DocumentElement.AppendChild(doc.CreateElement("consoleEncoding")).AppendChild(doc.CreateTextNode(ConsoleEncoding)); doc.DocumentElement.AppendChild(doc.CreateElement("autoclass.decorateAsCS6")).AppendChild(doc.CreateTextNode(autoClass_DecorateAsCS6.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("inMemoryAsm")).AppendChild(doc.CreateTextNode(InMemoryAssembly.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("hideCompilerWarnings")).AppendChild(doc.CreateTextNode(HideCompilerWarnings.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("reportDetailedErrorInfo")).AppendChild(doc.CreateTextNode(ReportDetailedErrorInfo.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("enableDbgPrint")).AppendChild(doc.CreateTextNode(enableDbgPrint.ToString())); if (hideOptions != HideOptions.HideAll) { doc.DocumentElement.AppendChild(doc.CreateElement("hideOptions")).AppendChild(doc.CreateTextNode(hideOptions.ToString())); } if (autoClass_DecorateAlways) { doc.DocumentElement.AppendChild(doc.CreateElement("autoclass.decorateAlways")).AppendChild(doc.CreateTextNode(autoClass_DecorateAlways.ToString())); } if (DefaultApartmentState != ApartmentState.STA) { doc.DocumentElement.AppendChild(doc.CreateElement("defaultApartmentState")).AppendChild(doc.CreateTextNode(DefaultApartmentState.ToString())); } if (!string.IsNullOrEmpty(precompiler)) { doc.DocumentElement.AppendChild(doc.CreateElement("precompiler")).AppendChild(doc.CreateTextNode(Precompiler)); } if (!string.IsNullOrEmpty(UsePostProcessor)) { doc.DocumentElement.AppendChild(doc.CreateElement("usePostProcessor")).AppendChild(doc.CreateTextNode(UsePostProcessor)); } if (!string.IsNullOrEmpty(CleanupShellCommand)) { doc.DocumentElement.AppendChild(doc.CreateElement("cleanupShellCommand")).AppendChild(doc.CreateTextNode(CleanupShellCommand)); doc.DocumentElement.AppendChild(doc.CreateElement("doCleanupAfterNumberOfRuns")).AppendChild(doc.CreateTextNode(DoCleanupAfterNumberOfRuns.ToString())); } if (ConcurrencyControl != ConcurrencyControl.Standard) { doc.DocumentElement.AppendChild(doc.CreateElement("concurrencyControl")).AppendChild(doc.CreateTextNode(ConcurrencyControl.ToString())); } #if net35 if (TargetFramework != "v3.5") #else if (TargetFramework != "v4.0") #endif { doc.DocumentElement.AppendChild(doc.CreateElement("targetFramework")).AppendChild(doc.CreateTextNode(TargetFramework)); } if (useSurrogatepHostingProcess) { doc.DocumentElement.AppendChild(doc.CreateElement("useSurrogatepHostingProcess")).AppendChild(doc.CreateTextNode(useSurrogatepHostingProcess.ToString())); } if (!openEndDirectiveSyntax) { doc.DocumentElement.AppendChild(doc.CreateElement("openEndDirectiveSyntax")).AppendChild(doc.CreateTextNode(openEndDirectiveSyntax.ToString())); } if (!CustomHashing) { doc.DocumentElement.AppendChild(doc.CreateElement("customHashing")).AppendChild(doc.CreateTextNode(CustomHashing.ToString())); } //note node.ParentNode.InsertAfter(doc.CreateComment("") injects int node inner text and it is not what we want //very simplistic formatting var xml = doc.InnerXml.Replace("><", ">\n <") .Replace(">\n </", "></") .Replace("></CSSConfig>", ">\n</CSSConfig>"); xml = CommentElement(xml, "consoleEncoding", "if 'default' then system default is used; otherwise specify the name of the encoding (e.g. 'utf-8')"); xml = CommentElement(xml, "autoclass.decorateAsCS6", "if 'true' auto-class decoration will inject C# 6 specific syntax expressions (e.g. 'using static dbg;')"); xml = CommentElement(xml, "autoclass.decorateAlways", "if 'true' decorate classless scripts unconditionally; otherwise only if a top level class-less 'main' detected. Not used yet."); xml = CommentElement(xml, "useAlternativeCompiler", "Custom script compiler. For example C# 7 (Roslyn): '%CSSCRIPT_DIR%!lib!CSSRoslynProvider.dll'".Replace('!', Path.DirectorySeparatorChar)); xml = CommentElement(xml, "roslynDir", "Location of Roslyn compilers to be used by custom script compilers. For example C# 7 (Roslyn): /usr/lib/mono/4.5"); xml = CommentElement(xml, "enableDbgPrint", "Gets or sets a value indicating whether to enable Python-like print methods (e.g. dbg.print(DateTime.Now))"); File.WriteAllText(fileName, xml); } catch { if (throwOnError) { throw; } } }
/// <summary> /// Saves CS-Script application settings to a file (.dat). /// </summary> /// <param name="fileName">File name of the .dat file</param> public void Save(string fileName) { //It is very tempting to use XmlSerializer but it adds 200 ms to the //application startup time. Whereas current startup delay for cscs.exe is just a 100 ms. try { XmlDocument doc = new XmlDocument(); doc.LoadXml("<CSSConfig/>"); doc.DocumentElement.AppendChild(doc.CreateElement("defaultArguments")).AppendChild(doc.CreateTextNode(DefaultArguments)); doc.DocumentElement.AppendChild(doc.CreateElement("defaultApartmentState")).AppendChild(doc.CreateTextNode(DefaultApartmentState.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("reportDetailedErrorInfo")).AppendChild(doc.CreateTextNode(ReportDetailedErrorInfo.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("useAlternativeCompiler")).AppendChild(doc.CreateTextNode(UseAlternativeCompiler)); doc.DocumentElement.AppendChild(doc.CreateElement("usePostProcessor")).AppendChild(doc.CreateTextNode(UsePostProcessor)); doc.DocumentElement.AppendChild(doc.CreateElement("searchDirs")).AppendChild(doc.CreateTextNode(SearchDirs)); doc.DocumentElement.AppendChild(doc.CreateElement("cleanupShellCommand")).AppendChild(doc.CreateTextNode(CleanupShellCommand)); doc.DocumentElement.AppendChild(doc.CreateElement("doCleanupAfterNumberOfRuns")).AppendChild(doc.CreateTextNode(DoCleanupAfterNumberOfRuns.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("hideOptions")).AppendChild(doc.CreateTextNode(hideOptions.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("hideCompilerWarnings")).AppendChild(doc.CreateTextNode(HideCompilerWarnings.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("inMemoryAsm")).AppendChild(doc.CreateTextNode(InMemoryAssembly.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("ConcurrencyControl")).AppendChild(doc.CreateTextNode(ConcurrencyControl.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("TragetFramework")).AppendChild(doc.CreateTextNode(TargetFramework)); doc.DocumentElement.AppendChild(doc.CreateElement("ConsoleEncoding")).AppendChild(doc.CreateTextNode(ConsoleEncoding)); doc.DocumentElement.AppendChild(doc.CreateElement("defaultRefAssemblies")).AppendChild(doc.CreateTextNode(DefaultRefAssemblies)); doc.DocumentElement.AppendChild(doc.CreateElement("useSurrogatepHostingProcess")).AppendChild(doc.CreateTextNode(useSurrogatepHostingProcess.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("openEndDirectiveSyntax")).AppendChild(doc.CreateTextNode(openEndDirectiveSyntax.ToString())); doc.DocumentElement.AppendChild(doc.CreateElement("Precompiler")).AppendChild(doc.CreateTextNode(Precompiler)); doc.DocumentElement.AppendChild(doc.CreateElement("CustomHashing")).AppendChild(doc.CreateTextNode(CustomHashing.ToString())); doc.Save(fileName); } catch { } }