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 void ReadPortableDebugTableEntries(PEReader peReader, out DebugDirectoryEntry codeViewEntry, out DebugDirectoryEntry embeddedPdbEntry) { // See spec: https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PE-COFF.md codeViewEntry = default(DebugDirectoryEntry); embeddedPdbEntry = default(DebugDirectoryEntry); foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { const ushort PortableCodeViewVersionMagic = 0x504d; if (entry.MinorVersion != PortableCodeViewVersionMagic) { continue; } codeViewEntry = entry; } else if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb) { embeddedPdbEntry = entry; } } }
internal EmitOutput(ImmutableArray <byte> assembly, ImmutableArray <byte> pdb) { Assembly = assembly; if (pdb.IsDefault) { // We didn't emit a discrete PDB file, so we'll look for an embedded PDB instead. using (var peReader = new PEReader(Assembly)) { DebugDirectoryEntry portablePdbEntry = peReader.ReadDebugDirectory().FirstOrDefault(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb); if (portablePdbEntry.DataSize != 0) { using (var embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(portablePdbEntry)) { var mdReader = embeddedMetadataProvider.GetMetadataReader(); pdb = readMetadata(mdReader); } } } } Pdb = pdb; unsafe ImmutableArray <byte> readMetadata(MetadataReader mdReader) { var length = mdReader.MetadataLength; var bytes = new byte[length]; Marshal.Copy((IntPtr)mdReader.MetadataPointer, bytes, 0, length); return(ImmutableArray.Create(bytes)); } } }
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 DebugDirectoryEntryView(DebugDirectoryEntry entry, string data) { this.RawData = data; this.Timestamp = entry.Stamp; this.MajorVersion = entry.MajorVersion; this.MinorVersion = entry.MinorVersion; this.Type = entry.Type.ToString(); this.SizeOfRawData = entry.DataSize; this.AddressOfRawData = entry.DataRelativeVirtualAddress; this.AddressOfRawData = entry.DataPointer; }
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 static DebugData Get(DebugDirectoryEntry entry) { if (entry.PointerToRawData == 0 && entry.SizeOfData == 0) return null; LocationCalculator calc = entry.Directory.DataDirectory.Directories.Image.GetCalculator(); uint rva = entry.AddressOfRawData; Section section = calc.RVAToSection(rva); ulong image_base = entry.Directory.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; Location location = new Location(entry.PointerToRawData, rva, image_base + rva, entry.SizeOfData, entry.SizeOfData, section); DebugData data = new DebugData(entry, location); return data; }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } ImmutableArray <DebugDirectoryEntry> entries = _module.PEReader.ReadDebugDirectory(); Debug.Assert(entries != null && _debugEntryIndex < entries.Length); DebugDirectoryEntry sourceDebugEntry = entries[_debugEntryIndex]; PEMemoryBlock block = _module.PEReader.GetSectionData(sourceDebugEntry.DataRelativeVirtualAddress); byte[] result = new byte[sourceDebugEntry.DataSize]; block.GetContent(0, sourceDebugEntry.DataSize).CopyTo(result); return(new ObjectData(result, Array.Empty <Relocation>(), _module.Context.Target.PointerSize, new ISymbolDefinitionNode[] { this })); }
private void ReadPortableDebugTableEntries(PEReader peReader, out DebugDirectoryEntry codeViewEntry, out DebugDirectoryEntry embeddedPdbEntry) { // See spec: https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md codeViewEntry = default; embeddedPdbEntry = default; foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { if (entry.MinorVersion != ImageDebugDirectory.PortablePDBMinorVersion) { continue; } codeViewEntry = entry; } else if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb) { embeddedPdbEntry = entry; } } }
/// <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> internal static PdbChecksumDebugDirectoryData ReadPdbChecksumDebugDirectoryData(this PEReader peReader, DebugDirectoryEntry entry) { if (entry.Type != PdbChecksumEntryType) { throw new ArgumentException("Unexpected debug directory entry type", nameof(entry)); } var peImage = peReader.GetEntireImage(); int dataOffset = peReader.IsLoadedImage ? entry.DataRelativeVirtualAddress : entry.DataPointer; var reader = peImage.GetReader(dataOffset, entry.DataSize); int nameLength = reader.IndexOf(0); if (nameLength <= 0) { throw new BadImageFormatException("Invalid PDB Checksum data format"); } string algorithmName = reader.ReadUTF8(nameLength); // NUL reader.Offset += 1; var checksum = reader.ReadBytes(reader.RemainingBytes).ToImmutableArray(); if (checksum.Length == 0) { throw new BadImageFormatException("Invalid PDB Checksum data format"); } return(new PdbChecksumDebugDirectoryData(algorithmName, checksum)); }
public DebugDirectoryEntryTreeNode(PEFile module, DebugDirectoryEntry entry) { this.module = module; this.reader = module.Reader; this.entry = entry; }
internal DebugData(DebugDirectoryEntry directorEntry, Location dataLocation) { entry = directorEntry; location = dataLocation; }
private string ShowDebugDirectory_Type(DebugDirectoryEntry directoryEntry) { DebugDirectoryEntryType type = directoryEntry.GetEntryType(); EnumAnnotations<DebugDirectoryEntryType> annotations = new EnumAnnotations<DebugDirectoryEntryType>(); EnumAnnotation<DebugDirectoryEntryType> annotation = annotations.FirstOrDefault(a => a.Value == type); if (annotation == null) return null; long value = Convert.ToInt64(annotation.Value); string result = String.Format("{0} {1}", Utils.IntToHex(value, 8), annotation.HeaderName); return result; }
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); }