Пример #1
0
        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);
        }
Пример #2
0
            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);
            }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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");
        }
Пример #14
0
 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);
             }
         }
     }
 }
Пример #15
0
        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));
        }
Пример #16
0
        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));
        }
Пример #18
0
        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);
        }
Пример #19
0
        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);
        }
Пример #20
0
        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);
            }
Пример #22
0
        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 { })