aboutsummaryrefslogtreecommitdiff
path: root/lib/std/coff.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/coff.zig')
-rw-r--r--lib/std/coff.zig1335
1 files changed, 839 insertions, 496 deletions
diff --git a/lib/std/coff.zig b/lib/std/coff.zig
index c0929020ec..1706af24ab 100644
--- a/lib/std/coff.zig
+++ b/lib/std/coff.zig
@@ -2,70 +2,9 @@ const std = @import("std.zig");
const assert = std.debug.assert;
const mem = std.mem;
-pub const CoffHeaderFlags = packed struct {
- /// Image only, Windows CE, and Microsoft Windows NT and later.
- /// This indicates that the file does not contain base relocations
- /// and must therefore be loaded at its preferred base address.
- /// If the base address is not available, the loader reports an error.
- /// The default behavior of the linker is to strip base relocations
- /// from executable (EXE) files.
- RELOCS_STRIPPED: u1 = 0,
-
- /// Image only. This indicates that the image file is valid and can be run.
- /// If this flag is not set, it indicates a linker error.
- EXECUTABLE_IMAGE: u1 = 0,
-
- /// COFF line numbers have been removed. This flag is deprecated and should be zero.
- LINE_NUMS_STRIPPED: u1 = 0,
-
- /// COFF symbol table entries for local symbols have been removed.
- /// This flag is deprecated and should be zero.
- LOCAL_SYMS_STRIPPED: u1 = 0,
-
- /// Obsolete. Aggressively trim working set.
- /// This flag is deprecated for Windows 2000 and later and must be zero.
- AGGRESSIVE_WS_TRIM: u1 = 0,
-
- /// Application can handle > 2-GB addresses.
- LARGE_ADDRESS_AWARE: u1 = 0,
-
- /// This flag is reserved for future use.
- RESERVED: u1 = 0,
-
- /// Little endian: the least significant bit (LSB) precedes the
- /// most significant bit (MSB) in memory. This flag is deprecated and should be zero.
- BYTES_REVERSED_LO: u1 = 0,
-
- /// Machine is based on a 32-bit-word architecture.
- @"32BIT_MACHINE": u1 = 0,
-
- /// Debugging information is removed from the image file.
- DEBUG_STRIPPED: u1 = 0,
-
- /// If the image is on removable media, fully load it and copy it to the swap file.
- REMOVABLE_RUN_FROM_SWAP: u1 = 0,
-
- /// If the image is on network media, fully load it and copy it to the swap file.
- NET_RUN_FROM_SWAP: u1 = 0,
-
- /// The image file is a system file, not a user program.
- SYSTEM: u1 = 0,
-
- /// The image file is a dynamic-link library (DLL).
- /// Such files are considered executable files for almost all purposes,
- /// although they cannot be directly run.
- DLL: u1 = 0,
-
- /// The file should be run only on a uniprocessor machine.
- UP_SYSTEM_ONLY: u1 = 0,
-
- /// Big endian: the MSB precedes the LSB in memory. This flag is deprecated and should be zero.
- BYTES_REVERSED_HI: u1 = 0,
-};
-
-pub const CoffHeader = extern struct {
+pub const Header = extern struct {
/// The number that identifies the type of target machine.
- machine: MachineType,
+ machine: IMAGE.FILE.MACHINE,
/// The number of sections. This indicates the size of the section table, which immediately follows the headers.
number_of_sections: u16,
@@ -88,49 +27,110 @@ pub const CoffHeader = extern struct {
size_of_optional_header: u16,
/// The flags that indicate the attributes of the file.
- flags: CoffHeaderFlags,
+ flags: Header.Flags,
+
+ pub const Flags = packed struct(u16) {
+ /// Image only, Windows CE, and Microsoft Windows NT and later.
+ /// This indicates that the file does not contain base relocations
+ /// and must therefore be loaded at its preferred base address.
+ /// If the base address is not available, the loader reports an error.
+ /// The default behavior of the linker is to strip base relocations
+ /// from executable (EXE) files.
+ RELOCS_STRIPPED: bool = false,
+
+ /// Image only. This indicates that the image file is valid and can be run.
+ /// If this flag is not set, it indicates a linker error.
+ EXECUTABLE_IMAGE: bool = false,
+
+ /// COFF line numbers have been removed. This flag is deprecated and should be zero.
+ LINE_NUMS_STRIPPED: bool = false,
+
+ /// COFF symbol table entries for local symbols have been removed.
+ /// This flag is deprecated and should be zero.
+ LOCAL_SYMS_STRIPPED: bool = false,
+
+ /// Obsolete. Aggressively trim working set.
+ /// This flag is deprecated for Windows 2000 and later and must be zero.
+ AGGRESSIVE_WS_TRIM: bool = false,
+
+ /// Application can handle > 2-GB addresses.
+ LARGE_ADDRESS_AWARE: bool = false,
+
+ /// This flag is reserved for future use.
+ RESERVED: bool = false,
+
+ /// Little endian: the least significant bit (LSB) precedes the
+ /// most significant bit (MSB) in memory. This flag is deprecated and should be zero.
+ BYTES_REVERSED_LO: bool = false,
+
+ /// Machine is based on a 32-bit-word architecture.
+ @"32BIT_MACHINE": bool = false,
+
+ /// Debugging information is removed from the image file.
+ DEBUG_STRIPPED: bool = false,
+
+ /// If the image is on removable media, fully load it and copy it to the swap file.
+ REMOVABLE_RUN_FROM_SWAP: bool = false,
+
+ /// If the image is on network media, fully load it and copy it to the swap file.
+ NET_RUN_FROM_SWAP: bool = false,
+
+ /// The image file is a system file, not a user program.
+ SYSTEM: bool = false,
+
+ /// The image file is a dynamic-link library (DLL).
+ /// Such files are considered executable files for almost all purposes,
+ /// although they cannot be directly run.
+ DLL: bool = false,
+
+ /// The file should be run only on a uniprocessor machine.
+ UP_SYSTEM_ONLY: bool = false,
+
+ /// Big endian: the MSB precedes the LSB in memory. This flag is deprecated and should be zero.
+ BYTES_REVERSED_HI: bool = false,
+ };
};
// OptionalHeader.magic values
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx
-pub const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
-pub const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
+pub const IMAGE_NT_OPTIONAL_HDR32_MAGIC = @intFromEnum(OptionalHeader.Magic.PE32);
+pub const IMAGE_NT_OPTIONAL_HDR64_MAGIC = @intFromEnum(OptionalHeader.Magic.@"PE32+");
-pub const DllFlags = packed struct {
+pub const DllFlags = packed struct(u16) {
_reserved_0: u5 = 0,
/// Image can handle a high entropy 64-bit virtual address space.
- HIGH_ENTROPY_VA: u1 = 0,
+ HIGH_ENTROPY_VA: bool = false,
/// DLL can be relocated at load time.
- DYNAMIC_BASE: u1 = 0,
+ DYNAMIC_BASE: bool = false,
/// Code Integrity checks are enforced.
- FORCE_INTEGRITY: u1 = 0,
+ FORCE_INTEGRITY: bool = false,
/// Image is NX compatible.
- NX_COMPAT: u1 = 0,
+ NX_COMPAT: bool = false,
/// Isolation aware, but do not isolate the image.
- NO_ISOLATION: u1 = 0,
+ NO_ISOLATION: bool = false,
/// Does not use structured exception (SE) handling. No SE handler may be called in this image.
- NO_SEH: u1 = 0,
+ NO_SEH: bool = false,
/// Do not bind the image.
- NO_BIND: u1 = 0,
+ NO_BIND: bool = false,
/// Image must execute in an AppContainer.
- APPCONTAINER: u1 = 0,
+ APPCONTAINER: bool = false,
/// A WDM driver.
- WDM_DRIVER: u1 = 0,
+ WDM_DRIVER: bool = false,
/// Image supports Control Flow Guard.
- GUARD_CF: u1 = 0,
+ GUARD_CF: bool = false,
/// Terminal Server aware.
- TERMINAL_SERVER_AWARE: u1 = 0,
+ TERMINAL_SERVER_AWARE: bool = false,
};
pub const Subsystem = enum(u16) {
@@ -180,7 +180,7 @@ pub const Subsystem = enum(u16) {
};
pub const OptionalHeader = extern struct {
- magic: u16,
+ magic: OptionalHeader.Magic,
major_linker_version: u8,
minor_linker_version: u8,
size_of_code: u32,
@@ -188,124 +188,67 @@ pub const OptionalHeader = extern struct {
size_of_uninitialized_data: u32,
address_of_entry_point: u32,
base_of_code: u32,
-};
-pub const OptionalHeaderPE32 = extern struct {
- magic: u16,
- major_linker_version: u8,
- minor_linker_version: u8,
- size_of_code: u32,
- size_of_initialized_data: u32,
- size_of_uninitialized_data: u32,
- address_of_entry_point: u32,
- base_of_code: u32,
- base_of_data: u32,
- image_base: u32,
- section_alignment: u32,
- file_alignment: u32,
- major_operating_system_version: u16,
- minor_operating_system_version: u16,
- major_image_version: u16,
- minor_image_version: u16,
- major_subsystem_version: u16,
- minor_subsystem_version: u16,
- win32_version_value: u32,
- size_of_image: u32,
- size_of_headers: u32,
- checksum: u32,
- subsystem: Subsystem,
- dll_flags: DllFlags,
- size_of_stack_reserve: u32,
- size_of_stack_commit: u32,
- size_of_heap_reserve: u32,
- size_of_heap_commit: u32,
- loader_flags: u32,
- number_of_rva_and_sizes: u32,
-};
+ pub const Magic = enum(u16) {
+ PE32 = 0x10b,
+ @"PE32+" = 0x20b,
+ _,
+ };
-pub const OptionalHeaderPE64 = extern struct {
- magic: u16,
- major_linker_version: u8,
- minor_linker_version: u8,
- size_of_code: u32,
- size_of_initialized_data: u32,
- size_of_uninitialized_data: u32,
- address_of_entry_point: u32,
- base_of_code: u32,
- image_base: u64,
- section_alignment: u32,
- file_alignment: u32,
- major_operating_system_version: u16,
- minor_operating_system_version: u16,
- major_image_version: u16,
- minor_image_version: u16,
- major_subsystem_version: u16,
- minor_subsystem_version: u16,
- win32_version_value: u32,
- size_of_image: u32,
- size_of_headers: u32,
- checksum: u32,
- subsystem: Subsystem,
- dll_flags: DllFlags,
- size_of_stack_reserve: u64,
- size_of_stack_commit: u64,
- size_of_heap_reserve: u64,
- size_of_heap_commit: u64,
- loader_flags: u32,
- number_of_rva_and_sizes: u32,
+ pub const PE32 = extern struct {
+ standard: OptionalHeader,
+ base_of_data: u32,
+ image_base: u32,
+ section_alignment: u32,
+ file_alignment: u32,
+ major_operating_system_version: u16,
+ minor_operating_system_version: u16,
+ major_image_version: u16,
+ minor_image_version: u16,
+ major_subsystem_version: u16,
+ minor_subsystem_version: u16,
+ win32_version_value: u32,
+ size_of_image: u32,
+ size_of_headers: u32,
+ checksum: u32,
+ subsystem: Subsystem,
+ dll_flags: DllFlags,
+ size_of_stack_reserve: u32,
+ size_of_stack_commit: u32,
+ size_of_heap_reserve: u32,
+ size_of_heap_commit: u32,
+ loader_flags: u32,
+ number_of_rva_and_sizes: u32,
+ };
+
+ pub const @"PE32+" = extern struct {
+ standard: OptionalHeader,
+ image_base: u64,
+ section_alignment: u32,
+ file_alignment: u32,
+ major_operating_system_version: u16,
+ minor_operating_system_version: u16,
+ major_image_version: u16,
+ minor_image_version: u16,
+ major_subsystem_version: u16,
+ minor_subsystem_version: u16,
+ win32_version_value: u32,
+ size_of_image: u32,
+ size_of_headers: u32,
+ checksum: u32,
+ subsystem: Subsystem,
+ dll_flags: DllFlags,
+ size_of_stack_reserve: u64,
+ size_of_stack_commit: u64,
+ size_of_heap_reserve: u64,
+ size_of_heap_commit: u64,
+ loader_flags: u32,
+ number_of_rva_and_sizes: u32,
+ };
};
pub const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
-pub const DirectoryEntry = enum(u16) {
- /// Export Directory
- EXPORT = 0,
-
- /// Import Directory
- IMPORT = 1,
-
- /// Resource Directory
- RESOURCE = 2,
-
- /// Exception Directory
- EXCEPTION = 3,
-
- /// Security Directory
- SECURITY = 4,
-
- /// Base Relocation Table
- BASERELOC = 5,
-
- /// Debug Directory
- DEBUG = 6,
-
- /// Architecture Specific Data
- ARCHITECTURE = 7,
-
- /// RVA of GP
- GLOBALPTR = 8,
-
- /// TLS Directory
- TLS = 9,
-
- /// Load Configuration Directory
- LOAD_CONFIG = 10,
-
- /// Bound Import Directory in headers
- BOUND_IMPORT = 11,
-
- /// Import Address Table
- IAT = 12,
-
- /// Delay Load Import Descriptors
- DELAY_IMPORT = 13,
-
- /// COM Runtime descriptor
- COM_DESCRIPTOR = 14,
-
- _,
-};
-
pub const ImageDataDirectory = extern struct {
virtual_address: u32,
size: u32,
@@ -319,7 +262,7 @@ pub const BaseRelocationDirectoryEntry = extern struct {
block_size: u32,
};
-pub const BaseRelocation = packed struct {
+pub const BaseRelocation = packed struct(u16) {
/// Stored in the remaining 12 bits of the WORD, an offset from the starting address that was specified in the Page RVA field for the block.
/// This offset specifies where the base relocation is to be applied.
offset: u12,
@@ -447,12 +390,12 @@ pub const ImportDirectoryEntry = extern struct {
};
pub const ImportLookupEntry32 = struct {
- pub const ByName = packed struct {
+ pub const ByName = packed struct(u32) {
name_table_rva: u31,
flag: u1 = 0,
};
- pub const ByOrdinal = packed struct {
+ pub const ByOrdinal = packed struct(u32) {
ordinal_number: u16,
unused: u15 = 0,
flag: u1 = 1,
@@ -472,13 +415,13 @@ pub const ImportLookupEntry32 = struct {
};
pub const ImportLookupEntry64 = struct {
- pub const ByName = packed struct {
+ pub const ByName = packed struct(u64) {
name_table_rva: u31,
unused: u32 = 0,
flag: u1 = 0,
};
- pub const ByOrdinal = packed struct {
+ pub const ByOrdinal = packed struct(u64) {
ordinal_number: u16,
unused: u47 = 0,
flag: u1 = 1,
@@ -519,7 +462,7 @@ pub const SectionHeader = extern struct {
pointer_to_linenumbers: u32,
number_of_relocations: u16,
number_of_linenumbers: u16,
- flags: SectionHeaderFlags,
+ flags: SectionHeader.Flags,
pub fn getName(self: *align(1) const SectionHeader) ?[]const u8 {
if (self.name[0] == '/') return null;
@@ -536,119 +479,139 @@ pub const SectionHeader = extern struct {
/// Applicable only to section headers in COFF objects.
pub fn getAlignment(self: SectionHeader) ?u16 {
- if (self.flags.ALIGN == 0) return null;
- return std.math.powi(u16, 2, self.flags.ALIGN - 1) catch unreachable;
+ return self.flags.ALIGN.toByteUnits();
}
pub fn setAlignment(self: *SectionHeader, new_alignment: u16) void {
- assert(new_alignment > 0 and new_alignment <= 8192);
- self.flags.ALIGN = @intCast(std.math.log2(new_alignment));
+ self.flags.ALIGN = .fromByteUnits(new_alignment);
}
pub fn isCode(self: SectionHeader) bool {
- return self.flags.CNT_CODE == 0b1;
+ return self.flags.CNT_CODE;
}
pub fn isComdat(self: SectionHeader) bool {
- return self.flags.LNK_COMDAT == 0b1;
+ return self.flags.LNK_COMDAT;
}
-};
-pub const SectionHeaderFlags = packed struct {
- _reserved_0: u3 = 0,
+ pub const Flags = packed struct(u32) {
+ SCALE_INDEX: bool = false,
+
+ unused1: u2 = 0,
- /// The section should not be padded to the next boundary.
- /// This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES.
- /// This is valid only for object files.
- TYPE_NO_PAD: u1 = 0,
+ /// The section should not be padded to the next boundary.
+ /// This flag is obsolete and is replaced by `.ALIGN = .@"1BYTES"`.
+ /// This is valid only for object files.
+ TYPE_NO_PAD: bool = false,
- _reserved_1: u1 = 0,
+ unused4: u1 = 0,
- /// The section contains executable code.
- CNT_CODE: u1 = 0,
+ /// The section contains executable code.
+ CNT_CODE: bool = false,
- /// The section contains initialized data.
- CNT_INITIALIZED_DATA: u1 = 0,
+ /// The section contains initialized data.
+ CNT_INITIALIZED_DATA: bool = false,
- /// The section contains uninitialized data.
- CNT_UNINITIALIZED_DATA: u1 = 0,
+ /// The section contains uninitialized data.
+ CNT_UNINITIALIZED_DATA: bool = false,
- /// Reserved for future use.
- LNK_OTHER: u1 = 0,
+ /// Reserved for future use.
+ LNK_OTHER: bool = false,
- /// The section contains comments or other information.
- /// The .drectve section has this type.
- /// This is valid for object files only.
- LNK_INFO: u1 = 0,
+ /// The section contains comments or other information.
+ /// The .drectve section has this type.
+ /// This is valid for object files only.
+ LNK_INFO: bool = false,
- _reserved_2: u1 = 0,
+ unused10: u1 = 0,
- /// The section will not become part of the image.
- /// This is valid only for object files.
- LNK_REMOVE: u1 = 0,
+ /// The section will not become part of the image.
+ /// This is valid only for object files.
+ LNK_REMOVE: bool = false,
- /// The section contains COMDAT data.
- /// For more information, see COMDAT Sections (Object Only).
- /// This is valid only for object files.
- LNK_COMDAT: u1 = 0,
+ /// The section contains COMDAT data.
+ /// For more information, see COMDAT Sections (Object Only).
+ /// This is valid only for object files.
+ LNK_COMDAT: bool = false,
- _reserved_3: u2 = 0,
+ unused13: u2 = 0,
- /// The section contains data referenced through the global pointer (GP).
- GPREL: u1 = 0,
+ union14: packed union {
+ mask: u1,
+ /// The section contains data referenced through the global pointer (GP).
+ GPREL: bool,
+ MEM_FARDATA: bool,
+ } = .{ .mask = 0 },
- /// Reserved for future use.
- MEM_PURGEABLE: u1 = 0,
+ unused15: u1 = 0,
- /// Reserved for future use.
- MEM_16BIT: u1 = 0,
+ union16: packed union {
+ mask: u1,
+ MEM_PURGEABLE: bool,
+ MEM_16BIT: bool,
+ } = .{ .mask = 0 },
- /// Reserved for future use.
- MEM_LOCKED: u1 = 0,
+ /// Reserved for future use.
+ MEM_LOCKED: bool = false,
- /// Reserved for future use.
- MEM_PRELOAD: u1 = 0,
+ /// Reserved for future use.
+ MEM_PRELOAD: bool = false,
- /// Takes on multiple values according to flags:
- /// pub const IMAGE_SCN_ALIGN_1BYTES: u32 = 0x100000;
- /// pub const IMAGE_SCN_ALIGN_2BYTES: u32 = 0x200000;
- /// pub const IMAGE_SCN_ALIGN_4BYTES: u32 = 0x300000;
- /// pub const IMAGE_SCN_ALIGN_8BYTES: u32 = 0x400000;
- /// pub const IMAGE_SCN_ALIGN_16BYTES: u32 = 0x500000;
- /// pub const IMAGE_SCN_ALIGN_32BYTES: u32 = 0x600000;
- /// pub const IMAGE_SCN_ALIGN_64BYTES: u32 = 0x700000;
- /// pub const IMAGE_SCN_ALIGN_128BYTES: u32 = 0x800000;
- /// pub const IMAGE_SCN_ALIGN_256BYTES: u32 = 0x900000;
- /// pub const IMAGE_SCN_ALIGN_512BYTES: u32 = 0xA00000;
- /// pub const IMAGE_SCN_ALIGN_1024BYTES: u32 = 0xB00000;
- /// pub const IMAGE_SCN_ALIGN_2048BYTES: u32 = 0xC00000;
- /// pub const IMAGE_SCN_ALIGN_4096BYTES: u32 = 0xD00000;
- /// pub const IMAGE_SCN_ALIGN_8192BYTES: u32 = 0xE00000;
- ALIGN: u4 = 0,
+ ALIGN: SectionHeader.Flags.Align = .NONE,
- /// The section contains extended relocations.
- LNK_NRELOC_OVFL: u1 = 0,
+ /// The section contains extended relocations.
+ LNK_NRELOC_OVFL: bool = false,
- /// The section can be discarded as needed.
- MEM_DISCARDABLE: u1 = 0,
+ /// The section can be discarded as needed.
+ MEM_DISCARDABLE: bool = false,
- /// The section cannot be cached.
- MEM_NOT_CACHED: u1 = 0,
+ /// The section cannot be cached.
+ MEM_NOT_CACHED: bool = false,
- /// The section is not pageable.
- MEM_NOT_PAGED: u1 = 0,
+ /// The section is not pageable.
+ MEM_NOT_PAGED: bool = false,
- /// The section can be shared in memory.
- MEM_SHARED: u1 = 0,
+ /// The section can be shared in memory.
+ MEM_SHARED: bool = false,
- /// The section can be executed as code.
- MEM_EXECUTE: u1 = 0,
+ /// The section can be executed as code.
+ MEM_EXECUTE: bool = false,
- /// The section can be read.
- MEM_READ: u1 = 0,
+ /// The section can be read.
+ MEM_READ: bool = false,
- /// The section can be written to.
- MEM_WRITE: u1 = 0,
+ /// The section can be written to.
+ MEM_WRITE: bool = false,
+
+ pub const Align = enum(u4) {
+ NONE = 0,
+ @"1BYTES" = 1,
+ @"2BYTES" = 2,
+ @"4BYTES" = 3,
+ @"8BYTES" = 4,
+ @"16BYTES" = 5,
+ @"32BYTES" = 6,
+ @"64BYTES" = 7,
+ @"128BYTES" = 8,
+ @"256BYTES" = 9,
+ @"512BYTES" = 10,
+ @"1024BYTES" = 11,
+ @"2048BYTES" = 12,
+ @"4096BYTES" = 13,
+ @"8192BYTES" = 14,
+ _,
+
+ pub fn toByteUnits(a: Align) ?u16 {
+ if (a == .NONE) return null;
+ return @as(u16, 1) << (@intFromEnum(a) - 1);
+ }
+
+ pub fn fromByteUnits(n: u16) Align {
+ std.debug.assert(std.math.isPowerOfTwo(n));
+ return @enumFromInt(@ctz(n) + 1);
+ }
+ };
+ };
};
pub const Symbol = struct {
@@ -691,7 +654,7 @@ pub const SectionNumber = enum(u16) {
_,
};
-pub const SymType = packed struct {
+pub const SymType = packed struct(u16) {
complex_type: ComplexType,
base_type: BaseType,
};
@@ -921,6 +884,10 @@ pub const WeakExternalDefinition = struct {
flag: WeakExternalFlag,
unused: [10]u8,
+
+ pub fn sizeOf() usize {
+ return 18;
+ }
};
// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/km/ntimage.h
@@ -982,87 +949,7 @@ pub const DebugInfoDefinition = struct {
unused_3: [2]u8,
};
-pub const MachineType = enum(u16) {
- UNKNOWN = 0x0,
- /// Alpha AXP, 32-bit address space
- ALPHA = 0x184,
- /// Alpha 64, 64-bit address space
- ALPHA64 = 0x284,
- /// Matsushita AM33
- AM33 = 0x1d3,
- /// x64
- X64 = 0x8664,
- /// ARM little endian
- ARM = 0x1c0,
- /// ARM64 little endian
- ARM64 = 0xaa64,
- /// ARM64EC
- ARM64EC = 0xa641,
- /// ARM64X
- ARM64X = 0xa64e,
- /// ARM Thumb-2 little endian
- ARMNT = 0x1c4,
- /// CEE
- CEE = 0xc0ee,
- /// CEF
- CEF = 0xcef,
- /// Hybrid PE
- CHPE_X86 = 0x3a64,
- /// EFI byte code
- EBC = 0xebc,
- /// Intel 386 or later processors and compatible processors
- I386 = 0x14c,
- /// Intel Itanium processor family
- IA64 = 0x200,
- /// LoongArch32
- LOONGARCH32 = 0x6232,
- /// LoongArch64
- LOONGARCH64 = 0x6264,
- /// Mitsubishi M32R little endian
- M32R = 0x9041,
- /// MIPS16
- MIPS16 = 0x266,
- /// MIPS with FPU
- MIPSFPU = 0x366,
- /// MIPS16 with FPU
- MIPSFPU16 = 0x466,
- /// Power PC little endian
- POWERPC = 0x1f0,
- /// Power PC with floating point support
- POWERPCFP = 0x1f1,
- /// MIPS little endian
- R3000 = 0x162,
- /// MIPS little endian
- R4000 = 0x166,
- /// MIPS little endian
- R10000 = 0x168,
- /// RISC-V 32-bit address space
- RISCV32 = 0x5032,
- /// RISC-V 64-bit address space
- RISCV64 = 0x5064,
- /// RISC-V 128-bit address space
- RISCV128 = 0x5128,
- /// Hitachi SH3
- SH3 = 0x1a2,
- /// Hitachi SH3 DSP
- SH3DSP = 0x1a3,
- /// SH3E little-endian
- SH3E = 0x1a4,
- /// Hitachi SH4
- SH4 = 0x1a6,
- /// Hitachi SH5
- SH5 = 0x1a8,
- /// Thumb
- THUMB = 0x1c2,
- /// Infineon
- TRICORE = 0x520,
- /// MIPS little-endian WCE v2
- WCEMIPSV2 = 0x169,
-
- _,
-};
-
-pub const CoffError = error{
+pub const Error = error{
InvalidPEMagic,
InvalidPEHeader,
InvalidMachine,
@@ -1083,27 +970,28 @@ pub const Coff = struct {
age: u32 = undefined,
// The lifetime of `data` must be longer than the lifetime of the returned Coff
- pub fn init(data: []const u8, is_loaded: bool) !Coff {
+ pub fn init(data: []const u8, is_loaded: bool) error{ EndOfStream, MissingPEHeader }!Coff {
const pe_pointer_offset = 0x3C;
const pe_magic = "PE\x00\x00";
- var reader: std.Io.Reader = .fixed(data);
- reader.seek = pe_pointer_offset;
- const coff_header_offset = try reader.takeInt(u32, .little);
- reader.seek = coff_header_offset;
- const is_image = mem.eql(u8, pe_magic, try reader.takeArray(4));
+ if (data.len < pe_pointer_offset + 4) return error.EndOfStream;
+ const header_offset = mem.readInt(u32, data[pe_pointer_offset..][0..4], .little);
+ if (data.len < header_offset + 4) return error.EndOfStream;
+ const is_image = mem.eql(u8, data[header_offset..][0..4], pe_magic);
- var coff = @This(){
+ const coff: Coff = .{
.data = data,
.is_image = is_image,
.is_loaded = is_loaded,
- .coff_header_offset = coff_header_offset,
+ .coff_header_offset = o: {
+ if (is_image) break :o header_offset + 4;
+ break :o header_offset;
+ },
};
// Do some basic validation upfront
if (is_image) {
- coff.coff_header_offset = coff.coff_header_offset + 4;
- const coff_header = coff.getCoffHeader();
+ const coff_header = coff.getHeader();
if (coff_header.size_of_optional_header == 0) return error.MissingPEHeader;
}
@@ -1117,9 +1005,9 @@ pub const Coff = struct {
assert(self.is_image);
const data_dirs = self.getDataDirectories();
- if (@intFromEnum(DirectoryEntry.DEBUG) >= data_dirs.len) return null;
+ if (@intFromEnum(IMAGE.DIRECTORY_ENTRY.DEBUG) >= data_dirs.len) return null;
- const debug_dir = data_dirs[@intFromEnum(DirectoryEntry.DEBUG)];
+ const debug_dir = data_dirs[@intFromEnum(IMAGE.DIRECTORY_ENTRY.DEBUG)];
var reader: std.Io.Reader = .fixed(self.data);
if (self.is_loaded) {
@@ -1160,31 +1048,31 @@ pub const Coff = struct {
return self.data[start .. start + len];
}
- pub fn getCoffHeader(self: Coff) CoffHeader {
- return @as(*align(1) const CoffHeader, @ptrCast(self.data[self.coff_header_offset..][0..@sizeOf(CoffHeader)])).*;
+ pub fn getHeader(self: Coff) Header {
+ return @as(*align(1) const Header, @ptrCast(self.data[self.coff_header_offset..][0..@sizeOf(Header)])).*;
}
pub fn getOptionalHeader(self: Coff) OptionalHeader {
assert(self.is_image);
- const offset = self.coff_header_offset + @sizeOf(CoffHeader);
+ const offset = self.coff_header_offset + @sizeOf(Header);
return @as(*align(1) const OptionalHeader, @ptrCast(self.data[offset..][0..@sizeOf(OptionalHeader)])).*;
}
- pub fn getOptionalHeader32(self: Coff) OptionalHeaderPE32 {
+ pub fn getOptionalHeader32(self: Coff) OptionalHeader.PE32 {
assert(self.is_image);
- const offset = self.coff_header_offset + @sizeOf(CoffHeader);
- return @as(*align(1) const OptionalHeaderPE32, @ptrCast(self.data[offset..][0..@sizeOf(OptionalHeaderPE32)])).*;
+ const offset = self.coff_header_offset + @sizeOf(Header);
+ return @as(*align(1) const OptionalHeader.PE32, @ptrCast(self.data[offset..][0..@sizeOf(OptionalHeader.PE32)])).*;
}
- pub fn getOptionalHeader64(self: Coff) OptionalHeaderPE64 {
+ pub fn getOptionalHeader64(self: Coff) OptionalHeader.@"PE32+" {
assert(self.is_image);
- const offset = self.coff_header_offset + @sizeOf(CoffHeader);
- return @as(*align(1) const OptionalHeaderPE64, @ptrCast(self.data[offset..][0..@sizeOf(OptionalHeaderPE64)])).*;
+ const offset = self.coff_header_offset + @sizeOf(Header);
+ return @as(*align(1) const OptionalHeader.@"PE32+", @ptrCast(self.data[offset..][0..@sizeOf(OptionalHeader.@"PE32+")])).*;
}
pub fn getImageBase(self: Coff) u64 {
const hdr = self.getOptionalHeader();
- return switch (hdr.magic) {
+ return switch (@intFromEnum(hdr.magic)) {
IMAGE_NT_OPTIONAL_HDR32_MAGIC => self.getOptionalHeader32().image_base,
IMAGE_NT_OPTIONAL_HDR64_MAGIC => self.getOptionalHeader64().image_base,
else => unreachable, // We assume we have validated the header already
@@ -1193,7 +1081,7 @@ pub const Coff = struct {
pub fn getNumberOfDataDirectories(self: Coff) u32 {
const hdr = self.getOptionalHeader();
- return switch (hdr.magic) {
+ return switch (@intFromEnum(hdr.magic)) {
IMAGE_NT_OPTIONAL_HDR32_MAGIC => self.getOptionalHeader32().number_of_rva_and_sizes,
IMAGE_NT_OPTIONAL_HDR64_MAGIC => self.getOptionalHeader64().number_of_rva_and_sizes,
else => unreachable, // We assume we have validated the header already
@@ -1202,17 +1090,17 @@ pub const Coff = struct {
pub fn getDataDirectories(self: *const Coff) []align(1) const ImageDataDirectory {
const hdr = self.getOptionalHeader();
- const size: usize = switch (hdr.magic) {
- IMAGE_NT_OPTIONAL_HDR32_MAGIC => @sizeOf(OptionalHeaderPE32),
- IMAGE_NT_OPTIONAL_HDR64_MAGIC => @sizeOf(OptionalHeaderPE64),
+ const size: usize = switch (@intFromEnum(hdr.magic)) {
+ IMAGE_NT_OPTIONAL_HDR32_MAGIC => @sizeOf(OptionalHeader.PE32),
+ IMAGE_NT_OPTIONAL_HDR64_MAGIC => @sizeOf(OptionalHeader.@"PE32+"),
else => unreachable, // We assume we have validated the header already
};
- const offset = self.coff_header_offset + @sizeOf(CoffHeader) + size;
+ const offset = self.coff_header_offset + @sizeOf(Header) + size;
return @as([*]align(1) const ImageDataDirectory, @ptrCast(self.data[offset..]))[0..self.getNumberOfDataDirectories()];
}
pub fn getSymtab(self: *const Coff) ?Symtab {
- const coff_header = self.getCoffHeader();
+ const coff_header = self.getHeader();
if (coff_header.pointer_to_symbol_table == 0) return null;
const offset = coff_header.pointer_to_symbol_table;
@@ -1221,7 +1109,7 @@ pub const Coff = struct {
}
pub fn getStrtab(self: *const Coff) error{InvalidStrtabSize}!?Strtab {
- const coff_header = self.getCoffHeader();
+ const coff_header = self.getHeader();
if (coff_header.pointer_to_symbol_table == 0) return null;
const offset = coff_header.pointer_to_symbol_table + Symbol.sizeOf() * coff_header.number_of_symbols;
@@ -1237,8 +1125,8 @@ pub const Coff = struct {
}
pub fn getSectionHeaders(self: *const Coff) []align(1) const SectionHeader {
- const coff_header = self.getCoffHeader();
- const offset = self.coff_header_offset + @sizeOf(CoffHeader) + coff_header.size_of_optional_header;
+ const coff_header = self.getHeader();
+ const offset = self.coff_header_offset + @sizeOf(Header) + coff_header.size_of_optional_header;
return @as([*]align(1) const SectionHeader, @ptrCast(self.data.ptr + offset))[0..coff_header.number_of_sections];
}
@@ -1413,14 +1301,16 @@ pub const Strtab = struct {
};
pub const ImportHeader = extern struct {
- sig1: MachineType,
- sig2: u16,
+ /// Must be IMAGE_FILE_MACHINE_UNKNOWN
+ sig1: IMAGE.FILE.MACHINE = .UNKNOWN,
+ /// Must be 0xFFFF
+ sig2: u16 = 0xFFFF,
version: u16,
- machine: MachineType,
+ machine: IMAGE.FILE.MACHINE,
time_date_stamp: u32,
size_of_data: u32,
hint: u16,
- types: packed struct {
+ types: packed struct(u16) {
type: ImportType,
name_type: ImportNameType,
reserved: u11,
@@ -1460,119 +1350,572 @@ pub const Relocation = extern struct {
type: u16,
};
-pub const ImageRelAmd64 = enum(u16) {
- /// The relocation is ignored.
- absolute = 0,
-
- /// The 64-bit VA of the relocation target.
- addr64 = 1,
-
- /// The 32-bit VA of the relocation target.
- addr32 = 2,
-
- /// The 32-bit address without an image base.
- addr32nb = 3,
-
- /// The 32-bit relative address from the byte following the relocation.
- rel32 = 4,
-
- /// The 32-bit address relative to byte distance 1 from the relocation.
- rel32_1 = 5,
-
- /// The 32-bit address relative to byte distance 2 from the relocation.
- rel32_2 = 6,
-
- /// The 32-bit address relative to byte distance 3 from the relocation.
- rel32_3 = 7,
-
- /// The 32-bit address relative to byte distance 4 from the relocation.
- rel32_4 = 8,
-
- /// The 32-bit address relative to byte distance 5 from the relocation.
- rel32_5 = 9,
-
- /// The 16-bit section index of the section that contains the target.
- /// This is used to support debugging information.
- section = 10,
-
- /// The 32-bit offset of the target from the beginning of its section.
- /// This is used to support debugging information and static thread local storage.
- secrel = 11,
-
- /// A 7-bit unsigned offset from the base of the section that contains the target.
- secrel7 = 12,
-
- /// CLR tokens.
- token = 13,
-
- /// A 32-bit signed span-dependent value emitted into the object.
- srel32 = 14,
-
- /// A pair that must immediately follow every span-dependent value.
- pair = 15,
-
- /// A 32-bit signed span-dependent value that is applied at link time.
- sspan32 = 16,
-
- _,
-};
-
-pub const ImageRelArm64 = enum(u16) {
- /// The relocation is ignored.
- absolute = 0,
-
- /// The 32-bit VA of the target.
- addr32 = 1,
-
- /// The 32-bit RVA of the target.
- addr32nb = 2,
-
- /// The 26-bit relative displacement to the target, for B and BL instructions.
- branch26 = 3,
-
- /// The page base of the target, for ADRP instruction.
- pagebase_rel21 = 4,
-
- /// The 21-bit relative displacement to the target, for instruction ADR.
- rel21 = 5,
-
- /// The 12-bit page offset of the target, for instructions ADD/ADDS (immediate) with zero shift.
- pageoffset_12a = 6,
-
- /// The 12-bit page offset of the target, for instruction LDR (indexed, unsigned immediate).
- pageoffset_12l = 7,
-
- /// The 32-bit offset of the target from the beginning of its section.
- /// This is used to support debugging information and static thread local storage.
- secrel = 8,
+pub const IMAGE = struct {
+ pub const DIRECTORY_ENTRY = enum(u32) {
+ /// Export Directory
+ EXPORT = 0,
+ /// Import Directory
+ IMPORT = 1,
+ /// Resource Directory
+ RESOURCE = 2,
+ /// Exception Directory
+ EXCEPTION = 3,
+ /// Security Directory
+ SECURITY = 4,
+ /// Base Relocation Table
+ BASERELOC = 5,
+ /// Debug Directory
+ DEBUG = 6,
+ /// Architecture Specific Data
+ ARCHITECTURE = 7,
+ /// RVA of GP
+ GLOBALPTR = 8,
+ /// TLS Directory
+ TLS = 9,
+ /// Load Configuration Directory
+ LOAD_CONFIG = 10,
+ /// Bound Import Directory in headers
+ BOUND_IMPORT = 11,
+ /// Import Address Table
+ IAT = 12,
+ /// Delay Load Import Descriptors
+ DELAY_IMPORT = 13,
+ /// COM Runtime descriptor
+ COM_DESCRIPTOR = 14,
+ /// must be zero
+ RESERVED = 15,
+ _,
+
+ pub const len = @typeInfo(IMAGE.DIRECTORY_ENTRY).@"enum".fields.len;
+ };
- /// Bit 0:11 of section offset of the target for instructions ADD/ADDS (immediate) with zero shift.
- low12a = 9,
+ pub const FILE = struct {
+ /// Machine Types
+ /// The Machine field has one of the following values, which specify the CPU type.
+ /// An image file can be run only on the specified machine or on a system that emulates the specified machine.
+ pub const MACHINE = enum(u16) {
+ /// The content of this field is assumed to be applicable to any machine type
+ UNKNOWN = 0x0,
+ /// Alpha AXP, 32-bit address space
+ ALPHA = 0x184,
+ /// Alpha 64, 64-bit address space
+ ALPHA64 = 0x284,
+ /// Matsushita AM33
+ AM33 = 0x1d3,
+ /// x64
+ AMD64 = 0x8664,
+ /// ARM little endian
+ ARM = 0x1c0,
+ /// ARM64 little endian
+ ARM64 = 0xaa64,
+ /// ABI that enables interoperability between native ARM64 and emulated x64 code.
+ ARM64EC = 0xA641,
+ /// Binary format that allows both native ARM64 and ARM64EC code to coexist in the same file.
+ ARM64X = 0xA64E,
+ /// ARM Thumb-2 little endian
+ ARMNT = 0x1c4,
+ /// EFI byte code
+ EBC = 0xebc,
+ /// Intel 386 or later processors and compatible processors
+ I386 = 0x14c,
+ /// Intel Itanium processor family
+ IA64 = 0x200,
+ /// LoongArch 32-bit processor family
+ LOONGARCH32 = 0x6232,
+ /// LoongArch 64-bit processor family
+ LOONGARCH64 = 0x6264,
+ /// Mitsubishi M32R little endian
+ M32R = 0x9041,
+ /// MIPS16
+ MIPS16 = 0x266,
+ /// MIPS with FPU
+ MIPSFPU = 0x366,
+ /// MIPS16 with FPU
+ MIPSFPU16 = 0x466,
+ /// Power PC little endian
+ POWERPC = 0x1f0,
+ /// Power PC with floating point support
+ POWERPCFP = 0x1f1,
+ /// MIPS I compatible 32-bit big endian
+ R3000BE = 0x160,
+ /// MIPS I compatible 32-bit little endian
+ R3000 = 0x162,
+ /// MIPS III compatible 64-bit little endian
+ R4000 = 0x166,
+ /// MIPS IV compatible 64-bit little endian
+ R10000 = 0x168,
+ /// RISC-V 32-bit address space
+ RISCV32 = 0x5032,
+ /// RISC-V 64-bit address space
+ RISCV64 = 0x5064,
+ /// RISC-V 128-bit address space
+ RISCV128 = 0x5128,
+ /// Hitachi SH3
+ SH3 = 0x1a2,
+ /// Hitachi SH3 DSP
+ SH3DSP = 0x1a3,
+ /// Hitachi SH4
+ SH4 = 0x1a6,
+ /// Hitachi SH5
+ SH5 = 0x1a8,
+ /// Thumb
+ THUMB = 0x1c2,
+ /// MIPS little-endian WCE v2
+ WCEMIPSV2 = 0x169,
+ _,
+ /// AXP 64 (Same as Alpha 64)
+ pub const AXP64: IMAGE.FILE.MACHINE = .ALPHA64;
+ };
+ };
- /// Bit 12:23 of section offset of the target, for instructions ADD/ADDS (immediate) with zero shift.
- high12a = 10,
+ pub const REL = struct {
+ /// x64 Processors
+ /// The following relocation type indicators are defined for x64 and compatible processors.
+ pub const AMD64 = enum(u16) {
+ /// The relocation is ignored.
+ ABSOLUTE = 0x0000,
+ /// The 64-bit VA of the relocation target.
+ ADDR64 = 0x0001,
+ /// The 32-bit VA of the relocation target.
+ ADDR32 = 0x0002,
+ /// The 32-bit address without an image base (RVA).
+ ADDR32NB = 0x0003,
+ /// The 32-bit relative address from the byte following the relocation.
+ REL32 = 0x0004,
+ /// The 32-bit address relative to byte distance 1 from the relocation.
+ REL32_1 = 0x0005,
+ /// The 32-bit address relative to byte distance 2 from the relocation.
+ REL32_2 = 0x0006,
+ /// The 32-bit address relative to byte distance 3 from the relocation.
+ REL32_3 = 0x0007,
+ /// The 32-bit address relative to byte distance 4 from the relocation.
+ REL32_4 = 0x0008,
+ /// The 32-bit address relative to byte distance 5 from the relocation.
+ REL32_5 = 0x0009,
+ /// The 16-bit section index of the section that contains the target.
+ /// This is used to support debugging information.
+ SECTION = 0x000A,
+ /// The 32-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ SECREL = 0x000B,
+ /// A 7-bit unsigned offset from the base of the section that contains the target.
+ SECREL7 = 0x000C,
+ /// CLR tokens.
+ TOKEN = 0x000D,
+ /// A 32-bit signed span-dependent value emitted into the object.
+ SREL32 = 0x000E,
+ /// A pair that must immediately follow every span-dependent value.
+ PAIR = 0x000F,
+ /// A 32-bit signed span-dependent value that is applied at link time.
+ SSPAN32 = 0x0010,
+ _,
+ };
- /// Bit 0:11 of section offset of the target, for instruction LDR (indexed, unsigned immediate).
- low12l = 11,
+ /// ARM Processors
+ /// The following relocation type indicators are defined for ARM processors.
+ pub const ARM = enum(u16) {
+ /// The relocation is ignored.
+ ABSOLUTE = 0x0000,
+ /// The 32-bit VA of the target.
+ ADDR32 = 0x0001,
+ /// The 32-bit RVA of the target.
+ ADDR32NB = 0x0002,
+ /// The 24-bit relative displacement to the target.
+ BRANCH24 = 0x0003,
+ /// The reference to a subroutine call.
+ /// The reference consists of two 16-bit instructions with 11-bit offsets.
+ BRANCH11 = 0x0004,
+ /// The 32-bit relative address from the byte following the relocation.
+ REL32 = 0x000A,
+ /// The 16-bit section index of the section that contains the target.
+ /// This is used to support debugging information.
+ SECTION = 0x000E,
+ /// The 32-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ SECREL = 0x000F,
+ /// The 32-bit VA of the target.
+ /// This relocation is applied using a MOVW instruction for the low 16 bits followed by a MOVT for the high 16 bits.
+ MOV32 = 0x0010,
+ /// The 32-bit VA of the target.
+ /// This relocation is applied using a MOVW instruction for the low 16 bits followed by a MOVT for the high 16 bits.
+ THUMB_MOV32 = 0x0011,
+ /// The instruction is fixed up with the 21-bit relative displacement to the 2-byte aligned target.
+ /// The least significant bit of the displacement is always zero and is not stored.
+ /// This relocation corresponds to a Thumb-2 32-bit conditional B instruction.
+ THUMB_BRANCH20 = 0x0012,
+ Unused = 0x0013,
+ /// The instruction is fixed up with the 25-bit relative displacement to the 2-byte aligned target.
+ /// The least significant bit of the displacement is zero and is not stored.This relocation corresponds to a Thumb-2 B instruction.
+ THUMB_BRANCH24 = 0x0014,
+ /// The instruction is fixed up with the 25-bit relative displacement to the 4-byte aligned target.
+ /// The low 2 bits of the displacement are zero and are not stored.
+ /// This relocation corresponds to a Thumb-2 BLX instruction.
+ THUMB_BLX23 = 0x0015,
+ /// The relocation is valid only when it immediately follows a ARM_REFHI or THUMB_REFHI.
+ /// Its SymbolTableIndex contains a displacement and not an index into the symbol table.
+ PAIR = 0x0016,
+ _,
+ };
- /// CLR token.
- token = 12,
+ /// ARM64 Processors
+ /// The following relocation type indicators are defined for ARM64 processors.
+ pub const ARM64 = enum(u16) {
+ /// The relocation is ignored.
+ ABSOLUTE = 0x0000,
+ /// The 32-bit VA of the target.
+ ADDR32 = 0x0001,
+ /// The 32-bit RVA of the target.
+ ADDR32NB = 0x0002,
+ /// The 26-bit relative displacement to the target, for B and BL instructions.
+ BRANCH26 = 0x0003,
+ /// The page base of the target, for ADRP instruction.
+ PAGEBASE_REL21 = 0x0004,
+ /// The 12-bit relative displacement to the target, for instruction ADR
+ REL21 = 0x0005,
+ /// The 12-bit page offset of the target, for instructions ADD/ADDS (immediate) with zero shift.
+ PAGEOFFSET_12A = 0x0006,
+ /// The 12-bit page offset of the target, for instruction LDR (indexed, unsigned immediate).
+ PAGEOFFSET_12L = 0x0007,
+ /// The 32-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ SECREL = 0x0008,
+ /// Bit 0:11 of section offset of the target, for instructions ADD/ADDS (immediate) with zero shift.
+ SECREL_LOW12A = 0x0009,
+ /// Bit 12:23 of section offset of the target, for instructions ADD/ADDS (immediate) with zero shift.
+ SECREL_HIGH12A = 0x000A,
+ /// Bit 0:11 of section offset of the target, for instruction LDR (indexed, unsigned immediate).
+ SECREL_LOW12L = 0x000B,
+ /// CLR token.
+ TOKEN = 0x000C,
+ /// The 16-bit section index of the section that contains the target.
+ /// This is used to support debugging information.
+ SECTION = 0x000D,
+ /// The 64-bit VA of the relocation target.
+ ADDR64 = 0x000E,
+ /// The 19-bit offset to the relocation target, for conditional B instruction.
+ BRANCH19 = 0x000F,
+ /// The 14-bit offset to the relocation target, for instructions TBZ and TBNZ.
+ BRANCH14 = 0x0010,
+ /// The 32-bit relative address from the byte following the relocation.
+ REL32 = 0x0011,
+ _,
+ };
- /// The 16-bit section index of the section that contains the target.
- /// This is used to support debugging information.
- section = 13,
+ /// Hitachi SuperH Processors
+ /// The following relocation type indicators are defined for SH3 and SH4 processors.
+ /// SH5-specific relocations are noted as SHM (SH Media).
+ pub const SH = enum(u16) {
+ /// The relocation is ignored.
+ @"3_ABSOLUTE" = 0x0000,
+ /// A reference to the 16-bit location that contains the VA of the target symbol.
+ @"3_DIRECT16" = 0x0001,
+ /// The 32-bit VA of the target symbol.
+ @"3_DIRECT32" = 0x0002,
+ /// A reference to the 8-bit location that contains the VA of the target symbol.
+ @"3_DIRECT8" = 0x0003,
+ /// A reference to the 8-bit instruction that contains the effective 16-bit VA of the target symbol.
+ @"3_DIRECT8_WORD" = 0x0004,
+ /// A reference to the 8-bit instruction that contains the effective 32-bit VA of the target symbol.
+ @"3_DIRECT8_LONG" = 0x0005,
+ /// A reference to the 8-bit location whose low 4 bits contain the VA of the target symbol.
+ @"3_DIRECT4" = 0x0006,
+ /// A reference to the 8-bit instruction whose low 4 bits contain the effective 16-bit VA of the target symbol.
+ @"3_DIRECT4_WORD" = 0x0007,
+ /// A reference to the 8-bit instruction whose low 4 bits contain the effective 32-bit VA of the target symbol.
+ @"3_DIRECT4_LONG" = 0x0008,
+ /// A reference to the 8-bit instruction that contains the effective 16-bit relative offset of the target symbol.
+ @"3_PCREL8_WORD" = 0x0009,
+ /// A reference to the 8-bit instruction that contains the effective 32-bit relative offset of the target symbol.
+ @"3_PCREL8_LONG" = 0x000A,
+ /// A reference to the 16-bit instruction whose low 12 bits contain the effective 16-bit relative offset of the target symbol.
+ @"3_PCREL12_WORD" = 0x000B,
+ /// A reference to a 32-bit location that is the VA of the section that contains the target symbol.
+ @"3_STARTOF_SECTION" = 0x000C,
+ /// A reference to the 32-bit location that is the size of the section that contains the target symbol.
+ @"3_SIZEOF_SECTION" = 0x000D,
+ /// The 16-bit section index of the section that contains the target.
+ /// This is used to support debugging information.
+ @"3_SECTION" = 0x000E,
+ /// The 32-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ @"3_SECREL" = 0x000F,
+ /// The 32-bit RVA of the target symbol.
+ @"3_DIRECT32_NB" = 0x0010,
+ /// GP relative.
+ @"3_GPREL4_LONG" = 0x0011,
+ /// CLR token.
+ @"3_TOKEN" = 0x0012,
+ /// The offset from the current instruction in longwords.
+ /// If the NOMODE bit is not set, insert the inverse of the low bit at bit 32 to select PTA or PTB.
+ M_PCRELPT = 0x0013,
+ /// The low 16 bits of the 32-bit address.
+ M_REFLO = 0x0014,
+ /// The high 16 bits of the 32-bit address.
+ M_REFHALF = 0x0015,
+ /// The low 16 bits of the relative address.
+ M_RELLO = 0x0016,
+ /// The high 16 bits of the relative address.
+ M_RELHALF = 0x0017,
+ /// The relocation is valid only when it immediately follows a REFHALF, RELHALF, or RELLO relocation.
+ /// The SymbolTableIndex field of the relocation contains a displacement and not an index into the symbol table.
+ M_PAIR = 0x0018,
+ /// The relocation ignores section mode.
+ M_NOMODE = 0x8000,
+ _,
+ };
- /// The 64-bit VA of the relocation target.
- addr64 = 14,
+ /// IBM PowerPC Processors
+ /// The following relocation type indicators are defined for PowerPC processors.
+ pub const PPC = enum(u16) {
+ /// The relocation is ignored.
+ ABSOLUTE = 0x0000,
+ /// The 64-bit VA of the target.
+ ADDR64 = 0x0001,
+ /// The 32-bit VA of the target.
+ ADDR32 = 0x0002,
+ /// The low 24 bits of the VA of the target.
+ /// This is valid only when the target symbol is absolute and can be sign-extended to its original value.
+ ADDR24 = 0x0003,
+ /// The low 16 bits of the target's VA.
+ ADDR16 = 0x0004,
+ /// The low 14 bits of the target's VA.
+ /// This is valid only when the target symbol is absolute and can be sign-extended to its original value.
+ ADDR14 = 0x0005,
+ /// A 24-bit PC-relative offset to the symbol's location.
+ REL24 = 0x0006,
+ /// A 14-bit PC-relative offset to the symbol's location.
+ REL14 = 0x0007,
+ /// The 32-bit RVA of the target.
+ ADDR32NB = 0x000A,
+ /// The 32-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ SECREL = 0x000B,
+ /// The 16-bit section index of the section that contains the target.
+ /// This is used to support debugging information.
+ SECTION = 0x000C,
+ /// The 16-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ SECREL16 = 0x000F,
+ /// The high 16 bits of the target's 32-bit VA.
+ /// This is used for the first instruction in a two-instruction sequence that loads a full address.
+ /// This relocation must be immediately followed by a PAIR relocation whose SymbolTableIndex contains a signed 16-bit displacement that is added to the upper 16 bits that was taken from the location that is being relocated.
+ REFHI = 0x0010,
+ /// The low 16 bits of the target's VA.
+ REFLO = 0x0011,
+ /// A relocation that is valid only when it immediately follows a REFHI or SECRELHI relocation.
+ /// Its SymbolTableIndex contains a displacement and not an index into the symbol table.
+ PAIR = 0x0012,
+ /// The low 16 bits of the 32-bit offset of the target from the beginning of its section.
+ SECRELLO = 0x0013,
+ /// The 16-bit signed displacement of the target relative to the GP register.
+ GPREL = 0x0015,
+ /// The CLR token.
+ TOKEN = 0x0016,
+ _,
+ };
- /// The 19-bit offset to the relocation target, for conditional B instruction.
- branch19 = 15,
+ /// Intel 386 Processors
+ /// The following relocation type indicators are defined for Intel 386 and compatible processors.
+ pub const I386 = enum(u16) {
+ /// The relocation is ignored.
+ ABSOLUTE = 0x0000,
+ /// Not supported.
+ DIR16 = 0x0001,
+ /// Not supported.
+ REL16 = 0x0002,
+ /// The target's 32-bit VA.
+ DIR32 = 0x0006,
+ /// The target's 32-bit RVA.
+ DIR32NB = 0x0007,
+ /// Not supported.
+ SEG12 = 0x0009,
+ /// The 16-bit section index of the section that contains the target.
+ /// This is used to support debugging information.
+ SECTION = 0x000A,
+ /// The 32-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ SECREL = 0x000B,
+ /// The CLR token.
+ TOKEN = 0x000C,
+ /// A 7-bit offset from the base of the section that contains the target.
+ SECREL7 = 0x000D,
+ /// The 32-bit relative displacement to the target.
+ /// This supports the x86 relative branch and call instructions.
+ REL32 = 0x0014,
+ _,
+ };
- /// The 14-bit offset to the relocation target, for instructions TBZ and TBNZ.
- branch14 = 16,
+ /// Intel Itanium Processor Family (IPF)
+ /// The following relocation type indicators are defined for the Intel Itanium processor family and compatible processors.
+ /// Note that relocations on instructions use the bundle's offset and slot number for the relocation offset.
+ pub const IA64 = enum(u16) {
+ /// The relocation is ignored.
+ ABSOLUTE = 0x0000,
+ /// The instruction relocation can be followed by an ADDEND relocation whose value is added to the target address before it is inserted into the specified slot in the IMM14 bundle.
+ /// The relocation target must be absolute or the image must be fixed.
+ IMM14 = 0x0001,
+ /// The instruction relocation can be followed by an ADDEND relocation whose value is added to the target address before it is inserted into the specified slot in the IMM22 bundle.
+ /// The relocation target must be absolute or the image must be fixed.
+ IMM22 = 0x0002,
+ /// The slot number of this relocation must be one (1).
+ /// The relocation can be followed by an ADDEND relocation whose value is added to the target address before it is stored in all three slots of the IMM64 bundle.
+ IMM64 = 0x0003,
+ /// The target's 32-bit VA.
+ /// This is supported only for /LARGEADDRESSAWARE:NO images.
+ DIR32 = 0x0004,
+ /// The target's 64-bit VA.
+ DIR64 = 0x0005,
+ /// The instruction is fixed up with the 25-bit relative displacement to the 16-bit aligned target.
+ /// The low 4 bits of the displacement are zero and are not stored.
+ PCREL21B = 0x0006,
+ /// The instruction is fixed up with the 25-bit relative displacement to the 16-bit aligned target.
+ /// The low 4 bits of the displacement, which are zero, are not stored.
+ PCREL21M = 0x0007,
+ /// The LSBs of this relocation's offset must contain the slot number whereas the rest is the bundle address.
+ /// The bundle is fixed up with the 25-bit relative displacement to the 16-bit aligned target.
+ /// The low 4 bits of the displacement are zero and are not stored.
+ PCREL21F = 0x0008,
+ /// The instruction relocation can be followed by an ADDEND relocation whose value is added to the target address and then a 22-bit GP-relative offset that is calculated and applied to the GPREL22 bundle.
+ GPREL22 = 0x0009,
+ /// The instruction is fixed up with the 22-bit GP-relative offset to the target symbol's literal table entry.
+ /// The linker creates this literal table entry based on this relocation and the ADDEND relocation that might follow.
+ LTOFF22 = 0x000A,
+ /// The 16-bit section index of the section contains the target.
+ /// This is used to support debugging information.
+ SECTION = 0x000B,
+ /// The instruction is fixed up with the 22-bit offset of the target from the beginning of its section.
+ /// This relocation can be followed immediately by an ADDEND relocation, whose Value field contains the 32-bit unsigned offset of the target from the beginning of the section.
+ SECREL22 = 0x000C,
+ /// The slot number for this relocation must be one (1).
+ /// The instruction is fixed up with the 64-bit offset of the target from the beginning of its section.
+ /// This relocation can be followed immediately by an ADDEND relocation whose Value field contains the 32-bit unsigned offset of the target from the beginning of the section.
+ SECREL64I = 0x000D,
+ /// The address of data to be fixed up with the 32-bit offset of the target from the beginning of its section.
+ SECREL32 = 0x000E,
+ /// The target's 32-bit RVA.
+ DIR32NB = 0x0010,
+ /// This is applied to a signed 14-bit immediate that contains the difference between two relocatable targets.
+ /// This is a declarative field for the linker that indicates that the compiler has already emitted this value.
+ SREL14 = 0x0011,
+ /// This is applied to a signed 22-bit immediate that contains the difference between two relocatable targets.
+ /// This is a declarative field for the linker that indicates that the compiler has already emitted this value.
+ SREL22 = 0x0012,
+ /// This is applied to a signed 32-bit immediate that contains the difference between two relocatable values.
+ /// This is a declarative field for the linker that indicates that the compiler has already emitted this value.
+ SREL32 = 0x0013,
+ /// This is applied to an unsigned 32-bit immediate that contains the difference between two relocatable values.
+ /// This is a declarative field for the linker that indicates that the compiler has already emitted this value.
+ UREL32 = 0x0014,
+ /// A 60-bit PC-relative fixup that always stays as a BRL instruction of an MLX bundle.
+ PCREL60X = 0x0015,
+ /// A 60-bit PC-relative fixup.
+ /// If the target displacement fits in a signed 25-bit field, convert the entire bundle to an MBB bundle with NOP.B in slot 1 and a 25-bit BR instruction (with the 4 lowest bits all zero and dropped) in slot 2.
+ PCREL60B = 0x0016,
+ /// A 60-bit PC-relative fixup.
+ /// If the target displacement fits in a signed 25-bit field, convert the entire bundle to an MFB bundle with NOP.F in slot 1 and a 25-bit (4 lowest bits all zero and dropped) BR instruction in slot 2.
+ PCREL60F = 0x0017,
+ /// A 60-bit PC-relative fixup.
+ /// If the target displacement fits in a signed 25-bit field, convert the entire bundle to an MIB bundle with NOP.I in slot 1 and a 25-bit (4 lowest bits all zero and dropped) BR instruction in slot 2.
+ PCREL60I = 0x0018,
+ /// A 60-bit PC-relative fixup.
+ /// If the target displacement fits in a signed 25-bit field, convert the entire bundle to an MMB bundle with NOP.M in slot 1 and a 25-bit (4 lowest bits all zero and dropped) BR instruction in slot 2.
+ PCREL60M = 0x0019,
+ /// A 64-bit GP-relative fixup.
+ IMMGPREL64 = 0x001a,
+ /// A CLR token.
+ TOKEN = 0x001b,
+ /// A 32-bit GP-relative fixup.
+ GPREL32 = 0x001c,
+ /// The relocation is valid only when it immediately follows one of the following relocations: IMM14, IMM22, IMM64, GPREL22, LTOFF22, LTOFF64, SECREL22, SECREL64I, or SECREL32.
+ /// Its value contains the addend to apply to instructions within a bundle, not for data.
+ ADDEND = 0x001F,
+ _,
+ };
- /// The 32-bit relative address from the byte following the relocation.
- rel32 = 17,
+ /// MIPS Processors
+ /// The following relocation type indicators are defined for MIPS processors.
+ pub const MIPS = enum(u16) {
+ /// The relocation is ignored.
+ ABSOLUTE = 0x0000,
+ /// The high 16 bits of the target's 32-bit VA.
+ REFHALF = 0x0001,
+ /// The target's 32-bit VA.
+ REFWORD = 0x0002,
+ /// The low 26 bits of the target's VA.
+ /// This supports the MIPS J and JAL instructions.
+ JMPADDR = 0x0003,
+ /// The high 16 bits of the target's 32-bit VA.
+ /// This is used for the first instruction in a two-instruction sequence that loads a full address.
+ /// This relocation must be immediately followed by a PAIR relocation whose SymbolTableIndex contains a signed 16-bit displacement that is added to the upper 16 bits that are taken from the location that is being relocated.
+ REFHI = 0x0004,
+ /// The low 16 bits of the target's VA.
+ REFLO = 0x0005,
+ /// A 16-bit signed displacement of the target relative to the GP register.
+ GPREL = 0x0006,
+ /// The same as IMAGE_REL_MIPS_GPREL.
+ LITERAL = 0x0007,
+ /// The 16-bit section index of the section contains the target.
+ /// This is used to support debugging information.
+ SECTION = 0x000A,
+ /// The 32-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ SECREL = 0x000B,
+ /// The low 16 bits of the 32-bit offset of the target from the beginning of its section.
+ SECRELLO = 0x000C,
+ /// The high 16 bits of the 32-bit offset of the target from the beginning of its section.
+ /// An IMAGE_REL_MIPS_PAIR relocation must immediately follow this one.
+ /// The SymbolTableIndex of the PAIR relocation contains a signed 16-bit displacement that is added to the upper 16 bits that are taken from the location that is being relocated.
+ SECRELHI = 0x000D,
+ /// The low 26 bits of the target's VA.
+ /// This supports the MIPS16 JAL instruction.
+ JMPADDR16 = 0x0010,
+ /// The target's 32-bit RVA.
+ REFWORDNB = 0x0022,
+ /// The relocation is valid only when it immediately follows a REFHI or SECRELHI relocation.
+ /// Its SymbolTableIndex contains a displacement and not an index into the symbol table.
+ PAIR = 0x0025,
+ _,
+ };
- _,
+ /// Mitsubishi M32R
+ /// The following relocation type indicators are defined for the Mitsubishi M32R processors.
+ pub const M32R = enum(u16) {
+ /// The relocation is ignored.
+ ABSOLUTE = 0x0000,
+ /// The target's 32-bit VA.
+ ADDR32 = 0x0001,
+ /// The target's 32-bit RVA.
+ ADDR32NB = 0x0002,
+ /// The target's 24-bit VA.
+ ADDR24 = 0x0003,
+ /// The target's 16-bit offset from the GP register.
+ GPREL16 = 0x0004,
+ /// The target's 24-bit offset from the program counter (PC), shifted left by 2 bits and sign-extended
+ PCREL24 = 0x0005,
+ /// The target's 16-bit offset from the PC, shifted left by 2 bits and sign-extended
+ PCREL16 = 0x0006,
+ /// The target's 8-bit offset from the PC, shifted left by 2 bits and sign-extended
+ PCREL8 = 0x0007,
+ /// The 16 MSBs of the target VA.
+ REFHALF = 0x0008,
+ /// The 16 MSBs of the target VA, adjusted for LSB sign extension.
+ /// This is used for the first instruction in a two-instruction sequence that loads a full 32-bit address.
+ /// This relocation must be immediately followed by a PAIR relocation whose SymbolTableIndex contains a signed 16-bit displacement that is added to the upper 16 bits that are taken from the location that is being relocated.
+ REFHI = 0x0009,
+ /// The 16 LSBs of the target VA.
+ REFLO = 0x000A,
+ /// The relocation must follow the REFHI relocation.
+ /// Its SymbolTableIndex contains a displacement and not an index into the symbol table.
+ PAIR = 0x000B,
+ /// The 16-bit section index of the section that contains the target.
+ /// This is used to support debugging information.
+ SECTION = 0x000C,
+ /// The 32-bit offset of the target from the beginning of its section.
+ /// This is used to support debugging information and static thread local storage.
+ SECREL = 0x000D,
+ /// The CLR token.
+ TOKEN = 0x000E,
+ _,
+ };
+ };
};