/// <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 MetadataReader GetMetadataReader(string assemblyPath) { MetadataReaderProvider provider = null; if (!_cache.TryGetValue(assemblyPath, out 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()); }
public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, byte[] assembly, byte[] pdb, CancellationToken token) { 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(); }
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(); if (peStream != null) { _peReader = new PEReader(peStream); _ownPeReader = 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 if (!_fileSystem.Exists(docName)) { firstNotFoundDocument = docName; return(false); } } } } } return(true); }
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 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 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); }
/// <summary> /// Returns the portable PDB reader for the assembly path /// </summary> /// <param name="assembly">Managed Assembly to be used as a cache key</param> /// <param name="assemblyPath"> /// File path of the assembly or null if the module is dynamic (generated by Reflection.Emit). /// </param> /// <param name="loadedPeAddress"> /// Loaded PE image address or zero if the module is dynamic (generated by Reflection.Emit). /// Dynamic modules have their PDBs (if any) generated to an in-memory stream /// (pointed to by <paramref name="inMemoryPdbAddress"/> and <paramref name="inMemoryPdbSize"/>). /// </param> /// <param name="loadedPeSize">loaded PE image size</param> /// <param name="inMemoryPdbAddress">in memory PDB address or zero</param> /// <param name="inMemoryPdbSize">in memory PDB size</param> /// <returns>reader</returns> /// <remarks> /// Accounts for unloadable and dynamic types by keying the cache on the managed Assembly. The /// underlying ConditionalWeakTable doesn't keep the assembly alive, so cached types will be /// correctly invalidated when the Assembly is unloaded by the GC. /// </remarks> private unsafe MetadataReader TryGetReader(Assembly assembly, string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, IntPtr inMemoryPdbAddress, int inMemoryPdbSize) { if ((loadedPeAddress == IntPtr.Zero || assemblyPath == null) && inMemoryPdbAddress == IntPtr.Zero) { // Dynamic or in-memory module without symbols (they would be in-memory if they were available). return(null); } // The ConditionalWeakTable's GetValue + callback will atomically create the cache entry for us // so we are protected from multiple threads racing to get/create the same MetadataReaderProvider MetadataReaderProvider provider = _metadataCache.GetValue(assembly, (assembly) => { return((inMemoryPdbAddress != IntPtr.Zero) ? TryOpenReaderForInMemoryPdb(inMemoryPdbAddress, inMemoryPdbSize) : TryOpenReaderFromAssemblyFile(assemblyPath, loadedPeAddress, loadedPeSize)); }); // The reader has already been open, so this doesn't throw. return(provider?.GetMetadataReader()); }
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 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()); } }
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); } }
/// <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)); } } }
/// <summary> /// The method takes ownership of the <paramref name="provider"/> upon entry and disposes it in case of a failure to construct the reader. /// </summary> internal PortablePdbReader(MetadataReaderProvider provider, LazyMetadataImport metadataImport) { Debug.Assert(metadataImport != null); Debug.Assert(provider != null); try { _metadataReader = provider.GetMetadataReader(); } finally { // dispose the provider on error: if (_metadataReader == null) { provider.Dispose(); } } _metadataReaderProvider = provider; _lazyMetadataImport = metadataImport; }
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> /// Opens metadata section of the assembly file produced by the compiler. /// </summary> /// <param name="prefetch"> /// True to prefetch all metadata from the assembly and close the underlying stream on return, /// otherwise keeps the underlying stream open until the returned <see cref="MetadataReaderProvider"/> is disposed. /// </param> /// <returns> /// Instance of <see cref="MetadataReaderProvider"/>, which owns the opened metadata and must be disposed once the caller is done reading the data, /// or null if the assembly is not available. /// </returns> /// <exception cref="BadImageFormatException">Invalid format of the assembly data.</exception> /// <exception cref="InvalidOperationException">The stream returned by <see cref="OpenAssemblyStreamChecked"/> does not support read and seek operations.</exception> /// <exception cref="Exception">Error while reading assembly data.</exception> public virtual MetadataReaderProvider OpenAssemblyMetadata(bool prefetch) { var peStream = OpenAssemblyStreamChecked(); if (peStream != null) { PEHeaders peHeaders; using (var peReader = new PEReader(peStream, PEStreamOptions.LeaveOpen)) { peHeaders = peReader.PEHeaders; } peStream.Position = peHeaders.MetadataStartOffset; return(MetadataReaderProvider.FromMetadataStream( peStream, prefetch ? MetadataStreamOptions.PrefetchMetadata : MetadataStreamOptions.Default, size: peHeaders.MetadataSize)); } return(null); }
/// <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); }
private static MetadataReaderProvider GetMetadataReaderProvider(Module module) { // TODO can the PEReader be pointed at a memory location instead of reading from disk? var dllFileContent = File.ReadAllBytes(module.FullyQualifiedName).ToImmutableArray(); var reader = new PEReader(dllFileContent); TraceSourceLink("probing for embedded symbols: " + module.FullyQualifiedName); if (!reader.HasMetadata) { return(null); } // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs var embeddedPdb = reader.ReadDebugDirectory().FirstOrDefault(x => x.Type == DebugDirectoryEntryType.EmbeddedPortablePdb); if (!embeddedPdb.Equals(default(DebugDirectoryEntry))) { TraceSourceLink("found embedded symbols: " + module.FullyQualifiedName); return(reader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdb)); } var sbFile = new StringBuilder(1024); var sbPath = new StringBuilder(1024); if (SymGetSymbolFile(ProcessHandle, null, module.FullyQualifiedName, SymbolFileType.sfPdb, sbFile, sbFile.Capacity, sbPath, sbPath.Capacity)) { // todo determine if pdb is not portable early // https://github.com/tmat/corefx/blob/f808e59c3ef93e141b019d661a4443a0e19c7442/src/System.Diagnostics.StackTrace/src/System/Diagnostics/StackTraceSymbols.CoreCLR.cs#L164 TraceSourceLink("probing for portable PDB symbols: " + sbFile); var pdbFileContent = File.ReadAllBytes(sbFile.ToString()).ToImmutableArray(); return(MetadataReaderProvider.FromPortablePdbImage(pdbFileContent)); } else { TraceSourceLink("probing for portable PDB symbols failed: " + Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())); } return(null); }
/// <summary> /// The method takes ownership of the <paramref name="provider"/> upon entry and disposes it in case of a failure to construct the reader. /// </summary> internal PortablePdbReader(MetadataReaderProvider provider, int version, int previousDocumentCount) { Debug.Assert(provider != null); Debug.Assert(version >= 1); try { _metadataReader = provider.GetMetadataReader(); } finally { // dispose the provider on error: if (_metadataReader == null) { provider.Dispose(); } } _metadataReaderProvider = provider; Version = version; PreviousDocumentCount = previousDocumentCount; }
/// <summary> /// Returns SourceLink information, that is the source link information as described at https://github.com/dotnet/designs/blob/master/accepted/diagnostics/source-link.md#source-link-json-schema /// stored in PortablePDB. /// The function will throw an exception if PortablePDB file is not found or anything else went wrong. /// </summary> /// <param name="pdbFilePath">Path to PortablePDB file </param> public static SourceLinkInfo GetSourceLinkInfo(string pdbFilePath) { using (FileStream stream = File.OpenRead(pdbFilePath)) { using (MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(stream)) { MetadataReader metadataReader = metadataReaderProvider.GetMetadataReader(); CustomDebugInformationHandleCollection customDebugInformationHandles = metadataReader.CustomDebugInformation; foreach (var customDebugInformationHandle in customDebugInformationHandles) { CustomDebugInformation customDebugInformation = metadataReader.GetCustomDebugInformation(customDebugInformationHandle); if (metadataReader.GetGuid(customDebugInformation.Kind) == SourceLink) { string jsonString = Encoding.UTF8.GetString(metadataReader.GetBlobBytes(customDebugInformation.Value)); return(Newtonsoft.Json.JsonConvert.DeserializeObject <SourceLinkInfo>(jsonString)); } } } } return(null); }
public void GetOrAddDocumentName2() { var mdBuilder = new MetadataBuilder(); mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle)); var n1 = mdBuilder.GetOrAddDocumentName(""); var n2 = mdBuilder.GetOrAddDocumentName("/a/b/c"); var n3 = mdBuilder.GetOrAddDocumentName(@"\a\b\cc"); var n4 = mdBuilder.GetOrAddDocumentName(@"/a/b\c"); var n5 = mdBuilder.GetOrAddDocumentName(@"/\a/\b\\//c"); var n6 = mdBuilder.GetOrAddDocumentName(@"a/"); var n7 = mdBuilder.GetOrAddDocumentName(@"/"); var n8 = mdBuilder.GetOrAddDocumentName(@"\\"); var n9 = mdBuilder.GetOrAddDocumentName("\ud800"); // unpaired surrogate var n10 = mdBuilder.GetOrAddDocumentName("\0"); var root = new MetadataRootBuilder(mdBuilder); var rootBuilder = new BlobBuilder(); root.Serialize(rootBuilder, 0, 0); var mdImage = rootBuilder.ToImmutableArray(); using (var provider = MetadataReaderProvider.FromMetadataImage(mdImage)) { var mdReader = provider.GetMetadataReader(); Assert.Equal("", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n1)))); Assert.Equal("/a/b/c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n2)))); Assert.Equal(@"\a\b\cc", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n3)))); Assert.Equal(@"/a/b\c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n4)))); Assert.Equal(@"/\a/\b\\//c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n5)))); Assert.Equal(@"a/", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n6)))); Assert.Equal(@"/", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n7)))); Assert.Equal(@"\\", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n8)))); Assert.Equal("\uFFFd\uFFFd", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n9)))); Assert.Equal("\0", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n10)))); } }
public static Guid TryReadPdbGuid(string pdbFilePath) { try { using (var stream = File.OpenRead(pdbFilePath)) { if (stream.Length < 1024) { return(Guid.Empty); } if (stream.ReadByte() != 'B' || stream.ReadByte() != 'S' || stream.ReadByte() != 'J' || stream.ReadByte() != 'B') { // not a portable Pdb return(Guid.Empty); } stream.Position = 0; using (var provider = MetadataReaderProvider.FromPortablePdbStream(stream)) { var metadataReader = provider.GetMetadataReader(); var id = metadataReader.DebugMetadataHeader.Id; var guid = new Guid(id.Take(16).ToArray()); var stamp = id.Skip(16).ToArray(); Log("Portable Pdb Guid: " + guid.ToString("D")); return(guid); } } } catch (Exception) { return(Guid.Empty); } }
private static void VerifyMatchingSignatures(Stream portablePdbStream, Stream windowsPdbStream) { Guid guid; uint stamp; int age; using (var provider = MetadataReaderProvider.FromPortablePdbStream(portablePdbStream, MetadataStreamOptions.LeaveOpen)) { SymReaderHelpers.GetWindowsPdbSignature(provider.GetMetadataReader().DebugMetadataHeader !.Id, out guid, out stamp, out age); } var symReader = SymReaderHelpers.CreateWindowsPdbReader(windowsPdbStream); try { Marshal.ThrowExceptionForHR(symReader.MatchesModule(guid, stamp, age, out bool result)); Assert.True(result); } finally { ((ISymUnmanagedDispose)symReader).Destroy(); } }
public string GetSrcSrvStream() { using (var stream = File.Open(this.pdbPath, FileMode.Open, FileAccess.Read)) { using (var metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(stream)) { var metadataReader = metadataReaderProvider.GetMetadataReader(); var customDebugInformationHandleCollection = metadataReader.CustomDebugInformation; foreach (var customDebugInformationHandle in customDebugInformationHandleCollection) { var customDebugInformation = metadataReader.GetCustomDebugInformation(customDebugInformationHandle); if (metadataReader.GetGuid(customDebugInformation.Kind) == SourceLink) { return(Encoding.UTF8.GetString(metadataReader.GetBlobBytes(customDebugInformation.Value))); } } } } return(null); }
public void CustomPdbId() { // Generate a PDB for an assembly using a randomly-generated ID, then validate that the PDB uses the specified ID (string peFileName, string pdbFileName) = CompileTestCase(nameof(CustomPdbId)); var moduleDefinition = new PEFile(peFileName); var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Metadata.DetectTargetFrameworkId(), null, PEStreamOptions.PrefetchEntireImage); var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings()); var expectedPdbId = new BlobContentId(Guid.NewGuid(), (uint)Random.Shared.Next()); using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, nameof(CustomPdbId) + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite)) { pdbStream.SetLength(0); PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream, noLogo: true, pdbId: expectedPdbId); pdbStream.Position = 0; var metadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader(); var generatedPdbId = new BlobContentId(metadataReader.DebugMetadataHeader.Id); Assert.AreEqual(expectedPdbId.Guid, generatedPdbId.Guid); Assert.AreEqual(expectedPdbId.Stamp, generatedPdbId.Stamp); } }
public DebugReaderProvider(string path, Stream stream) { Path = path; this.stream = stream; if (path.EndsWith(".dll")) { var reader = new PEReader(stream); if (reader.HasMetadata) { // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs var debugDirectoryEntries = reader.ReadDebugDirectory(); var embeddedPdb = debugDirectoryEntries.Where(dde => dde.Type == DebugDirectoryEntryType.EmbeddedPortablePdb).FirstOrDefault(); if (!embeddedPdb.Equals(default(DebugDirectoryEntry))) { provider = reader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdb); } } } else { provider = MetadataReaderProvider.FromPortablePdbStream(stream); } }
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); } var matchingResult = MatchDocumentsWithSources(metadataReader); if (!matchingResult.allDocumentsMatch) { firstNotFoundDocument = matchingResult.notFoundDocument; return(false); } } } } return(true); }
static void Main(string[] args) { string pdbPath = GetPdbPath("SourceLink.pdb"); using (var stream = File.OpenRead(pdbPath)) { using (var pdbStream = MetadataReaderProvider.FromPortablePdbStream(stream)) { MethodDebugInformationHandle methodDebugHandle = GetHandle("SourceLink.BubbleSort, SourceLink"); MetadataReader metadataReader = pdbStream.GetMetadataReader(); foreach (var localVariableHandle in GetLocalVariableHandles(metadataReader, methodDebugHandle).SelectMany(_ => _)) { var localVariable = metadataReader.GetLocalVariable(localVariableHandle); var name = metadataReader.GetString(localVariable.Name); Console.WriteLine("Local variable " + name); } Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); foreach (var debugInfoHandle in metadataReader.CustomDebugInformation) { CustomDebugInformation debugInfo = metadataReader.GetCustomDebugInformation(debugInfoHandle); var guid = metadataReader.GetGuid(debugInfo.Kind); if (guid == new Guid("CC110556-A091-4D38-9FEC-25AB9A351A6A")) { var reader = metadataReader.GetBlobReader(debugInfo.Value); Console.WriteLine(reader.ReadUTF8(reader.RemainingBytes)); } } } } Console.ReadLine(); }
public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNotFoundDocument) { firstNotFoundDocument = ""; using (Stream moduleStream = _fileSystem.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb) { using (MetadataReaderProvider embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(entry)) { MetadataReader metadataReader = embeddedMetadataProvider.GetMetadataReader(); 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); } } } } } } // If we don't have EmbeddedPortablePdb entry return true, for instance empty dll // We should call this method only on embedded pdb module return(true); }
private unsafe void TestGetMetadataReader(MetadataReaderProvider provider) { var decoder = new TestMetadataStringDecoder(Encoding.UTF8, (a, b) => "str"); var reader1 = provider.GetMetadataReader(MetadataReaderOptions.None, decoder); Assert.Equal("str", reader1.MetadataVersion); Assert.Same(reader1.UTF8Decoder, decoder); Assert.Equal(reader1.Options, MetadataReaderOptions.None); var reader2 = provider.GetMetadataReader(MetadataReaderOptions.None, decoder); Assert.Same(reader1, reader2); var reader3 = provider.GetMetadataReader(MetadataReaderOptions.None); Assert.NotSame(reader2, reader3); Assert.Equal("v9.9.9.9", reader3.MetadataVersion); Assert.Same(reader3.UTF8Decoder, MetadataStringDecoder.DefaultUTF8); Assert.Equal(reader3.Options, MetadataReaderOptions.None); var reader4 = provider.GetMetadataReader(MetadataReaderOptions.None); Assert.Same(reader3, reader4); var reader5 = provider.GetMetadataReader(MetadataReaderOptions.ApplyWindowsRuntimeProjections); Assert.NotSame(reader4, reader5); Assert.Equal("v9.9.9.9", reader5.MetadataVersion); Assert.Same(reader5.UTF8Decoder, MetadataStringDecoder.DefaultUTF8); Assert.Equal(reader5.Options, MetadataReaderOptions.ApplyWindowsRuntimeProjections); provider.Dispose(); Assert.Throws <ObjectDisposedException>(() => provider.GetMetadataReader(MetadataReaderOptions.ApplyWindowsRuntimeProjections)); Assert.Throws <ObjectDisposedException>(() => provider.GetMetadataReader()); }
private unsafe void TestGetMetadataReader(MetadataReaderProvider provider) { var decoder = new TestMetadataStringDecoder(Encoding.UTF8, (a, b) => "str"); var reader1 = provider.GetMetadataReader(MetadataReaderOptions.None, decoder); Assert.Equal("str", reader1.MetadataVersion); Assert.Same(reader1.Utf8Decoder, decoder); Assert.Equal(reader1.Options, MetadataReaderOptions.None); var reader2 = provider.GetMetadataReader(MetadataReaderOptions.None, decoder); Assert.Same(reader1, reader2); var reader3 = provider.GetMetadataReader(MetadataReaderOptions.None); Assert.NotSame(reader2, reader3); Assert.Equal("v9.9.9.9", reader3.MetadataVersion); Assert.Same(reader3.Utf8Decoder, MetadataStringDecoder.DefaultUTF8); Assert.Equal(reader3.Options, MetadataReaderOptions.None); var reader4 = provider.GetMetadataReader(MetadataReaderOptions.None); Assert.Same(reader3, reader4); var reader5 = provider.GetMetadataReader(MetadataReaderOptions.ApplyWindowsRuntimeProjections); Assert.NotSame(reader4, reader5); Assert.Equal("v9.9.9.9", reader5.MetadataVersion); Assert.Same(reader5.Utf8Decoder, MetadataStringDecoder.DefaultUTF8); Assert.Equal(reader5.Options, MetadataReaderOptions.ApplyWindowsRuntimeProjections); provider.Dispose(); Assert.Throws<ObjectDisposedException>(() => provider.GetMetadataReader(MetadataReaderOptions.ApplyWindowsRuntimeProjections)); Assert.Throws<ObjectDisposedException>(() => provider.GetMetadataReader()); }