Esempio n. 1
0
        /// <summary>
        /// Given dllInputPath determine if it is portable.  If so convert it *\WindowsPdb\*.pdb and update 'pdbInputPath' to
        /// point to this converted file.
        /// Returns true if the conversion was done (that is the original file was protable).
        /// 'dllInputPath' is the DLL that goes along with 'pdbInputPath'.
        /// </summary>
        private static bool ConvertFromPortableIfNecessary(string dllInputPath, ref string pdbInputPath)
        {
            string originalPdbInputPath = pdbInputPath;

            using (Stream pdbReadStream = File.OpenRead(pdbInputPath))
            {
                // If the input is not portable, there is nothing to do, and we can early out.
                if (!PdbConverter.IsPortable(pdbReadStream))
                {
                    return(false);
                }

                // We want to keep the same file name for the PDB because it is used as a key when looking it up on a symbol server
                string pdbInputPathPdbDir = Path.Combine(Path.GetDirectoryName(pdbInputPath), "WindowsPdb");
                Directory.CreateDirectory(pdbInputPathPdbDir);
                pdbInputPath = Path.Combine(pdbInputPathPdbDir, Path.GetFileName(pdbInputPath));

                Trace.TraceInformation("PDB " + originalPdbInputPath + " is a portable PDB, converting it to " + pdbInputPath);
                PdbConverter converter = new PdbConverter(d => Trace.TraceError(d.ToString(CultureInfo.InvariantCulture)));
                using (Stream peStream = File.OpenRead(dllInputPath))
                    using (Stream pdbWriteStream = File.OpenWrite(pdbInputPath))
                    {
                        converter.ConvertPortableToWindows(peStream, pdbReadStream, pdbWriteStream, new PortablePdbConversionOptions(suppressSourceLinkConversion: true));
                    }
            }
            return(true);
        }
        public AssemblyDebugParser(Stream?peStream, Stream pdbStream)
        {
            Stream inputStream;

            if (!PdbConverter.IsPortable(pdbStream))
            {
                if (peStream == null)
                {
                    throw new ArgumentNullException(nameof(peStream), "Full PDB's require the PE file to be next to the PDB");
                }
                // Full PDB. convert to ppdb in memory
                _temporaryPdbStream = new MemoryStream();
                PdbConverter.Default.ConvertWindowsToPortable(peStream, pdbStream, _temporaryPdbStream);
                _temporaryPdbStream.Position = 0;
                inputStream = _temporaryPdbStream;
                _pdbType    = PdbType.Full;
            }
            else
            {
                inputStream = pdbStream;
                _pdbType    = PdbType.Portable;
            }

            _readerProvider = MetadataReaderProvider.FromPortablePdbStream(inputStream);
            _reader         = _readerProvider.GetMetadataReader();
        }
        public override bool Execute()
        {
            var parsedConversionOptions = new PortablePdbConversionOptions(SuppressSourceLinkConversion);

            var converter = new PdbConverter(
                d => Log.LogError(d.ToString(CultureInfo.InvariantCulture)));

            foreach (ITaskItem file in Files)
            {
                if (_cancel)
                {
                    break;
                }

                try
                {
                    ConvertPortableToWindows(file, converter, parsedConversionOptions);
                }
                catch (Exception e)
                {
                    Log.LogErrorFromException(e, true, true, file.ItemSpec);
                }
            }

            return(!Log.HasLoggedErrors);
        }
        public static void VerifyWindowsConvertedFromPortableMatchesExpected(TestResource portable, string expectedXml, PdbDiagnostic[]?expectedDiagnostics, PortablePdbConversionOptions?options, bool validateTimeIndifference)
        {
            var portablePEStream           = new MemoryStream(portable.PE);
            var portablePdbStream          = new MemoryStream(portable.Pdb);
            var portablePdbStream2         = new MemoryStream(portable.Pdb);
            var convertedWindowsPdbStream1 = new MemoryStream();
            var convertedWindowsPdbStream2 = new MemoryStream();
            var actualDiagnostics          = new List <PdbDiagnostic>();

            var converter = new PdbConverter(actualDiagnostics.Add);

            converter.ConvertPortableToWindows(portablePEStream, portablePdbStream, convertedWindowsPdbStream1, options);
            AssertEx.Equal(expectedDiagnostics ?? Array.Empty <PdbDiagnostic>(), actualDiagnostics, itemInspector: InspectDiagnostic);

            VerifyPdb(convertedWindowsPdbStream1, portablePEStream, expectedXml, "Comparing Windows PDB converted from Portable PDB with expected XML");

            portablePdbStream.Position          = 0;
            convertedWindowsPdbStream1.Position = 0;
            VerifyMatchingSignatures(portablePdbStream, convertedWindowsPdbStream1);

            // validate determinism:
            if (validateTimeIndifference)
            {
                Thread.Sleep(1000);
            }

            portablePEStream.Position  = 0;
            portablePdbStream.Position = 0;
            converter.ConvertPortableToWindows(portablePEStream, portablePdbStream, convertedWindowsPdbStream2, options);
            AssertEx.Equal(convertedWindowsPdbStream1.ToArray(), convertedWindowsPdbStream2.ToArray());
        }
Esempio n. 5
0
        /// <summary>
        /// Detect whether a given stream contains portable or Windows PDB format data
        /// and deserialize CCI PDB information from the given format.
        /// </summary>
        /// <param name="peFilePath">Path to IL PE module (needed only for portable PDB's)</param>
        /// <param name="standalonePdbPath">Path to standalone Windows PDB (not used for portable PDBs)</param>
        public static PdbInfo TryLoadFunctions(
            string peFilePath,
            string standalonePdbPath)
        {
            if (!string.IsNullOrEmpty(peFilePath))
            {
                using (Stream peStream = new FileStream(peFilePath, FileMode.Open, FileAccess.Read))
                    using (PEReader peReader = new PEReader(peStream))
                    {
                        MetadataReaderProvider pdbReaderProvider;
                        string pdbPath;
                        if (peReader.TryOpenAssociatedPortablePdb(peFilePath, File.OpenRead, out pdbReaderProvider, out pdbPath))
                        {
                            using (pdbReaderProvider)
                            {
                                // Load associated portable PDB
                                PdbWriterForCci cciWriter = new PdbWriterForCci();

                                new PdbConverter().ConvertPortableToWindows(
                                    peReader,
                                    pdbReaderProvider.GetMetadataReader(),
                                    cciWriter,
                                    PdbConversionOptions.SuppressSourceLinkConversion);

                                PdbInfo pdbInfo = new PdbInfo()
                                {
                                    Functions            = cciWriter.Functions,
                                    TokenToSourceMapping = cciWriter.TokenToSourceMapping,
                                    Age  = cciWriter.Age,
                                    Guid = cciWriter.Guid,
                                    // Ignored for portable PDBs to avoid bringing in a dependency on Newtonsoft.Json
                                    SourceServerData = null,
                                    SourceLinkData   = cciWriter.SourceLinkData
                                };

                                return(pdbInfo);
                            }
                        }
                    }
            }

            if (File.Exists(standalonePdbPath))
            {
                using (FileStream pdbInputStream = new FileStream(standalonePdbPath, FileMode.Open, FileAccess.Read))
                {
                    if (!PdbConverter.IsPortable(pdbInputStream))
                    {
                        // Load CCI data from Windows PDB
                        return(PdbFile.LoadFunctions(pdbInputStream));
                    }
                }
            }

            // Non-existent Windows PDB or mismatched portable PDB
            return(null);
        }
Esempio n. 6
0
        /// <summary>
        /// Convert the windows PDB winPdbInputPath to portablePdbOutputPath.
        /// 'dllInputPath' is the DLL that goes along with 'winPdbInputPath'.
        /// </summary>
        private static void ConvertFromWindowsPdb(string dllInputPath, string winPdbInputPath, string portablePdbOutputPath)
        {
            PdbConverter converter = new PdbConverter(d => Trace.TraceError(d.ToString(CultureInfo.InvariantCulture)));

            using (Stream peStream = File.OpenRead(dllInputPath))
                using (Stream pdbReadStream = File.OpenRead(winPdbInputPath))
                    using (Stream pdbWriteStream = File.OpenWrite(portablePdbOutputPath))
                    {
                        converter.ConvertWindowsToPortable(peStream, pdbReadStream, pdbWriteStream);
                    }
        }
        public AssemblyDebugParser(Stream?peStream, Stream pdbStream)
        {
            Stream inputStream;

            if (!PdbConverter.IsPortable(pdbStream))
            {
                if (peStream == null)
                {
                    throw new ArgumentNullException(nameof(peStream), "Full PDB's require the PE file to be next to the PDB");
                }

                if (!AppCompat.IsSupported(RuntimeFeature.DiaSymReader))
                {
                    throw new PlatformNotSupportedException("Windows PDB cannot be processed on this platform.");
                }

                // Full PDB. convert to ppdb in memory

                _pdbBytes          = pdbStream.ReadAllBytes();
                pdbStream.Position = 0;
                _peBytes           = peStream.ReadAllBytes();
                peStream.Position  = 0;

                _temporaryPdbStream = new MemoryStream();
                PdbConverter.Default.ConvertWindowsToPortable(peStream, pdbStream, _temporaryPdbStream);
                _temporaryPdbStream.Position = 0;
                peStream.Position            = 0;
                inputStream = _temporaryPdbStream;
                _pdbType    = PdbType.Full;
            }
            else
            {
                inputStream        = pdbStream;
                _pdbType           = PdbType.Portable;
                _pdbBytes          = pdbStream.ReadAllBytes();
                pdbStream.Position = 0;
            }



            _readerProvider = MetadataReaderProvider.FromPortablePdbStream(inputStream);
            _reader         = _readerProvider.GetMetadataReader();

            if (peStream != null)
            {
                _peReader    = new PEReader(peStream);
                _ownPeReader = true;
            }
        }
Esempio n. 8
0
        private static void VerifyPortableConvertedFromWindowsMatchesExpected(TestResource windows, string expectedMetadata)
        {
            var windowsPEStream            = new MemoryStream(windows.PE);
            var windowsPdbStream           = new MemoryStream(windows.Pdb);
            var convertedPortablePdbStream = new MemoryStream();

            var converter = new PdbConverter(d => Assert.False(true, d.ToString()));

            converter.ConvertWindowsToPortable(windowsPEStream, windowsPdbStream, convertedPortablePdbStream);

            convertedPortablePdbStream.Position = 0;
            VerifyPortablePdb(
                convertedPortablePdbStream,
                SelectAlternative(expectedMetadata, leftAlternative: false),
                "Comparing Portable PDB converted from Windows PDB with expected metadata");
        }
Esempio n. 9
0
        public static void VerifyWindowsConvertedFromPortableMatchesExpected(TestResource portable, string expectedXml, PdbDiagnostic[] expectedDiagnostics, PortablePdbConversionOptions options)
        {
            var portablePEStream          = new MemoryStream(portable.PE);
            var portablePdbStream         = new MemoryStream(portable.Pdb);
            var convertedWindowsPdbStream = new MemoryStream();
            var actualDiagnostics         = new List <PdbDiagnostic>();

            var converter = new PdbConverter(actualDiagnostics.Add);

            converter.ConvertPortableToWindows(portablePEStream, portablePdbStream, convertedWindowsPdbStream, options);

            AssertEx.Equal(expectedDiagnostics ?? Array.Empty <PdbDiagnostic>(), actualDiagnostics, itemInspector: InspectDiagnostic);

            VerifyPdb(convertedWindowsPdbStream, portablePEStream, expectedXml, "Comparing Windows PDB converted from Portable PDB with expected XML");

            portablePdbStream.Position         = 0;
            convertedWindowsPdbStream.Position = 0;
            VerifyMatchingSignatures(portablePdbStream, convertedWindowsPdbStream);
        }
Esempio n. 10
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);
        }
        public override bool Execute()
        {
            var parsedConversionOptions = PdbConversionOptions.Default;

            foreach (string option in ConversionOptions ?? Enumerable.Empty <string>())
            {
                PdbConversionOptions parsedOption;
                if (!Enum.TryParse(option, out parsedOption))
                {
                    throw new ArgumentException(
                              $"Passed conversion option '{option}'" +
                              $"is not a value of {nameof(PdbConversionOptions)}.");
                }
                parsedConversionOptions |= parsedOption;
            }

            var converter = new PdbConverter(
                d => Log.LogError(d.ToString(CultureInfo.InvariantCulture)));

            foreach (ITaskItem file in Files)
            {
                if (_cancel)
                {
                    break;
                }

                try
                {
                    ConvertPortableToWindows(file, converter, parsedConversionOptions);
                }
                catch (Exception e)
                {
                    Log.LogErrorFromException(e, true, true, file.ItemSpec);
                }
            }

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            var parsedConversionOptions = PdbConversionOptions.Default;

            foreach (string option in ConversionOptions ?? Enumerable.Empty <string>())
            {
                PdbConversionOptions parsedOption;
                if (!Enum.TryParse(option, out parsedOption))
                {
                    throw new ArgumentException(
                              $"Passed conversion option '{option}'" +
                              $"is not a value of {nameof(PdbConversionOptions)}.");
                }
                parsedConversionOptions |= parsedOption;
            }

            var converter = new PdbConverter(
                d => Log.LogError(d.ToString(CultureInfo.InvariantCulture)));

            foreach (ITaskItem file in Files)
            {
                string pdbPath = file.GetMetadata(PdbPathMetadata);

                if (string.IsNullOrEmpty(pdbPath))
                {
                    Log.LogError($"No '{PdbPathMetadata}' metadata found for '{file}'.");
                    continue;
                }

                string targetPath = file.GetMetadata(TargetPathMetadata);

                if (string.IsNullOrEmpty(targetPath))
                {
                    Log.LogError($"No '{TargetPathMetadata}' metadata found for '{file}'.");
                    continue;
                }

                using (var sourcePdbStream = new FileStream(pdbPath, FileMode.Open, FileAccess.Read))
                {
                    if (PdbConverter.IsPortable(sourcePdbStream))
                    {
                        Log.LogMessage(
                            MessageImportance.Low,
                            $"Converting portable PDB '{file.ItemSpec}'...");

                        Directory.CreateDirectory(Path.GetDirectoryName(targetPath));

                        using (var peStream = new FileStream(file.ItemSpec, FileMode.Open, FileAccess.Read))
                            using (var peReader = new PEReader(peStream, PEStreamOptions.LeaveOpen))
                            {
                                if (peReader.ReadDebugDirectory().Length > 0)
                                {
                                    using (var outPdbStream = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
                                    {
                                        converter.ConvertPortableToWindows(
                                            peReader,
                                            sourcePdbStream,
                                            outPdbStream,
                                            parsedConversionOptions);
                                    }

                                    Log.LogMessage(
                                        MessageImportance.Normal,
                                        $"Portable PDB '{file.ItemSpec}' -> '{targetPath}'");
                                }
                                else
                                {
                                    Log.LogWarning($"'{file.ItemSpec}' {NoDebugDirectoryEntriesMessage}");
                                }
                            }
                    }
                    else
                    {
                        Log.LogMessage(
                            MessageImportance.Normal,
                            $"PDB is not portable, skipping: '{file.ItemSpec}'");
                    }
                }
            }

            return(!Log.HasLoggedErrors);
        }
        private void ConvertPortableToWindows(
            ITaskItem file,
            PdbConverter converter,
            PdbConversionOptions parsedConversionOptions)
        {
            string pdbPath = file.GetMetadata(PdbPathMetadata);

            if (string.IsNullOrEmpty(pdbPath))
            {
                Log.LogError($"No '{PdbPathMetadata}' metadata found for '{file}'.");
                return;
            }

            string targetPath = file.GetMetadata(TargetPathMetadata);

            if (string.IsNullOrEmpty(targetPath))
            {
                Log.LogError($"No '{TargetPathMetadata}' metadata found for '{file}'.");
                return;
            }

            using (var sourcePdbStream = new FileStream(pdbPath, FileMode.Open, FileAccess.Read))
            {
                if (PdbConverter.IsPortable(sourcePdbStream))
                {
                    Log.LogMessage(
                        MessageImportance.Low,
                        $"Converting portable PDB '{file.ItemSpec}'...");

                    Directory.CreateDirectory(Path.GetDirectoryName(targetPath));

                    using (var peStream = new FileStream(file.ItemSpec, FileMode.Open, FileAccess.Read))
                        using (var peReader = new PEReader(peStream, PEStreamOptions.LeaveOpen))
                        {
                            if (peReader.ReadDebugDirectory().Length > 0)
                            {
                                using (var outPdbStream = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
                                {
                                    converter.ConvertPortableToWindows(
                                        peReader,
                                        sourcePdbStream,
                                        outPdbStream,
                                        parsedConversionOptions);
                                }

                                Log.LogMessage(
                                    MessageImportance.Normal,
                                    $"Portable PDB '{file.ItemSpec}' -> '{targetPath}'");
                            }
                            else
                            {
                                Log.LogWarning($"'{file.ItemSpec}' {NoDebugDirectoryEntriesMessage}");
                            }
                        }
                }
                else
                {
                    Log.LogMessage(
                        MessageImportance.Normal,
                        $"PDB is not portable, skipping: '{file.ItemSpec}'");
                }
            }
        }
 public void Convert()
 {
     Assert.Throws <ArgumentNullException>(() => PdbConverter.Convert(null, new MemoryStream(), new MemoryStream()));
     Assert.Throws <ArgumentNullException>(() => PdbConverter.Convert(new MemoryStream(), null, new MemoryStream()));
     Assert.Throws <ArgumentNullException>(() => PdbConverter.Convert(new MemoryStream(), new MemoryStream(), null));
 }