/// <summary> /// Initializes a new instance of the <see cref="PortablePdbReader"/> class. /// </summary> /// <param name="stream"> /// Portable pdb stream /// </param> /// <exception cref="Exception"> /// Raises Exception on given stream is not portable pdb stream /// </exception> public PortablePdbReader(Stream stream) { if (!IsPortable(stream)) { throw new Exception("Given stream is not portable stream"); } this.provider = MetadataReaderProvider.FromPortablePdbStream(stream); this.reader = this.provider.GetMetadataReader(); }
public void TestTypetoDocumentNavigationMethod() { string sourceA = @" using System; public class C { public void F2() { } } "; string sourceB = @" using System; public class D { } "; var c1 = CreateCompilation(new[] { SyntaxFactory.ParseSyntaxTree(sourceA, path: "X.cs", encoding: Encoding.UTF8), SyntaxFactory.ParseSyntaxTree(sourceB, path: "Z.cs", encoding: Encoding.UTF8) }, options: TestOptions.DebugDll); var pdbStream = new MemoryStream(); var peImage = c1.EmitToArray(EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), pdbStream: pdbStream); pdbStream.Position = 0; string source2 = @" using System; public class Program { public static void Main() { } } "; var assemblyMetadata = AssemblyMetadata.CreateFromImage(peImage); var metadataReference = assemblyMetadata.GetReference(); var c2 = CreateCompilation(new[] { source2 }, new[] { metadataReference }, options: TestOptions.DebugDll); var typeC = c2.GetTypeByMetadataName("C"); Symbol symbol = typeC.GetMethod("F2"); //symbol = (PEMethodSymbol)symbol; using var provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); var pdbReader = provider.GetMetadataReader(); var docList = FindSourceDocuments(symbol, pdbReader); Assert.Equal(0x30000001, MetadataTokens.GetToken(docList[0])); }
public void SourceLink() { string source = @" using System; class C { public static void Main() { Console.WriteLine(); } } "; var sourceLinkBlob = Encoding.UTF8.GetBytes( @" { ""documents"": { ""f:/build/*"" : ""https://raw.githubusercontent.com/my-org/my-project/1111111111111111111111111111111111111111/*"" } } " ); var c = CreateCompilation( Parse(source, "f:/build/goo.cs"), options: TestOptions.DebugDll ); var pdbStream = new MemoryStream(); c.EmitToArray( EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), pdbStream: pdbStream, sourceLinkStream: new MemoryStream(sourceLinkBlob) ); pdbStream.Position = 0; using (var provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream)) { var pdbReader = provider.GetMetadataReader(); var actualBlob = ( from cdiHandle in pdbReader.GetCustomDebugInformation( EntityHandle.ModuleDefinition ) let cdi = pdbReader.GetCustomDebugInformation(cdiHandle) where pdbReader.GetGuid(cdi.Kind) == PortableCustomDebugInfoKinds.SourceLink select pdbReader.GetBlobBytes(cdi.Value) ).Single(); AssertEx.Equal(sourceLinkBlob, actualBlob); } }
public MetadataReader GetMetadataReaderfromSource(string source) { var c = CreateCompilation(new[] { source }, options: TestOptions.DebugDll); var pdbStream = new MemoryStream(); var peImage = c.EmitToArray(EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), pdbStream: pdbStream); pdbStream.Position = 0; var provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); return(provider.GetMetadataReader()); }
public bool EnC(byte[] meta, byte[] pdb) { var asmStream = new MemoryStream(meta); MetadataReader asmMetadataReader = MetadataReaderProvider.FromMetadataStream(asmStream).GetMetadataReader(); var pdbStream = new MemoryStream(pdb); MetadataReader pdbMetadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader(); enCMetadataReader.Add(asmMetadataReader); enCMetadataReader.Add(pdbMetadataReader); PopulateEnC(asmMetadataReader, pdbMetadataReader); return(true); }
private bool TryOpenPortablePdbFile(string path, BlobContentId id, Func <string, Stream?> pdbFileStreamProvider, out MetadataReaderProvider?provider, ref Exception?errorToReport) { provider = null; MetadataReaderProvider?candidate = null; try { Stream?pdbStream; try { pdbStream = pdbFileStreamProvider(path); } catch (FileNotFoundException) { // Not an unexpected IO exception, continue witout reporting the error. pdbStream = null; } if (pdbStream == null) { return(false); } if (!pdbStream.CanRead || !pdbStream.CanSeek) { throw new InvalidOperationException(SR.StreamMustSupportReadAndSeek); } candidate = MetadataReaderProvider.FromPortablePdbStream(pdbStream); // Validate that the PDB matches the assembly version if (new BlobContentId(candidate.GetMetadataReader().DebugMetadataHeader !.Id) != id) { return(false); } provider = candidate; return(true); } catch (Exception e) when(e is BadImageFormatException || e is IOException) { errorToReport = errorToReport ?? e; return(false); } finally { if (provider == null) { candidate?.Dispose(); } } }
public void AddPdb(Stream peStream, Stream pdbStream) { using (var peReader = new PEReader(peStream)) using (var pdbProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream)) { var peMetadataReader = peReader.GetMetadataReader(); var pdbMetadataReader = pdbProvider.GetMetadataReader(); var moduleName = peMetadataReader.GetString(peMetadataReader.GetModuleDefinition().Name); AddPdb(moduleName, peMetadataReader, pdbMetadataReader); } }
private static OpenedReader TryOpenReaderFromCodeView(PEReader peReader, DebugDirectoryEntry codeViewEntry, string assemblyPath) { OpenedReader result = null; MetadataReaderProvider provider = null; try { var data = peReader.ReadCodeViewDebugDirectoryData(codeViewEntry); string pdbPath = data.Path; if (assemblyPath != null) { try { pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileName(pdbPath)); } catch { // invalid characters in CodeView path return(null); } } var pdbStream = TryOpenFile(pdbPath); if (pdbStream == null) { return(null); } provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); var reader = provider.GetMetadataReader(); // Validate that the PDB matches the assembly version if (data.Age == 1 && new BlobContentId(reader.DebugMetadataHeader.Id) == new BlobContentId(data.Guid, codeViewEntry.Stamp)) { result = new OpenedReader(provider, reader); } } catch (Exception e) when(e is BadImageFormatException || e is IOException) { return(null); } finally { if (result == null) { provider?.Dispose(); } } return(result); }
public MetadataReader GetMetadataReaderfromTwoSource(string source, string sourceB) { var sourceTreeA = SyntaxFactory.ParseSyntaxTree(source, path: "a.cs", encoding: Encoding.UTF8); var sourceTreeB = SyntaxFactory.ParseSyntaxTree(sourceB, path: "b.cs", encoding: Encoding.UTF8); var c = CreateCompilation(new[] { sourceTreeA, sourceTreeB }, options: TestOptions.DebugDll); var pdbStream = new MemoryStream(); var peImage = c.EmitToArray(EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), pdbStream: pdbStream); pdbStream.Position = 0; var provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); return(provider.GetMetadataReader()); }
/// <summary> /// Returns the portable PDB reader for the portable PDB stream /// </summary> /// <param name="pdbStream">portable PDB memory or file stream</param> /// <returns>symbol file or null</returns> /// <remarks> /// Assumes that the PDB loaded into memory can be unloaded or moved around. /// </remarks> public ISymbolFile OpenSymbolFile(Stream pdbStream) { if (pdbStream != null) { throw new ArgumentNullException(nameof(pdbStream)); } if (!pdbStream.CanSeek) { throw new ArgumentException(nameof(pdbStream)); } byte[] buffer = new byte[sizeof(uint)]; pdbStream.Position = 0; if (pdbStream.Read(buffer, 0, sizeof(uint)) != sizeof(uint)) { return(null); } uint signature = BitConverter.ToUInt32(buffer, 0); // quick check to avoid throwing exceptions below in common cases: const uint ManagedMetadataSignature = 0x424A5342; if (signature != ManagedMetadataSignature) { // not a Portable PDB return(null); } SymbolFile result = null; MetadataReaderProvider provider = null; try { pdbStream.Position = 0; provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); result = new SymbolFile(provider, provider.GetMetadataReader()); } catch (Exception e) when(e is BadImageFormatException || e is IOException) { return(null); } finally { if (result == null) { provider?.Dispose(); } } return(result); }
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; } }
//<SnippetReadSourceLineData> public static void ReadSourceLineData(string pdbPath, int methodToken) { // Determine method row number EntityHandle ehMethod = MetadataTokens.EntityHandle(methodToken); if (ehMethod.Kind != HandleKind.MethodDefinition) { Console.WriteLine($"Invalid token kind: {ehMethod.Kind}"); return; } int rowNumber = MetadataTokens.GetRowNumber(ehMethod); // MethodDebugInformation table is indexed by same row numbers as MethodDefinition table MethodDebugInformationHandle hDebug = MetadataTokens.MethodDebugInformationHandle(rowNumber); // Open Portable PDB file using var fs = new FileStream(pdbPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(fs); MetadataReader reader = provider.GetMetadataReader(); if (rowNumber > reader.MethodDebugInformation.Count) { Console.WriteLine("Error: Method row number is out of range"); return; } // Print source line information as console table MethodDebugInformation di = reader.GetMethodDebugInformation(hDebug); Console.WriteLine("IL offset | Start line | Start col. | End line | End col. |"); foreach (SequencePoint sp in di.GetSequencePoints()) { if (sp.IsHidden) { Console.WriteLine($"{sp.Offset.ToString().PadLeft(9)} | (hidden sequence point)"); } else { Console.WriteLine("{0} |{1} |{2} |{3} |{4} |", sp.Offset.ToString().PadLeft(9), sp.StartLine.ToString().PadLeft(11), sp.StartColumn.ToString().PadLeft(11), sp.EndLine.ToString().PadLeft(9), sp.EndColumn.ToString().PadLeft(9)); } } }
private bool HasSourceLinkDebugInformation(Stream pdbStream) { if (!pdbStream.CanSeek) { using var seekablePdbStream = new MemoryStream(); pdbStream.CopyTo(seekablePdbStream); seekablePdbStream.Position = 0; return(HasSourceLinkDebugInformation(seekablePdbStream)); } using var pdbReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); var pdbReader = pdbReaderProvider.GetMetadataReader(); return(HasSourceLinkDebugInformation(pdbReader)); }
public override bool IsValid() { try { _file.Stream.Position = 0; using (MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(_file.Stream, MetadataStreamOptions.LeaveOpen)) { MetadataReader reader = provider.GetMetadataReader(); return(true); } } catch (BadImageFormatException) { } return(false); }
public void EndToEnd_WindowsToPortable_ImplicitPath() { var dir = _temp.CreateDirectory(); var pe = dir.CreateFile("SourceData.dll").WriteAllBytes(TestResources.SourceData.WindowsDll); dir.CreateFile("SourceData.pdb").WriteAllBytes(TestResources.SourceData.WindowsPdb); var outPdb = dir.CreateFile("SourceLink.pdb").WriteAllText("dummy"); Assert.True(Pdb2Pdb.Convert(new Pdb2Pdb.Args( peFilePath: pe.Path, pdbFilePathOpt: null, outPdbFilePathOpt: outPdb.Path, options: PortablePdbConversionOptions.Default, suppressedWarnings: ImmutableArray <PdbDiagnosticId> .Empty, suppressAllWarnings: false, extract: false))); using (var provider = MetadataReaderProvider.FromPortablePdbStream(File.OpenRead(outPdb.Path))) { var sourceLinkCdiGuid = new Guid("CC110556-A091-4D38-9FEC-25AB9A351A6A"); var mdReader = provider.GetMetadataReader(); var sourceLink = from cdiHandle in mdReader.CustomDebugInformation let cdi = mdReader.GetCustomDebugInformation(cdiHandle) where mdReader.GetGuid(cdi.Kind) == sourceLinkCdiGuid select Encoding.UTF8.GetString(mdReader.GetBlobBytes(cdi.Value)); AssertEx.AssertLinesEqual(@" { ""documents"": { ""C:\Documents.cs"": ""http://server/3/Documents.cs.g"", ""C:\a\b\c\d\1.cs"": ""http://server/1/a/b/c/d/1.cs"", ""C:\a\b\c\D\2.cs"": ""http://server/1/a/b/c/D/2.cs"", ""C:\a\b\C\d\3.cs"": ""http://server/1/a/b/C/d/3.cs"", ""C:\a\b\c\d\x.cs"": ""http://server/1/a/b/c/d/x.cs"", ""C:\A\b\c\x.cs"": ""http://server/1/a/b/c/x.cs"", ""C:\a\b\x.cs"": ""http://server/1/a/b/x.cs"", ""C:\a\B\3.cs"": ""http://server/1/a/B/3.cs"", ""C:\a\B\c\4.cs"": ""http://server/1/a/B/c/4.cs"", "":6.cs"": ""http://server/4/%3A6.cs"", ""C:\a\b\X.cs"": ""http://server/1/a/b/X.cs"", ""C:\a\B\x.cs"": ""http://server/1/a/B/x.cs"" } } ", sourceLink.Single()); } }
private MetadataReader GetMetadataReader(string assemblyPath) { if (!_cache.TryGetValue(assemblyPath, out var provider)) { var pdbPath = GetPdbPath(assemblyPath); if (!string.IsNullOrEmpty(pdbPath) && File.Exists(pdbPath) && IsPortable(pdbPath)) { var pdbStream = File.OpenRead(pdbPath); provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); } _cache[assemblyPath] = provider; } return(provider?.GetMetadataReader()); }
/// <summary> /// The output file format looks something like this /// "Module.dll\0Namspace.SubNamespace\0Class\0Method\0" /// + 32-bit big-endian sequence point count /// + (32-bit big-endian sequence point offset) * sequence point count /// </summary> public static void WriteSequencePointsToFile(Stream peStream, Stream pdbStream, Stream outputFile) { var peReader = new PEReader(peStream); var pdbProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); var peMetadataReader = peReader.GetMetadataReader(); var pdbMetadataReader = pdbProvider.GetMetadataReader(); var moduleNameBytes = Encoding.UTF8.GetBytes(peMetadataReader.GetString(peMetadataReader.GetModuleDefinition().Name)); foreach (var methodDebugInfoHandle in pdbMetadataReader.MethodDebugInformation) { var methodDebugInfo = pdbMetadataReader.GetMethodDebugInformation(methodDebugInfoHandle); var methodDefHandle = methodDebugInfoHandle.ToDefinitionHandle(); var methodDef = peMetadataReader.GetMethodDefinition(methodDefHandle); var document = pdbMetadataReader.GetDocument(methodDebugInfo.Document); var methodDefToken = MetadataTokens.GetToken(methodDefHandle); var methodDebugInfoToken = MetadataTokens.GetToken(methodDefHandle); var declaringType = peMetadataReader.GetTypeDefinition(methodDef.GetDeclaringType()); var namespaceNameBytes = Encoding.UTF8.GetBytes(peMetadataReader.GetString(declaringType.Namespace)); var classNameBytes = Encoding.UTF8.GetBytes(peMetadataReader.GetString(declaringType.Name)); var methodNameBytes = Encoding.UTF8.GetBytes(peMetadataReader.GetString(methodDef.Name)); var sequencePoints = methodDebugInfo.GetSequencePoints().Where(sp => !sp.IsHidden).ToArray(); outputFile.Write(moduleNameBytes, 0, moduleNameBytes.Length); outputFile.WriteByte(0); outputFile.Write(namespaceNameBytes, 0, namespaceNameBytes.Length); outputFile.WriteByte(0); outputFile.Write(classNameBytes, 0, classNameBytes.Length); outputFile.WriteByte(0); outputFile.Write(methodNameBytes, 0, methodNameBytes.Length); outputFile.WriteByte(0); WriteInt32(outputFile, sequencePoints.Length); foreach (var sequencePoint in sequencePoints) { WriteInt32(outputFile, sequencePoint.Offset); //Console.WriteLine($"document name: {pdbMetadataReader.GetString(document.Name)} namespace: {peMetadataReader.GetString(declaringType.Namespace)} class name: {peMetadataReader.GetString(declaringType.Name)} method name: {peMetadataReader.GetString(methodDef.Name)} method def token: {methodDefToken} method debug info token: {methodDebugInfoToken} start line: {sequencePoint.StartLine} offset: {sequencePoint.Offset}"); } } outputFile.WriteByte(0); }
public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument) { firstNotFoundDocument = ""; using (var moduleStream = _fileSystem.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { foreach (var entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); using Stream pdbStream = _fileSystem.NewFileStream(codeViewData.Path, FileMode.Open); using MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader metadataReader = null; try { metadataReader = metadataReaderProvider.GetMetadataReader(); } catch (BadImageFormatException) { // TODO log this to warning // In case of non portable pdb we get exception so we skip file sources check return(true); } foreach (DocumentHandle docHandle in metadataReader.Documents) { Document document = metadataReader.GetDocument(docHandle); string docName = metadataReader.GetString(document.Name); // We verify all docs and return false if not all are present in local // We could have false negative if doc is not a source // Btw check for all possible extension could be weak approach if (!_fileSystem.Exists(docName)) { firstNotFoundDocument = docName; return(false); } } } } } return(true); }
public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument) { firstNotFoundDocument = ""; using (var moduleStream = _fileSystem.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { foreach (var entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); using Stream pdbStream = _fileSystem.OpenRead(_sourceRootTranslator.ResolveFilePath(codeViewData.Path)); using MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader metadataReader = null; try { metadataReader = metadataReaderProvider.GetMetadataReader(); } catch (BadImageFormatException) { _logger.LogWarning($"{nameof(BadImageFormatException)} during MetadataReaderProvider.FromPortablePdbStream in InstrumentationHelper.PortablePdbHasLocalSource, unable to check if module has got local source."); return(true); } foreach (DocumentHandle docHandle in metadataReader.Documents) { Document document = metadataReader.GetDocument(docHandle); string docName = _sourceRootTranslator.ResolveFilePath(metadataReader.GetString(document.Name)); // We verify all docs and return false if not all are present in local // We could have false negative if doc is not a source // Btw check for all possible extension could be weak approach // We exlude from the check the autogenerated source file(i.e. source generators) if (!_fileSystem.Exists(docName) && !docName.EndsWith(".g.cs")) { firstNotFoundDocument = docName; return(false); } } } } } return(true); }
public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, byte[] assembly, byte[] pdb, CancellationToken token) { debugId = -1; this.id = Interlocked.Increment(ref next_id); using var asmStream = new MemoryStream(assembly); peReader = new PEReader(asmStream); var entries = peReader.ReadDebugDirectory(); if (entries.Length > 0) { var codeView = entries[0]; CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(codeView); PdbAge = codeViewData.Age; PdbGuid = codeViewData.Guid; PdbName = codeViewData.Path; PdbInformationAvailable = true; } asmMetadataReader = PEReaderExtensions.GetMetadataReader(peReader); var asmDef = asmMetadataReader.GetAssemblyDefinition(); Name = asmDef.GetAssemblyName().Name + ".dll"; if (pdb != null) { var pdbStream = new MemoryStream(pdb); try { // MetadataReaderProvider.FromPortablePdbStream takes ownership of the stream pdbMetadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader(); } catch (BadImageFormatException) { monoProxy.SendLog(sessionId, $"Warning: Unable to read debug information of: {Name} (use DebugType=Portable/Embedded)", token); } } else { var embeddedPdbEntry = entries.FirstOrDefault(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb); if (embeddedPdbEntry.DataSize != 0) { pdbMetadataReader = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry).GetMetadataReader(); } } Populate(); }
/// <summary> /// Returns metadata readers for assembly PE file and portable PDB. /// </summary> /// <param name="assemblyFileName">file name of the assembly</param> /// <param name="peReader">PE metadata reader return</param> /// <param name="pdbReader">PDB metadata reader return</param> /// <returns>true if debugging information is available</returns> private static bool GetReaders(string assemblyFileName, out MetadataReader peReader, out MetadataReader pdbReader) { peReader = null; pdbReader = null; if (!File.Exists(assemblyFileName)) { return(false); } Stream peStream = File.OpenRead(assemblyFileName); PEReader reader = new PEReader(peStream); string pdbPath = null; foreach (DebugDirectoryEntry entry in reader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { CodeViewDebugDirectoryData codeViewData = reader.ReadCodeViewDebugDirectoryData(entry); pdbPath = codeViewData.Path; break; } } if (pdbPath == null) { return(false); } if (!File.Exists(pdbPath)) { pdbPath = Path.GetFileName(pdbPath); if (!File.Exists(pdbPath)) { return(false); } } peReader = reader.GetMetadataReader(); Stream pdbStream = File.OpenRead(pdbPath); MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); pdbReader = provider.GetMetadataReader(); return(true); }
private static OpenedReader TryOpenReaderForInMemoryPdb(Stream pdbStream) { Debug.Assert(pdbStream != null); byte[] buffer = new byte[sizeof(uint)]; if (pdbStream.Read(buffer, 0, sizeof(uint)) != sizeof(uint)) { return(null); } uint signature = BitConverter.ToUInt32(buffer, 0); // quick check to avoid throwing exceptions below in common cases: const uint ManagedMetadataSignature = 0x424A5342; if (signature != ManagedMetadataSignature) { // not a Portable PDB return(null); } OpenedReader result = null; MetadataReaderProvider provider = null; try { pdbStream.Position = 0; provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); result = new OpenedReader(provider, provider.GetMetadataReader()); } catch (Exception e) when(e is BadImageFormatException || e is IOException) { return(null); } finally { if (result == null) { provider?.Dispose(); } } return(result); }
private static void VerifyPortablePdb(Stream pdbStream, string expectedMetadata, string message) { using (var provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream, MetadataStreamOptions.LeaveOpen)) { var mdReader = provider.GetMetadataReader(); var writer = new StringWriter(); var mdv = new MetadataVisualizer(mdReader, writer, MetadataVisualizerOptions.NoHeapReferences); mdv.WriteDocument(); mdv.WriteMethodDebugInformation(); mdv.WriteLocalScope(); mdv.WriteLocalVariable(); mdv.WriteLocalConstant(); mdv.WriteImportScope(); mdv.WriteCustomDebugInformation(); AssertEx.AssertLinesEqual(expectedMetadata, writer.ToString(), message); } }
private async Task <PortablePdb> ExtractPortablePdbAsync( PackageArchiveReader symbolPackage, string pdbPath, CancellationToken cancellationToken) { // TODO: Validate that the PDB has a corresponding DLL // See: https://github.com/NuGet/NuGet.Jobs/blob/master/src/Validation.Symbols/SymbolsValidatorService.cs#L170 Stream pdbStream = null; PortablePdb result = null; try { using (var rawPdbStream = await symbolPackage.GetStreamAsync(pdbPath, cancellationToken)) { pdbStream = await rawPdbStream.AsTemporaryFileStreamAsync(); string signature; using (var pdbReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream, MetadataStreamOptions.LeaveOpen)) { var reader = pdbReaderProvider.GetMetadataReader(); var id = new BlobContentId(reader.DebugMetadataHeader.Id); signature = id.Guid.ToString("N").ToUpperInvariant(); } var fileName = Path.GetFileName(pdbPath).ToLowerInvariant(); var key = $"{signature}ffffffff"; pdbStream.Position = 0; result = new PortablePdb(fileName, key, pdbStream); } } finally { if (result == null) { pdbStream?.Dispose(); } } return(result); }
public string GetSourceLinkBlob() { using (var provider = MetadataReaderProvider.FromPortablePdbStream(GetStream())) { var pdbReader = provider.GetMetadataReader(); var jsonBlob = pdbReader.GetCustomDebugInformation(EntityHandle.ModuleDefinition) .Select(cdiHandle => pdbReader.GetCustomDebugInformation(cdiHandle)) .Where(cdi => pdbReader.GetGuid(cdi.Kind) == SourceLinkGuid) .Select(cdi => pdbReader.GetBlobBytes(cdi.Value)) .FirstOrDefault(); if (jsonBlob == null) { return(null); } return(System.Text.Encoding.UTF8.GetString(jsonBlob)); } }
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 _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(); _peReader = new PEReader(peStream !); //_peReader. _ownPeReader = true; }
public void EmbeddedSource() { string source = @" using System; class C { public static void Main() { Console.WriteLine(); } } "; var tree = Parse(source, "f:/build/foo.cs"); var c = CreateCompilationWithMscorlib(tree, options: TestOptions.DebugDll); var pdbStream = new MemoryStream(); c.EmitToArray( EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), pdbStream: pdbStream, embeddedTexts: new[] { EmbeddedText.FromSource(tree.FilePath, tree.GetText()) }); pdbStream.Position = 0; using (var provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream)) { var pdbReader = provider.GetMetadataReader(); var embeddedSource = (from documentHandle in pdbReader.Documents let document = pdbReader.GetDocument(documentHandle) select new { FilePath = pdbReader.GetString(document.Name), Text = pdbReader.GetEmbeddedSource(documentHandle) }).Single(); Assert.Equal(embeddedSource.FilePath, "f:/build/foo.cs"); Assert.Equal(source, embeddedSource.Text.ToString()); } }
/// <summary> /// This gets format for the VSTS symbol server indexed files. This format is /// based off of the PDB name and the signature present in the PDB /// </summary> /// <param name="pdbFullPath">Path to the PDB file</param> /// <returns>The indexed format of PDB file for the VSTS symbol server</returns> public static string GetIndex(string pdbFullPath) { if (pdbFullPath == null) { throw new ArgumentNullException(nameof(pdbFullPath)); } var indexingPath = string.Empty; using (var stream = File.OpenRead(pdbFullPath)) using (var pdbReaderProvider = MetadataReaderProvider.FromPortablePdbStream(stream, MetadataStreamOptions.LeaveOpen)) { var pdbReader = pdbReaderProvider.GetMetadataReader(); var pdbSignature = new BlobContentId(pdbReader.DebugMetadataHeader.Id).Guid; var pdbFileName = Path.GetFileName(pdbFullPath).ToLowerInvariant(); var pdbAge = "FFFFFFFF"; indexingPath = $"{pdbFileName}/{pdbSignature.ToString("N")}{pdbAge}/{pdbFileName}"; } return(indexingPath); }
internal string [] TupleElementNamesPrivate(MethodMirror method, int localVariableIndex) { using (var metadataReader = MetadataReaderProvider.FromPortablePdbStream(GetStream())) { var reader = metadataReader.GetMetadataReader(); var methodHandle = MetadataTokens.MethodDefinitionHandle(method.MetadataToken); var localScopes = reader.GetLocalScopes(methodHandle); // localVariableIndex is not really il_index, but sequential index when fetching locals // hence use Skip(index) instead of Index matching. var localVar = localScopes.Select(s => reader.GetLocalScope(s)).SelectMany(s => s.GetLocalVariables()).Skip(localVariableIndex).First(); var customDebugInfos = reader.GetCustomDebugInformation(localVar); foreach (var item in customDebugInfos) { var debugInfo = reader.GetCustomDebugInformation(item); if (reader.GetGuid(debugInfo.Kind) == TupleElementNames) { return(DecodeTupleElementNames(reader.GetBlobReader(debugInfo.Value))); } } } return(null); }
/// <summary> /// Constructs new assembly debug information. /// </summary> /// <param name="assembly">The referenced assembly.</param> /// <param name="pdbStream">The associated PDB stream.</param> internal AssemblyDebugInformation(Assembly assembly, Stream pdbStream) { Assembly = assembly; Modules = ImmutableArray.Create(assembly.GetModules()); using (var metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream, MetadataStreamOptions.PrefetchMetadata)) MetadataReader = metadataReaderProvider.GetMetadataReader(); var methodDebugInformationEnumerator = MetadataReader.MethodDebugInformation.GetEnumerator(); while (methodDebugInformationEnumerator.MoveNext()) { var methodDebugRef = methodDebugInformationEnumerator.Current; var methodDefinitionHandle = methodDebugRef.ToDefinitionHandle(); var metadataToken = MetadataTokens.GetToken(methodDefinitionHandle); if (TryResolveMethod(metadataToken, out MethodBase method)) { debugInformation.Add(method, new MethodDebugInformation(this, method, methodDebugRef)); } } }