private bool TryOpenCodeViewPortablePdb(DebugDirectoryEntry codeViewEntry, string peImageDirectory, Func <string, Stream> pdbFileStreamProvider, out MetadataReaderProvider provider, out string pdbPath, ref Exception errorToReport) { pdbPath = null; provider = null; CodeViewDebugDirectoryData data; try { data = ReadCodeViewDebugDirectoryData(codeViewEntry); } catch (Exception e) when(e is BadImageFormatException || e is IOException) { errorToReport = errorToReport ?? e; return(false); } var id = new BlobContentId(data.Guid, codeViewEntry.Stamp); // The interpretation os the path in the CodeView needs to be platform agnostic, // so that PDBs built on Windows work on Unix-like systems and vice versa. // System.IO.Path.GetFileName() on Unix-like systems doesn't treat '\' as a file name separator, // so we need a custom implementation. Also avoid throwing an exception if the path contains invalid characters, // they might not be invalid on the other platform. It's up to the FS APIs to deal with that when opening the stream. string collocatedPdbPath = PathUtilities.CombinePathWithRelativePath(peImageDirectory, PathUtilities.GetFileName(data.Path)); if (TryOpenPortablePdbFile(collocatedPdbPath, id, pdbFileStreamProvider, out provider, ref errorToReport)) { pdbPath = collocatedPdbPath; return(true); } return(false); }
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(); } } }
/// <summary> /// Reads the data pointed to by the specified Debug Directory entry and interprets them as PDB Checksum entry. /// </summary> /// <exception cref="ArgumentException"><paramref name="entry"/> is not a PDB Checksum entry.</exception> /// <exception cref="BadImageFormatException">Bad format of the data.</exception> /// <exception cref="IOException">IO error while reading from the underlying stream.</exception> /// <exception cref="InvalidOperationException">PE image not available.</exception> public PdbChecksumDebugDirectoryData ReadPdbChecksumDebugDirectoryData(DebugDirectoryEntry entry) { if (entry.Type != DebugDirectoryEntryType.PdbChecksum) { Throw.InvalidArgument(StarkPlatform.Reflection.Resources.SR.Format(SR.UnexpectedDebugDirectoryType, nameof(DebugDirectoryEntryType.PdbChecksum)), nameof(entry)); } using (var block = GetDebugDirectoryEntryDataBlock(entry)) { return(DecodePdbChecksumDebugDirectoryData(block)); } }
/// <summary> /// Reads the data pointed to by the specified Debug Directory entry and interprets them as Embedded Portable PDB blob. /// </summary> /// <returns> /// Provider of a metadata reader reading Portable PDB image. /// </returns> /// <exception cref="ArgumentException"><paramref name="entry"/> is not a <see cref="DebugDirectoryEntryType.EmbeddedPortablePdb"/> entry.</exception> /// <exception cref="BadImageFormatException">Bad format of the data.</exception> /// <exception cref="InvalidOperationException">PE image not available.</exception> public MetadataReaderProvider ReadEmbeddedPortablePdbDebugDirectoryData(DebugDirectoryEntry entry) { if (entry.Type != DebugDirectoryEntryType.EmbeddedPortablePdb) { Throw.InvalidArgument(StarkPlatform.Reflection.Resources.SR.Format(SR.UnexpectedDebugDirectoryType, nameof(DebugDirectoryEntryType.EmbeddedPortablePdb)), nameof(entry)); } ValidateEmbeddedPortablePdbVersion(entry); using (var block = GetDebugDirectoryEntryDataBlock(entry)) { var pdbImage = DecodeEmbeddedPortablePdbDebugDirectoryData(block); return(MetadataReaderProvider.FromPortablePdbImage(pdbImage)); } }
// internal for testing internal static void ValidateEmbeddedPortablePdbVersion(DebugDirectoryEntry entry) { // Major version encodes the version of Portable PDB format itself. // Minor version encodes the version of Embedded Portable PDB blob. // Accept any version of Portable PDB >= 1.0, // but only accept version 1.* of the Embedded Portable PDB blob. // Any breaking change in the format should rev major version of the embedded blob. ushort formatVersion = entry.MajorVersion; if (formatVersion < PortablePdbVersions.MinFormatVersion) { throw new BadImageFormatException(StarkPlatform.Reflection.Resources.SR.Format(SR.UnsupportedFormatVersion, PortablePdbVersions.Format(formatVersion))); } ushort embeddedBlobVersion = entry.MinorVersion; if (embeddedBlobVersion != PortablePdbVersions.DefaultEmbeddedVersion) { throw new BadImageFormatException(StarkPlatform.Reflection.Resources.SR.Format(SR.UnsupportedFormatVersion, PortablePdbVersions.Format(embeddedBlobVersion))); } }
partial void TryOpenEmbeddedPortablePdb(DebugDirectoryEntry embeddedPdbEntry, ref bool openedEmbeddedPdb, ref MetadataReaderProvider provider, ref Exception errorToReport);
private AbstractMemoryBlock GetDebugDirectoryEntryDataBlock(DebugDirectoryEntry entry) { int dataOffset = IsLoadedImage ? entry.DataRelativeVirtualAddress : entry.DataPointer; return(GetPEImage().GetMemoryBlock(dataOffset, entry.DataSize)); }