| File: System\Reflection\PortableExecutable\PEHeader.cs | Web Access |
| Project: src\runtime\src\libraries\System.Reflection.Metadata\src\System.Reflection.Metadata.csproj (System.Reflection.Metadata) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Reflection.Metadata; namespace System.Reflection.PortableExecutable { public sealed class PEHeader { #region Standard fields /// <summary> /// Identifies the format of the image file. /// </summary> public PEMagic Magic { get; } /// <summary> /// The linker major version number. /// </summary> public byte MajorLinkerVersion { get; } /// <summary> /// The linker minor version number. /// </summary> public byte MinorLinkerVersion { get; } /// <summary> /// The size of the code (text) section, or the sum of all code sections if there are multiple sections. /// </summary> public int SizeOfCode { get; } /// <summary> /// The size of the initialized data section, or the sum of all such sections if there are multiple data sections. /// </summary> public int SizeOfInitializedData { get; } /// <summary> /// The size of the uninitialized data section (BSS), or the sum of all such sections if there are multiple BSS sections. /// </summary> public int SizeOfUninitializedData { get; } /// <summary> /// The address of the entry point relative to the image base when the PE file is loaded into memory. /// For program images, this is the starting address. For device drivers, this is the address of the initialization function. /// An entry point is optional for DLLs. When no entry point is present, this field must be zero. /// </summary> public int AddressOfEntryPoint { get; } /// <summary> /// The address that is relative to the image base of the beginning-of-code section when it is loaded into memory. /// </summary> public int BaseOfCode { get; } /// <summary> /// The address that is relative to the image base of the beginning-of-data section when it is loaded into memory. /// </summary> public int BaseOfData { get; } #endregion #region Windows Specific Fields /// <summary> /// The preferred address of the first byte of image when loaded into memory; /// must be a multiple of 64K. /// </summary> public ulong ImageBase { get; } /// <summary> /// The alignment (in bytes) of sections when they are loaded into memory. It must be greater than or equal to <see cref="FileAlignment"/>. /// The default is the page size for the architecture. /// </summary> public int SectionAlignment { get; } /// <summary> /// The alignment factor (in bytes) that is used to align the raw data of sections in the image file. /// The value should be a power of 2 between 512 and 64K, inclusive. The default is 512. /// If the <see cref="SectionAlignment"/> is less than the architecture's page size, /// then <see cref="FileAlignment"/> must match <see cref="SectionAlignment"/>. /// </summary> public int FileAlignment { get; } /// <summary> /// The major version number of the required operating system. /// </summary> public ushort MajorOperatingSystemVersion { get; } /// <summary> /// The minor version number of the required operating system. /// </summary> public ushort MinorOperatingSystemVersion { get; } /// <summary> /// The major version number of the image. /// </summary> public ushort MajorImageVersion { get; } /// <summary> /// The minor version number of the image. /// </summary> public ushort MinorImageVersion { get; } /// <summary> /// The major version number of the subsystem. /// </summary> public ushort MajorSubsystemVersion { get; } /// <summary> /// The minor version number of the subsystem. /// </summary> public ushort MinorSubsystemVersion { get; } /// <summary> /// The size (in bytes) of the image, including all headers, as the image is loaded in memory. /// It must be a multiple of <see cref="SectionAlignment"/>. /// </summary> public int SizeOfImage { get; } /// <summary> /// The combined size of an MS DOS stub, PE header, and section headers rounded up to a multiple of FileAlignment. /// </summary> public int SizeOfHeaders { get; } /// <summary> /// The image file checksum. /// </summary> public uint CheckSum { get; } /// <summary> /// The subsystem that is required to run this image. /// </summary> public Subsystem Subsystem { get; } public DllCharacteristics DllCharacteristics { get; } /// <summary> /// The size of the stack to reserve. Only <see cref="SizeOfStackCommit"/> is committed; /// the rest is made available one page at a time until the reserve size is reached. /// </summary> public ulong SizeOfStackReserve { get; } /// <summary> /// The size of the stack to commit. /// </summary> public ulong SizeOfStackCommit { get; } /// <summary> /// The size of the local heap space to reserve. Only <see cref="SizeOfHeapCommit"/> is committed; /// the rest is made available one page at a time until the reserve size is reached. /// </summary> public ulong SizeOfHeapReserve { get; } /// <summary> /// The size of the local heap space to commit. /// </summary> public ulong SizeOfHeapCommit { get; } /// <summary> /// The number of data-directory entries in the remainder of the <see cref="PEHeader"/>. Each describes a location and size. /// </summary> public int NumberOfRvaAndSizes { get; } #endregion #region Directory Entries /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_EXPORT. /// </remarks> public DirectoryEntry ExportTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_IMPORT. /// </remarks> public DirectoryEntry ImportTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_RESOURCE. /// </remarks> public DirectoryEntry ResourceTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_EXCEPTION. /// </remarks> public DirectoryEntry ExceptionTableDirectory { get; } /// <summary> /// The Certificate Table entry points to a table of attribute certificates. /// </summary> /// <remarks> /// These certificates are not loaded into memory as part of the image. /// As such, the first field of this entry, which is normally an RVA, is a file pointer instead. /// /// Aka IMAGE_DIRECTORY_ENTRY_SECURITY. /// </remarks> public DirectoryEntry CertificateTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_BASERELOC. /// </remarks> public DirectoryEntry BaseRelocationTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_DEBUG. /// </remarks> public DirectoryEntry DebugTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_COPYRIGHT or IMAGE_DIRECTORY_ENTRY_ARCHITECTURE. /// </remarks> public DirectoryEntry CopyrightTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_GLOBALPTR. /// </remarks> public DirectoryEntry GlobalPointerTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_TLS. /// </remarks> public DirectoryEntry ThreadLocalStorageTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG. /// </remarks> public DirectoryEntry LoadConfigTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT. /// </remarks> public DirectoryEntry BoundImportTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_IAT. /// </remarks> public DirectoryEntry ImportAddressTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT. /// </remarks> public DirectoryEntry DelayImportTableDirectory { get; } /// <remarks> /// Aka IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR. /// </remarks> public DirectoryEntry CorHeaderTableDirectory { get; } #endregion internal const int OffsetOfChecksum = sizeof(short) + // Magic sizeof(byte) + // MajorLinkerVersion sizeof(byte) + // MinorLinkerVersion sizeof(int) + // SizeOfCode sizeof(int) + // SizeOfInitializedData sizeof(int) + // SizeOfUninitializedData sizeof(int) + // AddressOfEntryPoint sizeof(int) + // BaseOfCode sizeof(long) + // PE32: BaseOfData (int), ImageBase (int) // PE32+: ImageBase (long) sizeof(int) + // SectionAlignment sizeof(int) + // FileAlignment sizeof(short) + // MajorOperatingSystemVersion sizeof(short) + // MinorOperatingSystemVersion sizeof(short) + // MajorImageVersion sizeof(short) + // MinorImageVersion sizeof(short) + // MajorSubsystemVersion sizeof(short) + // MinorSubsystemVersion sizeof(int) + // Win32VersionValue sizeof(int) + // SizeOfImage sizeof(int); // SizeOfHeaders internal static int Size(bool is32Bit) => OffsetOfChecksum + sizeof(int) + // Checksum sizeof(short) + // Subsystem sizeof(short) + // DllCharacteristics 4 * (is32Bit ? sizeof(int) : sizeof(long)) + // SizeOfStackReserve, SizeOfStackCommit, SizeOfHeapReserve, SizeOfHeapCommit sizeof(int) + // LoaderFlags sizeof(int) + // NumberOfRvaAndSizes 16 * sizeof(long); // directory entries internal PEHeader(ref PEBinaryReader reader) { PEMagic magic = (PEMagic)reader.ReadUInt16(); if (magic != PEMagic.PE32 && magic != PEMagic.PE32Plus) { throw new BadImageFormatException(SR.UnknownPEMagicValue); } Magic = magic; MajorLinkerVersion = reader.ReadByte(); MinorLinkerVersion = reader.ReadByte(); SizeOfCode = reader.ReadInt32(); SizeOfInitializedData = reader.ReadInt32(); SizeOfUninitializedData = reader.ReadInt32(); AddressOfEntryPoint = reader.ReadInt32(); BaseOfCode = reader.ReadInt32(); if (magic == PEMagic.PE32Plus) { BaseOfData = 0; // not present } else { Debug.Assert(magic == PEMagic.PE32); BaseOfData = reader.ReadInt32(); } if (magic == PEMagic.PE32Plus) { ImageBase = reader.ReadUInt64(); } else { ImageBase = reader.ReadUInt32(); } // NT additional fields: SectionAlignment = reader.ReadInt32(); FileAlignment = reader.ReadInt32(); MajorOperatingSystemVersion = reader.ReadUInt16(); MinorOperatingSystemVersion = reader.ReadUInt16(); MajorImageVersion = reader.ReadUInt16(); MinorImageVersion = reader.ReadUInt16(); MajorSubsystemVersion = reader.ReadUInt16(); MinorSubsystemVersion = reader.ReadUInt16(); // Win32VersionValue (reserved, should be 0) reader.ReadUInt32(); SizeOfImage = reader.ReadInt32(); SizeOfHeaders = reader.ReadInt32(); CheckSum = reader.ReadUInt32(); Subsystem = (Subsystem)reader.ReadUInt16(); DllCharacteristics = (DllCharacteristics)reader.ReadUInt16(); if (magic == PEMagic.PE32Plus) { SizeOfStackReserve = reader.ReadUInt64(); SizeOfStackCommit = reader.ReadUInt64(); SizeOfHeapReserve = reader.ReadUInt64(); SizeOfHeapCommit = reader.ReadUInt64(); } else { SizeOfStackReserve = reader.ReadUInt32(); SizeOfStackCommit = reader.ReadUInt32(); SizeOfHeapReserve = reader.ReadUInt32(); SizeOfHeapCommit = reader.ReadUInt32(); } // loader flags reader.ReadUInt32(); NumberOfRvaAndSizes = reader.ReadInt32(); // directory entries: ExportTableDirectory = new DirectoryEntry(ref reader); ImportTableDirectory = new DirectoryEntry(ref reader); ResourceTableDirectory = new DirectoryEntry(ref reader); ExceptionTableDirectory = new DirectoryEntry(ref reader); CertificateTableDirectory = new DirectoryEntry(ref reader); BaseRelocationTableDirectory = new DirectoryEntry(ref reader); DebugTableDirectory = new DirectoryEntry(ref reader); CopyrightTableDirectory = new DirectoryEntry(ref reader); GlobalPointerTableDirectory = new DirectoryEntry(ref reader); ThreadLocalStorageTableDirectory = new DirectoryEntry(ref reader); LoadConfigTableDirectory = new DirectoryEntry(ref reader); BoundImportTableDirectory = new DirectoryEntry(ref reader); ImportAddressTableDirectory = new DirectoryEntry(ref reader); DelayImportTableDirectory = new DirectoryEntry(ref reader); CorHeaderTableDirectory = new DirectoryEntry(ref reader); // ReservedDirectory (should be 0, 0) new DirectoryEntry(ref reader); } } }