internal string VisualizeIL(CompilationTestData.MethodData methodData, bool realIL, string sequencePoints = null, string source = null) { Dictionary <int, string> markers = null; if (sequencePoints != null) { var actualPdbXml = PdbToXmlConverter.ToXml( pdbStream: new MemoryStream(EmittedAssemblyPdb.ToArray()), peStream: new MemoryStream(EmittedAssemblyData.ToArray()), options: PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError | PdbToXmlOptions.ExcludeDocuments | PdbToXmlOptions.ExcludeCustomDebugInformation | PdbToXmlOptions.ExcludeScopes, methodName: sequencePoints); markers = ILValidation.GetSequencePointMarkers(actualPdbXml, source); } if (!realIL) { return(ILBuilderVisualizer.ILBuilderToString(methodData.ILBuilder, markers: markers)); } if (_lazyModuleSymbol == null) { var targetReference = LoadTestEmittedExecutableForSymbolValidation(EmittedAssemblyData, _compilation.Options.OutputKind, display: _compilation.AssemblyName); _lazyModuleSymbol = GetSymbolFromMetadata(targetReference, MetadataImportOptions.All); } return(_lazyModuleSymbol != null?_visualizeRealIL(_lazyModuleSymbol, methodData, markers) : null); }
internal string VisualizeIL(CompilationTestData.MethodData methodData, bool realIL, string sequencePoints = null) { Dictionary <int, string> markers = null; if (sequencePoints != null) { var actualPdbXml = PdbToXmlConverter.ToXml( pdbStream: new MemoryStream(EmittedAssemblyPdb.ToArray()), peStream: new MemoryStream(EmittedAssemblyData.ToArray()), options: PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError | PdbToXmlOptions.ExcludeDocuments | PdbToXmlOptions.ExcludeCustomDebugInformation | PdbToXmlOptions.ExcludeScopes, methodName: sequencePoints); markers = PdbValidation.GetMarkers(actualPdbXml); } if (!realIL) { return(ILBuilderVisualizer.ILBuilderToString(methodData.ILBuilder, markers: markers)); } if (_lazyModuleSymbol == null) { _lazyModuleSymbol = GetModuleSymbolForEmittedImage(EmittedAssemblyData, MetadataImportOptions.All); } return(_lazyModuleSymbol != null?_test.VisualizeRealIL(_lazyModuleSymbol, methodData, markers) : null); }
internal static string GetPdbXml( Compilation compilation, IMethodSymbol debugEntryPoint = null, PdbToXmlOptions options = 0, string qualifiedMethodName = "", bool portable = false) { string actual = null; using (var exebits = new MemoryStream()) { using (var pdbbits = new MemoryStream()) { var result = compilation.Emit( exebits, pdbbits, debugEntryPoint: debugEntryPoint, options: EmitOptions.Default.WithDebugInformationFormat(portable ? DebugInformationFormat.PortablePdb : DebugInformationFormat.Pdb)); result.Diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).Verify(); pdbbits.Position = 0; exebits.Position = 0; options |= PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError; actual = PdbToXmlConverter.ToXml(pdbbits, exebits, options, methodName: qualifiedMethodName); ValidateDebugDirectory(exebits, portable ? pdbbits : null, compilation.AssemblyName + ".pdb", compilation.IsEmitDeterministic); } } return(actual); }
internal static string GetPdbXml( Compilation compilation, PdbToXmlOptions options = 0, string qualifiedMethodName = "", bool portable = false) { string actual = null; using (var exebits = new MemoryStream()) { using (var pdbbits = new MemoryStream()) { compilation.Emit( exebits, pdbbits, options: EmitOptions.Default.WithDebugInformationFormat(portable ? DebugInformationFormat.PortablePdb : DebugInformationFormat.Pdb)); pdbbits.Position = 0; exebits.Position = 0; options |= PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError; actual = PdbToXmlConverter.ToXml(pdbbits, exebits, options, methodName: qualifiedMethodName); } ValidateDebugDirectory(exebits, compilation.AssemblyName + ".pdb", portable); } return(actual); }
private static void VerifyPdbMatchesExpectedXml( Stream peStream, Stream pdbStream, string qualifiedMethodName, PdbToXmlOptions pdbToXmlOptions, string expectedPdb, int expectedValueSourceLine, string expectedValueSourcePath, bool expectedIsXmlLiteral, bool isPortable) { peStream.Position = 0; pdbStream.Position = 0; var actualPdb = XElement.Parse(PdbToXmlConverter.ToXml(pdbStream, peStream, pdbToXmlOptions, methodName: qualifiedMethodName)).ToString(); var(actual, expected) = AdjustToPdbFormat(actualPdb, expectedPdb, actualIsPortable: isPortable, actualIsConverted: false); AssertEx.AssertLinesEqual( expected, actual, $"PDB format: {(isPortable ? "Portable" : "Windows")}{Environment.NewLine}", expectedValueSourcePath, expectedValueSourceLine, escapeQuotes: !expectedIsXmlLiteral); }
private static void VerifyPdb(Stream pdbStream, Stream peStream, string expectedXml, string message) { pdbStream.Position = 0; peStream.Position = 0; var actualXml = PdbToXmlConverter.ToXml(pdbStream, peStream, Options); AssertEx.AssertLinesEqual(expectedXml, actualXml, message); }
private static void VerifyPdb(Stream pdbStream, Stream peStream, string expectedXml, string message) { pdbStream.Position = 0; peStream.Position = 0; var actualXml = PdbToXmlConverter.ToXml(pdbStream, peStream, PdbToXmlOptions.IncludeSourceServerInformation | PdbToXmlOptions.ResolveTokens); AssertEx.AssertLinesEqual(expectedXml, actualXml, message); }
internal string VisualizeIL(CompilationTestData.MethodData methodData, bool realIL, string sequencePoints = null, string source = null) { Dictionary <int, string> markers = null; if (sequencePoints != null) { if (EmittedAssemblyPdb == null) { throw new InvalidOperationException($"{nameof(EmittedAssemblyPdb)} is not set"); } if (EmittedAssemblyData == null) { throw new InvalidOperationException($"{nameof(EmittedAssemblyData)} is not set"); } var actualPdbXml = PdbToXmlConverter.ToXml( pdbStream: new MemoryStream(EmittedAssemblyPdb.ToArray()), peStream: new MemoryStream(EmittedAssemblyData.ToArray()), options: PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError | PdbToXmlOptions.ExcludeDocuments | PdbToXmlOptions.ExcludeCustomDebugInformation | PdbToXmlOptions.ExcludeScopes, methodName: sequencePoints); if (actualPdbXml.StartsWith("<error>")) { throw new Exception($"Failed to extract PDB information for method '{sequencePoints}'. PdbToXmlConverter returned:\r\n{actualPdbXml}"); } markers = ILValidation.GetSequencePointMarkers(actualPdbXml, source); } if (!realIL) { return(ILBuilderVisualizer.ILBuilderToString(methodData.ILBuilder, markers: markers)); } if (_lazyModuleSymbol == null) { var targetReference = LoadTestEmittedExecutableForSymbolValidation(EmittedAssemblyData, _compilation.Options.OutputKind, display: _compilation.AssemblyName); _lazyModuleSymbol = GetSymbolFromMetadata(targetReference, MetadataImportOptions.All); } if (_lazyModuleSymbol != null) { if (_visualizeRealIL == null) { throw new InvalidOperationException("IL visualization function is not set"); } return(_visualizeRealIL(_lazyModuleSymbol, methodData, markers, _testData.Module.GetMethodBody(methodData.Method).AreLocalsZeroed)); } return(null); }
public static void GenXmlFromPdb(string exePath, string pdbPath, string outPath, PdbToXmlOptions options) { using var peStream = new FileStream(exePath, FileMode.Open, FileAccess.Read); using var pdbStream = new FileStream(pdbPath, FileMode.Open, FileAccess.Read); using var dstFileStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite); using var sw = new StreamWriter(dstFileStream, Encoding.UTF8); PdbToXmlConverter.ToXml(sw, pdbStream, peStream, options); }
public static string GenXmlFromPdb(string exePath, string pdbPath) { using (var peStream = new FileStream(exePath, FileMode.Open, FileAccess.Read)) using (var pdbStream = new FileStream(pdbPath, FileMode.Open, FileAccess.Read)) using (var ms = new MemoryStream()) using (var sw = new StreamWriter(ms, Encoding.UTF8)) { PdbToXmlConverter.ToXml(sw, pdbStream, peStream, PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.IncludeTokens); return(Encoding.UTF8.GetString(ms.ToArray())); } }
public static void VerifyWindowsMatchesExpected(TestResource windows, string expectedXml) { var windowsPEStream = new MemoryStream(windows.PE); var windowsPdbStream = new MemoryStream(windows.Pdb); var actualXml = PdbToXmlConverter.ToXml(windowsPdbStream, windowsPEStream, Options); var adjustedExpectedXml = AdjustForInherentDifferences(expectedXml); var adjustedActualXml = AdjustForInherentDifferences(actualXml); AssertEx.AssertLinesEqual(adjustedExpectedXml, adjustedActualXml, "Comparing Windows PDB with expected XML"); }
public static void VerifyPortableReadNativelyMatchesExpected(TestResource portable, string expectedXml) { var portablePEStream = new MemoryStream(portable.PE); var portablePdbStream = new MemoryStream(portable.Pdb); var actualXml = PdbToXmlConverter.ToXml(portablePdbStream, portablePEStream, Options | PdbToXmlOptions.UseNativeReader); var adjustedActualXml = RemoveElementsNotSupportedByNativeReader(actualXml); var adjustedExpectedXml = RemoveElementsNotSupportedByNativeReader(expectedXml); AssertEx.AssertLinesEqual(adjustedExpectedXml, adjustedActualXml, "Comparing Portable PDB read via native reader with expected XML"); }
public static void VerifyPortablePdb( TestResource portable, string expectedXml, PdbToXmlOptions options = Options) { var portablePEStream = new MemoryStream(portable.PE); var portablePdbStream = new MemoryStream(portable.Pdb); var actualXml = PdbToXmlConverter.ToXml(portablePdbStream, portablePEStream, options); AssertEx.AssertLinesEqual(expectedXml, actualXml, "Comparing Portable PDB with expected XML"); }
public static void GenXmlFromPdb(string exePath, string pdbPath, string outPath, PdbToXmlOptions options) { using (var exebits = new FileStream(exePath, FileMode.Open, FileAccess.Read)) { using (var pdbbits = new FileStream(pdbPath, FileMode.Open, FileAccess.Read)) { using (var sw = new StreamWriter(outPath, append: false, encoding: Encoding.UTF8)) { PdbToXmlConverter.ToXml(sw, pdbbits, exebits, options); } } } }
internal static string GetPdbXml( Compilation compilation, IEnumerable <EmbeddedText> embeddedTexts = null, IMethodSymbol debugEntryPoint = null, PdbValidationOptions options = PdbValidationOptions.Default, string qualifiedMethodName = "", bool portable = false) { var peStream = new MemoryStream(); var pdbStream = new MemoryStream(); EmitWithPdb(peStream, pdbStream, compilation, debugEntryPoint, embeddedTexts, portable); pdbStream.Position = 0; peStream.Position = 0; return(PdbToXmlConverter.ToXml(pdbStream, peStream, options.ToPdbToXmlOptions(), methodName: qualifiedMethodName)); }
public static string GetPdbXml(Compilation compilation, string methodName = "") { string actual = null; using (var exebits = new MemoryStream()) { using (var pdbbits = new MemoryStream()) { compilation.Emit(exebits, null, "DontCare", pdbbits, null); pdbbits.Position = 0; exebits.Position = 0; actual = PdbToXmlConverter.ToXml(pdbbits, exebits, PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError, methodName: methodName); } } return(actual); }
private void TestGeneratePdb([CallerMemberName] string testName = null) { const PdbToXmlOptions options = PdbToXmlOptions.IncludeEmbeddedSources | PdbToXmlOptions.ThrowOnError | PdbToXmlOptions.IncludeTokens | PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.IncludeMethodSpans; string xmlFile = Path.Combine(TestCasePath, testName + ".xml"); string xmlContent = File.ReadAllText(xmlFile); XDocument document = XDocument.Parse(xmlContent); var files = document.Descendants("file").ToDictionary(f => f.Attribute("name").Value, f => f.Value); Tester.CompileCSharpWithPdb(Path.Combine(TestCasePath, testName + ".expected"), files); string peFileName = Path.Combine(TestCasePath, testName + ".expected.dll"); string pdbFileName = Path.Combine(TestCasePath, testName + ".expected.pdb"); var moduleDefinition = new PEFile(peFileName); var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage); var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings()); using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, testName + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite)) { pdbStream.SetLength(0); PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream, noLogo: true); pdbStream.Position = 0; using (Stream peStream = File.OpenRead(peFileName)) using (Stream expectedPdbStream = File.OpenRead(pdbFileName)) { using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(pdbFileName, ".xml"), false, Encoding.UTF8)) { PdbToXmlConverter.ToXml(writer, expectedPdbStream, peStream, options); } peStream.Position = 0; using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(xmlFile, ".generated.xml"), false, Encoding.UTF8)) { PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options); } } } string expectedFileName = Path.ChangeExtension(xmlFile, ".expected.xml"); ProcessXmlFile(expectedFileName); string generatedFileName = Path.ChangeExtension(xmlFile, ".generated.xml"); ProcessXmlFile(generatedFileName); Assert.AreEqual(Normalize(expectedFileName), Normalize(generatedFileName)); }
internal static string GetPdbXml(Compilation compilation, string qualifiedMethodName = "") { string actual = null; using (var exebits = new MemoryStream()) { using (var pdbbits = new MemoryStream()) { compilation.Emit(exebits, pdbbits); pdbbits.Position = 0; exebits.Position = 0; actual = PdbToXmlConverter.ToXml(pdbbits, exebits, PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError, methodName: qualifiedMethodName); } ValidateDebugDirectory(exebits, compilation.AssemblyName + ".pdb"); } return(actual); }
private static void VerifyConvertedPdbMatchesExpectedXml( Stream peStreamOriginal, Stream pdbStreamOriginal, string qualifiedMethodName, string expectedPdb, PdbToXmlOptions pdbToXmlOptions, bool expectedIsXmlLiteral, bool originalIsPortable) { var pdbStreamConverted = new MemoryStream(); var converter = new PdbConverter(diagnostic => Assert.True(false, diagnostic.ToString())); peStreamOriginal.Position = 0; pdbStreamOriginal.Position = 0; if (originalIsPortable) { converter.ConvertPortableToWindows(peStreamOriginal, pdbStreamOriginal, pdbStreamConverted); } else { converter.ConvertWindowsToPortable(peStreamOriginal, pdbStreamOriginal, pdbStreamConverted); } pdbStreamConverted.Position = 0; peStreamOriginal.Position = 0; var actualConverted = AdjustForConversionArtifacts(XElement.Parse(PdbToXmlConverter.ToXml(pdbStreamConverted, peStreamOriginal, pdbToXmlOptions, methodName: qualifiedMethodName)).ToString()); var adjustedExpected = AdjustForConversionArtifacts(expectedPdb); var(actual, expected) = AdjustToPdbFormat(actualConverted, adjustedExpected, actualIsPortable: !originalIsPortable, actualIsConverted: true); AssertEx.AssertLinesEqual( expected, actual, $"PDB format: {(originalIsPortable ? "Windows" : "Portable")} converted from {(originalIsPortable ? "Portable" : "Windows")}{Environment.NewLine}", expectedValueSourcePath: null, expectedValueSourceLine: 0, escapeQuotes: !expectedIsXmlLiteral); }
internal static void Execute(IEnumerable <AssemblyTreeNode> nodes) { var highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml"); var options = PdbToXmlOptions.IncludeEmbeddedSources | PdbToXmlOptions.IncludeMethodSpans | PdbToXmlOptions.IncludeTokens; Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task <AvalonEditTextOutput> .Factory.StartNew(() => { AvalonEditTextOutput output = new AvalonEditTextOutput(); var writer = new TextOutputWriter(output); foreach (var node in nodes) { string pdbFileName = Path.ChangeExtension(node.LoadedAssembly.FileName, ".pdb"); if (!File.Exists(pdbFileName)) { continue; } using (var pdbStream = File.OpenRead(pdbFileName)) using (var peStream = File.OpenRead(node.LoadedAssembly.FileName)) PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options); } return(output); }, ct)).Then(output => Docking.DockWorkspace.Instance.ShowNodes(output, null, highlighting)).HandleExceptions(); }
private string VisualizeIL(CompilationTestData.MethodData methodData, bool realIL, string sequencePoints, bool useRefEmitter) { Dictionary <int, string> markers = null; if (sequencePoints != null) { var actualPdbXml = PdbToXmlConverter.ToXml( pdbStream: new MemoryStream(EmittedAssemblyPdb.ToArray()), peStream: new MemoryStream(EmittedAssemblyData.ToArray()), options: PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError, methodName: sequencePoints); markers = GetMarkers(actualPdbXml); } if (!realIL) { return(ILBuilderVisualizer.ILBuilderToString(methodData.ILBuilder, markers: markers)); } var module = this.GetModuleSymbolForEmittedImage(); return(module != null?_test.VisualizeRealIL(module, methodData, markers) : null); }
public static unsafe CompilationDiff Create( FileInfo originalBinaryPath, CompilationOptionsReader optionsReader, Compilation producedCompilation, IMethodSymbol?debugEntryPoint, ILogger logger, Options options) { using var rebuildPeStream = new MemoryStream(); // By default the Roslyn command line adds a resource that we need to replicate here. using var win32ResourceStream = producedCompilation.CreateDefaultWin32Resources( versionResource: true, noManifest: producedCompilation.Options.OutputKind == OutputKind.DynamicallyLinkedLibrary, manifestContents: null, iconInIcoFormat: null); var sourceLink = optionsReader.GetSourceLinkUTF8(); var embeddedTexts = producedCompilation.SyntaxTrees .Select(st => (path: st.FilePath, text: st.GetText())) .Where(pair => pair.text.CanBeEmbedded) .Select(pair => EmbeddedText.FromSource(pair.path, pair.text)) .ToImmutableArray(); var emitResult = producedCompilation.Emit( peStream: rebuildPeStream, pdbStream: null, xmlDocumentationStream: null, win32Resources: win32ResourceStream, manifestResources: optionsReader.GetManifestResources(), options: new EmitOptions( debugInformationFormat: DebugInformationFormat.Embedded, highEntropyVirtualAddressSpace: true), debugEntryPoint: debugEntryPoint, metadataPEStream: null, pdbOptionsBlobReader: optionsReader.GetMetadataCompilationOptionsBlobReader(), sourceLinkStream: sourceLink != null ? new MemoryStream(sourceLink) : null, embeddedTexts: embeddedTexts, cancellationToken: CancellationToken.None); if (!emitResult.Success) { using var diagsScope = logger.BeginScope($"Diagnostics"); foreach (var diag in emitResult.Diagnostics) { logger.LogError(diag.ToString()); } return(new CompilationDiff(emitResult.Diagnostics, originalBinaryPath.FullName)); } else { var originalBytes = File.ReadAllBytes(originalBinaryPath.FullName); var rebuildBytes = rebuildPeStream.ToArray(); var bytesEqual = originalBytes.SequenceEqual(rebuildBytes); if (!bytesEqual) { logger.LogError($"Rebuild of {originalBinaryPath.Name} was not equivalent to the original."); if (!options.Debug) { logger.LogInformation("Pass the --debug argument and re-run to write the visualization of the original and rebuild to disk."); } else { logger.LogInformation("Creating a diff..."); var debugPath = options.DebugPath; logger.LogInformation($@"Writing diffs to ""{Path.GetFullPath(debugPath)}"""); var assemblyName = Path.GetFileNameWithoutExtension(originalBinaryPath.Name); var assemblyDebugPath = Path.Combine(debugPath, assemblyName); var originalPath = Path.Combine(assemblyDebugPath, "original"); var rebuildPath = Path.Combine(assemblyDebugPath, "rebuild"); var sourcesPath = Path.Combine(assemblyDebugPath, "sources"); Directory.CreateDirectory(originalPath); Directory.CreateDirectory(rebuildPath); Directory.CreateDirectory(sourcesPath); // TODO: output source files should include the entire relative path instead of just the file name. foreach (var tree in producedCompilation.SyntaxTrees) { var sourceFilePath = Path.Combine(sourcesPath, Path.GetFileName(tree.FilePath)); using var file = File.OpenWrite(sourceFilePath); var writer = new StreamWriter(file); tree.GetText().Write(writer); writer.Flush(); } var originalAssemblyPath = Path.Combine(originalPath, originalBinaryPath.Name); File.WriteAllBytes(originalAssemblyPath, originalBytes); var rebuildAssemblyPath = Path.Combine(rebuildPath, originalBinaryPath.Name); File.WriteAllBytes(rebuildAssemblyPath, rebuildBytes); var originalPeMdvPath = Path.Combine(originalPath, assemblyName + ".pe.mdv"); var originalPdbMdvPath = Path.Combine(originalPath, assemblyName + ".pdb.mdv"); writeVisualization(originalPeMdvPath, optionsReader.PeReader.GetMetadataReader()); writeVisualization(originalPdbMdvPath, optionsReader.PdbReader); var originalPdbXmlPath = Path.Combine(originalPath, assemblyName + ".pdb.xml"); using var originalPdbXml = File.Create(originalPdbXmlPath); var rebuildPdbXmlPath = Path.Combine(rebuildPath, assemblyName + ".pdb.xml"); var pdbToXmlOptions = PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.ThrowOnError | PdbToXmlOptions.ExcludeScopes | PdbToXmlOptions.IncludeSourceServerInformation | PdbToXmlOptions.IncludeEmbeddedSources | PdbToXmlOptions.IncludeTokens | PdbToXmlOptions.IncludeMethodSpans; PdbToXmlConverter.ToXml( new StreamWriter(originalPdbXml), pdbStream: new UnmanagedMemoryStream(optionsReader.PdbReader.MetadataPointer, optionsReader.PdbReader.MetadataLength), peStream: new MemoryStream(originalBytes), options: pdbToXmlOptions, methodName: null); var rebuildPeMdvPath = Path.Combine(rebuildPath, assemblyName + ".pe.mdv"); var rebuildPdbMdvPath = Path.Combine(rebuildPath, assemblyName + ".pdb.mdv"); fixed(byte *ptr = rebuildBytes) { using var rebuildPeReader = new PEReader(ptr, rebuildBytes.Length); writeVisualization(rebuildPeMdvPath, rebuildPeReader.GetMetadataReader()); if (rebuildPeReader.TryOpenAssociatedPortablePdb( rebuildAssemblyPath, path => File.Exists(path) ? File.OpenRead(path) : null, out var provider, out _) && provider is { })