mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-04-05 22:01:33 +00:00
This change looks dramatic, but it's just separating out the already-split namespaces into separate top-level folders. In theory, every single one could be built into their own Nuget package. `SabreTools.Serialization` still builds the normal Nuget package that is used by all other projects and includes all namespaces.
251 lines
10 KiB
C#
251 lines
10 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace SabreTools.Data.Models.PortableExecutable
|
|
{
|
|
/// <summary>
|
|
/// The following list describes the Microsoft PE executable format, with the
|
|
/// base of the image header at the top. The section from the MS-DOS 2.0
|
|
/// Compatible EXE Header through to the unused section just before the PE header
|
|
/// is the MS-DOS 2.0 Section, and is used for MS-DOS compatibility only.
|
|
/// </summary>
|
|
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
|
public sealed class Executable
|
|
{
|
|
/// <summary>
|
|
/// MS-DOS executable stub
|
|
/// </summary>
|
|
public MSDOS.Executable Stub { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// After the MS-DOS stub, at the file offset specified at offset 0x3c, is a 4-byte
|
|
/// signature that identifies the file as a PE format image file. This signature is "PE\0\0"
|
|
/// (the letters "P" and "E" followed by two null bytes).
|
|
/// </summary>
|
|
public string Signature { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// File header
|
|
/// </summary>
|
|
public COFF.FileHeader FileHeader { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// Microsoft extended optional header
|
|
/// </summary>
|
|
public OptionalHeader OptionalHeader { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// Section table
|
|
/// </summary>
|
|
public COFF.SectionHeader[] SectionTable { get; set; } = [];
|
|
|
|
/// <summary>
|
|
/// Symbol table
|
|
/// </summary>
|
|
public COFF.SymbolTableEntries.BaseEntry[]? SymbolTable { get; set; }
|
|
|
|
/// <summary>
|
|
/// String table
|
|
/// </summary>
|
|
public COFF.StringTable? StringTable { get; set; }
|
|
|
|
#region Data Directories
|
|
|
|
/// <summary>
|
|
/// The export data section, named .edata, contains information about symbols that other images
|
|
/// can access through dynamic linking. Exported symbols are generally found in DLLs, but DLLs
|
|
/// can also import symbols.
|
|
///
|
|
/// An overview of the general structure of the export section is described below. The tables
|
|
/// described are usually contiguous in the file in the order shown (though this is not
|
|
/// required). Only the export directory table and export address table are required to export
|
|
/// symbols as ordinals. (An ordinal is an export that is accessed directly by its export
|
|
/// address table index.) The name pointer table, ordinal table, and export name table all
|
|
/// exist to support use of export names.
|
|
/// </summary>
|
|
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
|
#region Export Table (.edata)
|
|
|
|
/// <summary>
|
|
/// A table with just one row (unlike the debug directory). This table indicates the
|
|
/// locations and sizes of the other export tables.
|
|
/// </summary>
|
|
public Export.DirectoryTable? ExportDirectoryTable { get; set; }
|
|
|
|
/// <summary>
|
|
/// An array of RVAs of exported symbols. These are the actual addresses of the exported
|
|
/// functions and data within the executable code and data sections. Other image files
|
|
/// can import a symbol by using an index to this table (an ordinal) or, optionally, by
|
|
/// using the public name that corresponds to the ordinal if a public name is defined.
|
|
/// </summary>
|
|
public Export.AddressTableEntry[]? ExportAddressTable { get; set; }
|
|
|
|
/// <summary>
|
|
/// An array of pointers to the public export names, sorted in ascending order.
|
|
/// </summary>
|
|
public Export.NamePointerTable? NamePointerTable { get; set; }
|
|
|
|
/// <summary>
|
|
/// An array of the ordinals that correspond to members of the name pointer table. The
|
|
/// correspondence is by position; therefore, the name pointer table and the ordinal table
|
|
/// must have the same number of members. Each ordinal is an index into the export address
|
|
/// table.
|
|
/// </summary>
|
|
public Export.OrdinalTable? OrdinalTable { get; set; }
|
|
|
|
/// <summary>
|
|
/// A series of null-terminated ASCII strings. Members of the name pointer table point into
|
|
/// this area. These names are the public names through which the symbols are imported and
|
|
/// exported; they are not necessarily the same as the private names that are used within
|
|
/// the image file.
|
|
/// </summary>
|
|
public Export.NameTable? ExportNameTable { get; set; }
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// All image files that import symbols, including virtually all executable (EXE) files,
|
|
/// have an .idata section. A typical file layout for the import information follows:
|
|
///
|
|
/// - Directory Table
|
|
/// Null Directory Entry
|
|
/// - DLL1 Import Lookup Table
|
|
/// Null
|
|
/// - DLL2 Import Lookup Table
|
|
/// Null
|
|
/// - DLL3 Import Lookup Table
|
|
/// Null
|
|
/// - Hint-Name Table
|
|
/// </summary>
|
|
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
|
#region Import Table (.idata) and Import Address Table
|
|
|
|
/// <summary>
|
|
/// The import information begins with the import directory table, which describes the
|
|
/// remainder of the import information.
|
|
/// </summary>
|
|
public Import.DirectoryTableEntry[]? ImportDirectoryTable { get; set; }
|
|
|
|
/// <summary>
|
|
/// An import lookup table is an array of 32-bit numbers for PE32 or an array of 64-bit
|
|
/// numbers for PE32+.
|
|
/// </summary>
|
|
public Dictionary<int, Import.LookupTableEntry[]?>? ImportLookupTables { get; set; }
|
|
|
|
/// <summary>
|
|
/// These addresses are the actual memory addresses of the symbols, although technically
|
|
/// they are still called "virtual addresses".
|
|
/// </summary>
|
|
public Dictionary<int, Import.AddressTableEntry[]?>? ImportAddressTables { get; set; }
|
|
|
|
/// <summary>
|
|
/// One hint/name table suffices for the entire import section.
|
|
/// </summary>
|
|
public Import.HintNameTableEntry[]? HintNameTable { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region Resource Table (.rsrc)
|
|
|
|
/// <summary>
|
|
/// Resource directory table (.rsrc)
|
|
/// </summary>
|
|
public Resource.DirectoryTable? ResourceDirectoryTable { get; set; }
|
|
|
|
#endregion
|
|
|
|
// TODO: Handle Exception Table
|
|
|
|
#region Certificate Table
|
|
|
|
/// <summary>
|
|
/// Attribute certificate table
|
|
/// </summary>
|
|
public AttributeCertificate.Entry[]? AttributeCertificateTable { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region Base Relocation Table (.reloc)
|
|
|
|
/// <summary>
|
|
/// Base relocation table
|
|
/// </summary>
|
|
public BaseRelocation.Block[]? BaseRelocationTable { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region Debug Data (.debug*)
|
|
|
|
/// <summary>
|
|
/// Debug table
|
|
/// </summary>
|
|
public DebugData.Table? DebugTable { get; set; }
|
|
|
|
#endregion
|
|
|
|
// TODO: Handle Architecture
|
|
// TODO: Handle Global Ptr
|
|
// TODO: Thread Local Storage (.tls)
|
|
// TODO: Load Configuration Table
|
|
// TODO: Bound Import Table
|
|
|
|
#region Delay Load Table
|
|
|
|
/// <summary>
|
|
/// Delay-load directory table
|
|
/// </summary>
|
|
public DelayLoad.DirectoryTable? DelayLoadDirectoryTable { get; set; }
|
|
|
|
#endregion
|
|
|
|
// TODO: CLR Runtime Header (.cormeta)
|
|
// TODO: Reserved
|
|
|
|
#endregion
|
|
|
|
#region Named Sections
|
|
|
|
// TODO: Support grouped sections in section reading and parsing
|
|
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#grouped-sections-object-only
|
|
// Grouped sections are ordered and mean that the data in the sections contributes
|
|
// to the "base" section (the one without the "$X" suffix). This may negatively impact
|
|
// the use of some of the different types of executables.
|
|
|
|
// .cormeta - CLR metadata is stored in this section. It is used to indicate that
|
|
// the object file contains managed code. The format of the metadata is not
|
|
// documented, but can be handed to the CLR interfaces for handling metadata.
|
|
|
|
// .drectve - A section is a directive section if it has the IMAGE_SCN_LNK_INFO
|
|
// flag set in the section header and has the .drectve section name. The linker
|
|
// removes a .drectve section after processing the information, so the section
|
|
// does not appear in the image file that is being linked.
|
|
//
|
|
// A .drectve section consists of a string of text that can be encoded as ANSI
|
|
// or UTF-8. If the UTF-8 byte order marker (BOM, a three-byte prefix that
|
|
// consists of 0xEF, 0xBB, and 0xBF) is not present, the directive string is
|
|
// interpreted as ANSI. The directive string is a series of linker options that
|
|
// are separated by spaces. Each option contains a hyphen, the option name, and
|
|
// any appropriate attribute. If an option contains spaces, the option must be
|
|
// enclosed in quotes. The .drectve section must not have relocations or line
|
|
// numbers.
|
|
//
|
|
// TODO: Can we implement reading/parsing the .drectve section?
|
|
|
|
// .pdata Section - Multiple formats per entry
|
|
|
|
// .sxdata - The valid exception handlers of an object are listed in the .sxdata
|
|
// section of that object. The section is marked IMAGE_SCN_LNK_INFO. It contains
|
|
// the COFF symbol index of each valid handler, using 4 bytes per index.
|
|
//
|
|
// Additionally, the compiler marks a COFF object as registered SEH by emitting
|
|
// the absolute symbol "@feat.00" with the LSB of the value field set to 1. A
|
|
// COFF object with no registered SEH handlers would have the "@feat.00" symbol,
|
|
// but no .sxdata section.
|
|
//
|
|
// TODO: Can we implement reading/parsing the .sxdata section?
|
|
|
|
#endregion
|
|
|
|
// TODO: Determine if "Archive (Library) File Format" is worth modelling
|
|
}
|
|
}
|