private static bool TryMapPortablePdb(Module module, out MetadataReaderProvider metadataReaderProvider) { metadataReaderProvider = null; MetadataReader rd = null; try { metadataReaderProvider = GetMetadataReaderProvider(module); rd = metadataReaderProvider?.GetMetadataReader(); } catch (BadImageFormatException ex) when(ex.Message == "Invalid COR20 header signature.") { TraceSourceLink("no portable PDB found: " + module.FullyQualifiedName); // todo figure out a better way to detect if PDB is portable or classic // https://github.com/dotnet/corefx/blob/06b1365d9881ed26a921490d7edd2d4e4de35565/src/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs#L185 } if (rd == null) { metadataReaderProvider?.Dispose(); metadataReaderProvider = null; return(false); } TraceSourceLink("found portable PDB for: " + module.FullyQualifiedName); // https://github.com/dotnet/symreader-portable/blob/d27c08d6015c4716ced790e34233c0219773ab10/src/Microsoft.DiaSymReader.PortablePdb/Utilities/MetadataUtilities.cs var sourceLinkHandles = rd .GetCustomDebugInformation(EntityHandle.ModuleDefinition) .Where(r => !r.IsNil) .Select(rd.GetCustomDebugInformation) .Where(cdi => !cdi.Value.IsNil && rd.GetGuid(cdi.Kind) == SourceLinkId) .ToList(); if (sourceLinkHandles.Count == 0) { metadataReaderProvider?.Dispose(); metadataReaderProvider = null; return(false); } var sourceLinkHandle = sourceLinkHandles.First(); var sourceLink = SourceLink.Deserialize(rd.GetBlobBytes(sourceLinkHandle.Value)); var hinstance = (long)Marshal.GetHINSTANCE(module); foreach (var dh in rd.Documents) { if (dh.IsNil) { continue; } var doc = rd.GetDocument(dh); var file = rd.GetString(doc.Name); SourceMappedPaths[Tuple.Create(hinstance, file)] = sourceLink.GetUrl(file); } return(true); }
partial void TryOpenEmbeddedPortablePdb(DebugDirectoryEntry embeddedPdbEntry, ref bool openedEmbeddedPdb, ref MetadataReaderProvider provider, ref Exception errorToReport) { provider = null; MetadataReaderProvider candidate = null; try { candidate = ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry); // throws if headers are invalid: candidate.GetMetadataReader(); provider = candidate; openedEmbeddedPdb = true; return; } catch (Exception e) when(e is BadImageFormatException || e is IOException) { errorToReport = errorToReport ?? e; openedEmbeddedPdb = false; } finally { if (candidate == null) { candidate?.Dispose(); } } }
private unsafe static OpenedReader TryOpenReaderForInMemoryPdb(IntPtr inMemoryPdbAddress, int inMemoryPdbSize) { Debug.Assert(inMemoryPdbAddress != IntPtr.Zero); // quick check to avoid throwing exceptions below in common cases: const uint ManagedMetadataSignature = 0x424A5342; if (inMemoryPdbSize < sizeof(uint) || *(uint *)inMemoryPdbAddress != ManagedMetadataSignature) { // not a Portable PDB return(null); } OpenedReader result = null; MetadataReaderProvider provider = null; try { provider = MetadataReaderProvider.FromMetadataImage((byte *)inMemoryPdbAddress, inMemoryPdbSize); result = new OpenedReader(provider, provider.GetMetadataReader()); } catch (BadImageFormatException) { return(null); } finally { if (result == null) { provider?.Dispose(); } } return(result); }
private static OpenedReader TryOpenReaderFromEmbeddedPdb(PEReader peReader, DebugDirectoryEntry embeddedPdbEntry) { OpenedReader result = null; MetadataReaderProvider provider = null; try { // TODO: We might want to cache this provider globally (across stack traces), // since decompressing embedded PDB takes some time. provider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry); 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 OpenedReader TryOpenReaderFromCodeView(PEReader peReader, DebugDirectoryEntry codeViewEntry, string assemblyPath) { OpenedReader result = null; MetadataReaderProvider provider = null; try { CodeViewDebugDirectoryData data = peReader.ReadCodeViewDebugDirectoryData(codeViewEntry); string pdbPath = data.Path; Stream pdbStream = null; if (assemblyPath != null) { try { pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), GetFileName(pdbPath)); } catch { // invalid characters in CodeView path return(null); } pdbStream = TryOpenFile(pdbPath); } if (pdbStream == null) { if (s_symbolStore == null) { return(null); } Debug.Assert(codeViewEntry.MinorVersion == ImageDebugDirectory.PortablePDBMinorVersion); SymbolStoreKey key = PortablePDBFileKeyGenerator.GetKey(pdbPath, data.Guid); pdbStream = GetSymbolStoreFile(key)?.Stream; } provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader 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 void Dispose() { _metadataReaderProvider?.Dispose(); _metadataReaderProvider = null; _lazyMetadataImport?.Dispose(); _lazyMetadataImport = null; }
public void Dispose() { if (!_disposedValue) { _readerProvider.Dispose(); _disposedValue = true; } }
public void Dispose() { if (!_disposedValue) { _readerProvider.Dispose(); _temporaryPdbStream?.Dispose(); _disposedValue = true; } }
/// <summary> /// Returns the portable PDB reader for the assembly path /// </summary> /// <param name="assemblyPath">file path of the assembly or null</param> /// <param name="loadedPeAddress">loaded PE image address or zero</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> /// <param name="reader">returns the reader</param> /// <returns>reader</returns> private MetadataReader GetReader(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, IntPtr inMemoryPdbAddress, int inMemoryPdbSize) { if (loadedPeAddress != IntPtr.Zero) { Tuple <MetadataReaderProvider, MetadataReader> tuple; if (_readerCache.TryGetValue(loadedPeAddress, out tuple)) { return(tuple.Item2); } } MetadataReaderProvider provider = null; MetadataReader reader = null; if (assemblyPath != null) { uint stamp; int age; Guid guid; string pdbName = GetPdbPathFromPeStream(assemblyPath, loadedPeAddress, loadedPeSize, out age, out guid, out stamp); if (pdbName != null && File.Exists(pdbName)) { Stream pdbStream = File.OpenRead(pdbName); provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader rdr = provider.GetMetadataReader(); // Validate that the PDB matches the assembly version if (age == 1 && IdEquals(rdr.DebugMetadataHeader.Id, guid, stamp)) { reader = rdr; } else { provider.Dispose(); provider = null; } } } else if (inMemoryPdbAddress != IntPtr.Zero && inMemoryPdbSize > 0) { unsafe { provider = MetadataReaderProvider.FromPortablePdbImage((byte *)inMemoryPdbAddress.ToPointer(), inMemoryPdbSize); reader = provider.GetMetadataReader(); } } if (reader != null && loadedPeAddress != IntPtr.Zero) { _readerCache.Add(loadedPeAddress, Tuple.Create(provider, reader)); } return(reader); }
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(); } } }
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); }
/// <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); }
protected virtual void Dispose(bool disposing) { if (disposing) { if (provider != null) { provider.Dispose(); } if (stream != null) { stream.Dispose(); } } }
private static CompilationDiff?ValidateFile(FileInfo file, BuildConstructor buildConstructor, string?thisCompilerVersion) { if (s_ignorePatterns.Any(r => r.IsMatch(file.FullName))) { s_logger.LogTrace($"Ignoring {file.FullName}"); return(null); } MetadataReaderProvider?pdbReaderProvider = null; try { // Find the embedded pdb using var fileStream = file.OpenRead(); using var peReader = new PEReader(fileStream); var pdbOpened = peReader.TryOpenAssociatedPortablePdb( peImagePath: file.FullName, filePath => File.Exists(filePath) ? File.OpenRead(filePath) : null, out pdbReaderProvider, out var pdbPath); if (!pdbOpened || pdbReaderProvider is null) { s_logger.LogError($"Could not find pdb for {file.FullName}"); return(null); } s_logger.LogInformation($"Compiling {file.FullName} with pdb {pdbPath ?? "[embedded]"}"); var reader = pdbReaderProvider.GetMetadataReader(); // TODO: Check compilation version using the PEReader var compilation = buildConstructor.CreateCompilation(reader, file.Name); return(CompilationDiff.Create(file, compilation)); } catch (Exception e) { s_logger.LogError(e, file.FullName); return(CompilationDiff.Create(file, e)); } finally { pdbReaderProvider?.Dispose(); } }
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); }
/// <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; }
/// <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; }
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 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), GetFileName(pdbPath)); } catch { // invalid characters in CodeView path return(null); } } var pdbStream = TryOpenFile(pdbPath); if (pdbStream == null) { // workaround, since NI file could be generated in `.native_image` subdirectory // NOTE this is temporary solution until we add option for specifying pdb path try { int tmpLastIndex = assemblyPath.LastIndexOf(".native_image"); if (tmpLastIndex == -1) { return(null); } string tmpPath = assemblyPath.Substring(0, tmpLastIndex); pdbPath = Path.Combine(Path.GetDirectoryName(tmpPath), GetFileName(pdbPath)); } catch { // invalid characters in CodeView path return(null); } 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); }
/// <inheritdoc/> protected override void OnDisposing() { _metadataReaderProvider.Dispose(); _peReader.Dispose(); }
public void Dispose() { provider.Dispose(); }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { embeddedPdbReaderProvider?.Dispose(); file?.Dispose(); }
public void Dispose() { _metadataReaderProvider?.Dispose(); _metadataReaderProvider = null; }
public void Dispose() => Provider.Dispose();
public void Dispose() { _provider?.Dispose(); _provider = null; _reader = null; }
private static CompilationDiff?ValidateFile(FileInfo originalBinary, BuildConstructor buildConstructor, ILogger logger, Options options) { if (s_ignorePatterns.Any(r => r.IsMatch(originalBinary.FullName))) { logger.LogTrace($"Ignoring {originalBinary.FullName}"); return(null); } MetadataReaderProvider?pdbReaderProvider = null; try { // Find the embedded pdb using var originalBinaryStream = originalBinary.OpenRead(); using var originalPeReader = new PEReader(originalBinaryStream); var pdbOpened = originalPeReader.TryOpenAssociatedPortablePdb( peImagePath: originalBinary.FullName, filePath => File.Exists(filePath) ? File.OpenRead(filePath) : null, out pdbReaderProvider, out var pdbPath); if (!pdbOpened || pdbReaderProvider is null) { logger.LogError($"Could not find pdb for {originalBinary.FullName}"); return(null); } using var _ = logger.BeginScope($"Verifying {originalBinary.FullName} with pdb {pdbPath ?? "[embedded]"}"); var pdbReader = pdbReaderProvider.GetMetadataReader(); var optionsReader = new CompilationOptionsReader(logger, pdbReader, originalPeReader); var compilation = buildConstructor.CreateCompilation( optionsReader, Path.GetFileNameWithoutExtension(originalBinary.Name)); var compilationDiff = CompilationDiff.Create(originalBinary, optionsReader, compilation, getDebugEntryPoint(), logger, options); return(compilationDiff); IMethodSymbol?getDebugEntryPoint() { if (optionsReader.GetMainTypeName() is { } mainTypeName&& optionsReader.GetMainMethodName() is { } mainMethodName) { var typeSymbol = compilation.GetTypeByMetadataName(mainTypeName); if (typeSymbol is object) { var methodSymbols = typeSymbol .GetMembers(mainMethodName) .OfType <IMethodSymbol>(); return(methodSymbols.FirstOrDefault()); } } return(null); } } finally { pdbReaderProvider?.Dispose(); } }
public void Dispose() { _pdbReaderProvider.Dispose(); _peReader.Dispose(); }
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()); }
public void Dispose() { _readerProvider.Dispose(); }