// Create an IL snippet that matches the given range (startLine to endLine, inclusive) in the // given source file. // Although we could compute the lines collection from the other 3 parameters, we pass it in for perf reasons // since we already have it available. public InlineILSnippet(string pathSourceFile, int idxStartLine, int idxEndLine, StringCollection lines) { Sourcefile = pathSourceFile; StartLine = idxStartLine; EndLine = idxEndLine; // This assert would be false if the incoming lines collection has been preprocessed (Eg, if the caller // already inject .line directives to map back to the source). Debug.Assert(idxEndLine - idxStartLine + 1 == lines.Count); // Marshal into an array. Since we're already copying, we'll also inject the sequence point info. Lines = new string[(lines.Count * 2) + 1]; Lines[0] = string.Format("// Snippet from {0}:{1}", pathSourceFile, idxStartLine); for (var i = 0; i < lines.Count; i++) { var idxSourceLine = idxStartLine + i; // ILAsm only lets us add sequence points to statements. var sequenceMarker = ILDocument.IsStatement(lines[i]) ? ILDocument.CreateILSequenceMarker(pathSourceFile, idxSourceLine, idxSourceLine, 1, lines[i].Length + 1) : "// skip sequence marker"; Lines[2 * i + 1] = sequenceMarker; Lines[2 * i + 2] = lines[i]; } }
// Create an IL snippet that matches the given range (startLine to endLine, inclusive) in the // given source file. // Although we could compute the lines collection from the other 3 parameters, we pass it in for perf reasons // since we already have it available. public InlineILSnippet(string pathSourceFile, int idxStartLine, int idxEndLine, StringCollection lines) { m_pathSourcefile = pathSourceFile; m_idxStartLine = idxStartLine; m_idxEndLine = idxEndLine; // This assert would be false if the incoming lines collection has been preprocessed (Eg, if the caller // already inject .line directives to map back to the source). Debug.Assert(idxEndLine - idxStartLine + 1 == lines.Count); // Marshal into an array. Since we're already copying, we'll also inject the sequence point info. m_lines = new string[lines.Count * 2]; for (int i = 0; i < lines.Count; i++) { int idxSourceLine = idxStartLine + i; string sequenceMarker; // ILAsm only lets us add sequence points to statements. if (ILDocument.IsStatement(lines[i])) { sequenceMarker = ILDocument.GetILSequenceMarker( pathSourceFile, idxSourceLine, idxSourceLine, 1, lines[i].Length + 1); } else { sequenceMarker = "// skip sequence marker"; } m_lines[2 * i] = sequenceMarker; m_lines[2 * i + 1] = lines[i]; } }
// Searches the given source file for inline IL snippets. static List<InlineILSnippet> FindInlineILSnippets(ILDocument doc) { var snippets = new List<InlineILSnippet>(); var sourceFiles = doc.GetSourceFiles(); foreach (var f in sourceFiles) { var lang = GetLanguageForFile(f); // An IL snippet begins at the first line prefixed with the startMarker // and goes until the first endMarker after that. var stStartMarker = lang.StartMarker.ToLower(); var stEndMarker = lang.EndMarker.ToLower(); TextReader reader = new StreamReader(new FileStream(f, FileMode.Open)); StringCollection list = null; var idxStartLine = 0; // 0 means we're not tracking a snippet. var idxLine = 0; // current line into source file. string line; while ((line = reader.ReadLine()) != null) { var lineLowercase = line.ToLower(); idxLine++; if (idxStartLine != 0) { if (lineLowercase == stEndMarker) { // We found the end of the IL snippet. var idxEndLine = idxLine - 1; // end line was the previous line var snippet = new InlineILSnippet(f, idxStartLine, idxEndLine, list); snippets.Add(snippet); idxStartLine = 0; // reset tracking the IL snippet. list = null; } else { list.Add(line); } } if (!lineLowercase.StartsWith(stStartMarker)) continue; // We found the start of an IL snippet. The actual snippet will start at the next line. list = new StringCollection(); idxStartLine = idxLine + 1; } // If we got to the end of the file and are still tracking, then we have an unterminated inline IL segment. if (idxStartLine != 0) { throw new ArgumentException(string.Format("Unterminated Inline IL segment in file '{0}' starting with '{1}' at line '{2}'. Expecting to find closing '{3}'", f, stStartMarker, idxStartLine, stEndMarker)); } } return snippets; }
static int MainWorker(ILanguage lang, string pathSourceFile, string pathFinalOut) { // Some compilers (like VBC) get confused if the output extension isn't .exe. string pathTempOut = Path.ChangeExtension(Path.GetTempFileName(), ".exe"); // First invoke the high-level compiler WriteMarker(); Console.WriteLine("Compiling input file '" + pathSourceFile + "' with '" + lang.PrettyName + "' to output '" + pathFinalOut + "'"); Console.WriteLine("Compiling to temporary file:" + pathTempOut); lang.Compile(pathSourceFile, pathTempOut); // Now, IL-disassemble it. WriteMarker(); ILDocument doc = new ILDocument(pathTempOut); InlineILSnippet[] snippets = FindInlineILSnippets(lang, pathSourceFile); // Reinject the snippets. foreach (InlineILSnippet s in snippets) { Console.WriteLine("Found:" + s); foreach (string x in s.Lines) { Console.WriteLine(" :" + x); } doc.InsertSnippet(s); } // Now re-emit the new IL. WriteMarker(); doc.EmitToFile(pathFinalOut); // Since they're doing direct IL manipulation, we really should run peverify on the output. WriteMarker(); Console.WriteLine("runnning PEVerify on '{0}'.", pathFinalOut); Util.Run(SdkDir + @"\bin\PEverify.exe", pathFinalOut); Console.WriteLine("PEVerify passed!"); return(0); } // end main
// Main entry point. static int Main(string[] args) { string outputType = null; var showHelp = false; string outputFile = null; string inputFile = null; var verify = false; var verbose = false; string keyFile = null; var o = new OptionSet { {"dll", v => outputType = "DLL"}, {"exe", v => outputType = "EXE"}, {"k|key=", v => keyFile = v}, {"c|verify", v => verify = v != null }, {"v|verbose", v => verbose = v != null }, {"i|input=", v => inputFile = v}, {"o|output=", v => outputFile = v}, {"h|?|help", "show this help message", v => showHelp = v != null}, }; var extra = o.Parse(args); if (showHelp) { ShowHelp(o); return 0; } if (extra.Count != 0) { ShowHelp(o); return 1; } InitSdkDir(); try { var doc = new ILDocument(inputFile); var snippets = FindInlineILSnippets(doc); // Re-inject the snippets. foreach (var s in snippets) { if (verbose) { Console.WriteLine("Found:" + s); foreach (var x in s.Lines) Console.WriteLine(" :" + x); } s.InsertLocation = doc.FindSnippetLocation(s); } snippets.Sort((x, y) => y.InsertLocation - x.InsertLocation); foreach (var s in snippets) doc.Lines = Util.InsertArrayIntoArray(doc.Lines, s.Lines, s.InsertLocation); // Now re-emit the new IL. doc.EmitToFile(outputFile, outputType, keyFile, verbose); // Since they're doing direct IL manipulation, we really should run peverify on the output. if (verify) { Console.WriteLine("Running PEVerify on '{0}'.", outputFile); Util.Run(Path.Combine(SdkDir + "PEverify.exe"), outputFile); Console.WriteLine("PEVerify passed!"); } } catch (Exception e) { Console.WriteLine("Error:" + e.Message); return 1; } return 0; }
// Searches the given source file for inline IL snippets. static List <InlineILSnippet> FindInlineILSnippets(ILDocument doc) { var snippets = new List <InlineILSnippet>(); var sourceFiles = doc.GetSourceFiles(); foreach (var f in sourceFiles) { var lang = GetLanguageForFile(f); // An IL snippet begins at the first line prefixed with the startMarker // and goes until the first endMarker after that. var stStartMarker = lang.StartMarker.ToLower(); var stEndMarker = lang.EndMarker.ToLower(); TextReader reader = new StreamReader(new FileStream(f, FileMode.Open)); StringCollection list = null; var idxStartLine = 0; // 0 means we're not tracking a snippet. var idxLine = 0; // current line into source file. string line; while ((line = reader.ReadLine()) != null) { var lineLowercase = line.ToLower(); idxLine++; if (idxStartLine != 0) { if (lineLowercase == stEndMarker) { // We found the end of the IL snippet. var idxEndLine = idxLine - 1; // end line was the previous line var snippet = new InlineILSnippet(f, idxStartLine, idxEndLine, list); snippets.Add(snippet); idxStartLine = 0; // reset tracking the IL snippet. list = null; } else { list.Add(line); } } if (!lineLowercase.StartsWith(stStartMarker)) { continue; } // We found the start of an IL snippet. The actual snippet will start at the next line. list = new StringCollection(); idxStartLine = idxLine + 1; } // If we got to the end of the file and are still tracking, then we have an unterminated inline IL segment. if (idxStartLine != 0) { throw new ArgumentException(string.Format("Unterminated Inline IL segment in file '{0}' starting with '{1}' at line '{2}'. Expecting to find closing '{3}'", f, stStartMarker, idxStartLine, stEndMarker)); } } return(snippets); }
// Main entry point. static int Main(string[] args) { string outputType = null; var showHelp = false; string outputFile = null; string inputFile = null; var verify = false; var verbose = false; string keyFile = null; var o = new OptionSet { { "dll", v => outputType = "DLL" }, { "exe", v => outputType = "EXE" }, { "k|key=", v => keyFile = v }, { "c|verify", v => verify = v != null }, { "v|verbose", v => verbose = v != null }, { "i|input=", v => inputFile = v }, { "o|output=", v => outputFile = v }, { "h|?|help", "show this help message", v => showHelp = v != null }, }; var extra = o.Parse(args); if (showHelp) { ShowHelp(o); return(0); } if (extra.Count != 0) { ShowHelp(o); return(1); } InitSdkDir(); try { var doc = new ILDocument(inputFile); var snippets = FindInlineILSnippets(doc); // Re-inject the snippets. foreach (var s in snippets) { if (verbose) { Console.WriteLine("Found:" + s); foreach (var x in s.Lines) { Console.WriteLine(" :" + x); } } s.InsertLocation = doc.FindSnippetLocation(s); } snippets.Sort((x, y) => y.InsertLocation - x.InsertLocation); foreach (var s in snippets) { doc.Lines = Util.InsertArrayIntoArray(doc.Lines, s.Lines, s.InsertLocation); } // Now re-emit the new IL. doc.EmitToFile(outputFile, outputType, keyFile, verbose); // Since they're doing direct IL manipulation, we really should run peverify on the output. if (verify) { Console.WriteLine("Running PEVerify on '{0}'.", outputFile); Util.Run(Path.Combine(SdkDir + "PEverify.exe"), outputFile); Console.WriteLine("PEVerify passed!"); } } catch (Exception e) { Console.WriteLine("Error:" + e.Message); return(1); } return(0); }