/// <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()); }
/// <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); }
/// <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; } }
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"); }
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); }
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)); }