/// <summary> /// Reads all Debug Directory table entries. /// </summary> /// <exception cref="BadImageFormatException">Bad format of the entry.</exception> /// <exception cref="IOException">IO error while reading from the underlying stream.</exception> /// <exception cref="InvalidOperationException">PE image not available.</exception> public ImmutableArray <DebugDirectoryEntry> ReadDebugDirectory() { Debug.Assert(PEHeaders.PEHeader != null); var debugDirectory = PEHeaders.PEHeader.DebugTableDirectory; if (debugDirectory.Size == 0) { return(ImmutableArray <DebugDirectoryEntry> .Empty); } int position; if (!PEHeaders.TryGetDirectoryOffset(debugDirectory, out position)) { throw new BadImageFormatException(SR.InvalidDirectoryRVA); } if (debugDirectory.Size % DebugDirectoryEntry.Size != 0) { throw new BadImageFormatException(SR.InvalidDirectorySize); } using (AbstractMemoryBlock block = GetPEImage().GetMemoryBlock(position, debugDirectory.Size)) { return(ReadDebugDirectoryEntries(block.GetReader())); } }
// internal for testing internal static unsafe ImmutableArray <byte> DecodeEmbeddedPortablePdbDebugDirectoryData(AbstractMemoryBlock block) { byte[] decompressed; var headerReader = block.GetReader(); if (headerReader.ReadUInt32() != PortablePdbVersions.DebugDirectoryEmbeddedSignature) { throw new BadImageFormatException(SR.UnexpectedEmbeddedPortablePdbDataSignature); } int decompressedSize = headerReader.ReadInt32(); try { decompressed = new byte[decompressedSize]; } catch { throw new BadImageFormatException(SR.DataTooBig); } var compressed = new ReadOnlyUnmanagedMemoryStream(headerReader.CurrentPointer, headerReader.RemainingBytes); var deflate = new DeflateStream(compressed, CompressionMode.Decompress, leaveOpen: true); if (decompressedSize > 0) { int actualLength; try { actualLength = deflate.TryReadAll(decompressed, 0, decompressed.Length); } catch (InvalidDataException e) { throw new BadImageFormatException(e.Message, e.InnerException); } if (actualLength != decompressed.Length) { throw new BadImageFormatException(SR.SizeMismatch); } } // Check that there is no more compressed data left, // in case the decompressed size specified in the header is smaller // than the actual decompressed size of the data. if (deflate.ReadByte() != -1) { throw new BadImageFormatException(SR.SizeMismatch); } return(ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref decompressed)); }
// internal for testing internal static PdbChecksumDebugDirectoryData DecodePdbChecksumDebugDirectoryData(AbstractMemoryBlock block) { var reader = block.GetReader(); var algorithmName = reader.ReadUtf8NullTerminated(); byte[]? checksum = reader.ReadBytes(reader.RemainingBytes); if (algorithmName.Length == 0 || checksum.Length == 0) { throw new BadImageFormatException(SR.InvalidPdbChecksumDataFormat); } return(new PdbChecksumDebugDirectoryData( algorithmName, ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref checksum))); }
// internal for testing internal static CodeViewDebugDirectoryData DecodeCodeViewDebugDirectoryData(AbstractMemoryBlock block) { var reader = block.GetReader(); if (reader.ReadByte() != (byte)'R' || reader.ReadByte() != (byte)'S' || reader.ReadByte() != (byte)'D' || reader.ReadByte() != (byte)'S') { throw new BadImageFormatException(SR.UnexpectedCodeViewDataSignature); } Guid guid = reader.ReadGuid(); int age = reader.ReadInt32(); string path = reader.ReadUtf8NullTerminated(); return(new CodeViewDebugDirectoryData(guid, age, path)); }
// internal for testing internal static unsafe NativeHeapMemoryBlock DecodeEmbeddedPortablePdbDebugDirectoryData(AbstractMemoryBlock block) { NativeHeapMemoryBlock?decompressed; var headerReader = block.GetReader(); if (headerReader.ReadUInt32() != PortablePdbVersions.DebugDirectoryEmbeddedSignature) { throw new BadImageFormatException(SR.UnexpectedEmbeddedPortablePdbDataSignature); } int decompressedSize = headerReader.ReadInt32(); try { decompressed = new NativeHeapMemoryBlock(decompressedSize); } catch { throw new BadImageFormatException(SR.DataTooBig); } bool success = false; try { var compressed = new ReadOnlyUnmanagedMemoryStream(headerReader.CurrentPointer, headerReader.RemainingBytes); var deflate = new DeflateStream(compressed, CompressionMode.Decompress, leaveOpen: true); if (decompressedSize > 0) { int actualLength; try { #if NETCOREAPP3_0_OR_GREATER actualLength = deflate.TryReadAll(new Span <byte>(decompressed.Pointer, decompressed.Size)); #else using var decompressedStream = new UnmanagedMemoryStream(decompressed.Pointer, decompressed.Size, decompressed.Size, FileAccess.Write); deflate.CopyTo(decompressedStream); actualLength = (int)decompressedStream.Position; #endif } catch (Exception e) { throw new BadImageFormatException(e.Message, e.InnerException); } if (actualLength != decompressed.Size) { throw new BadImageFormatException(SR.SizeMismatch); } } // Check that there is no more compressed data left, // in case the decompressed size specified in the header is smaller // than the actual decompressed size of the data. if (deflate.ReadByte() != -1) { throw new BadImageFormatException(SR.SizeMismatch); } success = true; } finally { if (!success) { decompressed.Dispose(); } } return(decompressed); }