tmp/
pecoff.rs

1//! Portable Executable / Common Object File Format
2//!
3//! The Portable Executable format (PE, PE/COFF, PE32, PE32+) encodes
4//! executable and library code on platforms like Microsoft Windows, UEFI, and
5//! others. The COFF format originates in UNIX but was later adopted and
6//! extended into PE by Microsoft. Apart from the latter, the format has been
7//! widely abandonded and replaced by the Executable and Linker Format (ELF).
8//!
9//! The COFF format is still used for object files and linker input. The PE
10//! format extends COFF slightly to allow MS-DOS stubs to be linked in front
11//! of the COFF executable. The name Portable Executable refers to the fact
12//! that the format is meant to be architecture independent.
13//!
14//! The format was further extended to support offsets larger than 32bit,
15//! paving the way for adoption on 64 bit machines. Files encoded in the
16//! extended format are called PE32+.
17//!
18//! XXX: This module is still incomplete.
19
20type U8Le = osi::ffi::Integer<osi::ffi::LittleEndian<u8>, osi::align::AlignAs<1>>;
21type U16Le = osi::ffi::Integer<osi::ffi::LittleEndian<u16>, osi::align::AlignAs<2>>;
22type U32Le = osi::ffi::Integer<osi::ffi::LittleEndian<u32>, osi::align::AlignAs<4>>;
23type U64Le = osi::ffi::Integer<osi::ffi::LittleEndian<u64>, osi::align::AlignAs<8>>;
24
25pub const INVALID_TIMESTAMPS: [u32; 2] = [0x00000000, 0xffffffff];
26
27pub const PE_MAGIC: [u8; 4] = [0x50, 0x45, 0x00, 0x00];
28pub const PE_MAGIC_OH32: u16 = 0x010b;
29pub const PE_MAGIC_OH32P: u16 = 0x010b;
30
31pub const PE_OFFSET: usize = 0x3c;
32
33pub const CHARACTERISTIC_RELOCS_STRIPPED: u16 = 0x0001;
34pub const CHARACTERISTIC_EXECUTABLE_IMAGE: u16 = 0x0002;
35pub const CHARACTERISTIC_LINE_NUMS_STRIPPED: u16 = 0x0004;
36pub const CHARACTERISTIC_LOCAL_SYMS_STRIPPED: u16 = 0x0008;
37pub const CHARACTERISTIC_AGGRESSIVE_WS_TRIM: u16 = 0x0010;
38pub const CHARACTERISTIC_LARGE_ADDRESS_AWARE: u16 = 0x0020;
39/* reserved: 0x0040 */
40pub const CHARACTERISTIC_BYTES_REVERSED_LO: u16 = 0x0080;
41pub const CHARACTERISTIC_32BIT_MACHINE: u16 = 0x0100;
42pub const CHARACTERISTIC_DEBUG_STRIPPED: u16 = 0x0200;
43pub const CHARACTERISTIC_REMOVABLE_RUN_FROM_SWAP: u16 = 0x0400;
44pub const CHARACTERISTIC_NET_RUN_FROM_SWAP: u16 = 0x0800;
45pub const CHARACTERISTIC_SYSTEM: u16 = 0x1000;
46pub const CHARACTERISTIC_DLL: u16 = 0x2000;
47pub const CHARACTERISTIC_UP_SYSTEM_ONLY: u16 = 0x4000;
48pub const CHARACTERISTIC_BYTES_REVERSED_HI: u16 = 0x8000;
49
50pub const DATA_DIRECTORY_EXPORT_TABLE: u16 = 0;
51pub const DATA_DIRECTORY_IMPORT_TABLE: u16 = 1;
52pub const DATA_DIRECTORY_RESOURCE_TABLE: u16 = 2;
53pub const DATA_DIRECTORY_EXCEPTION_TABLE: u16 = 3;
54pub const DATA_DIRECTORY_CERTIFICATE_TABLE: u16 = 4;
55pub const DATA_DIRECTORY_BASE_RELOCATION_TABLE: u16 = 5;
56pub const DATA_DIRECTORY_DEBUG: u16 = 6;
57pub const DATA_DIRECTORY_ARCHITECTURE: u16 = 7;
58pub const DATA_DIRECTORY_GLOBAL_PTR: u16 = 8;
59pub const DATA_DIRECTORY_TLS_TABLE: u16 = 9;
60pub const DATA_DIRECTORY_LOAD_CONFIG_TABLE: u16 = 10;
61pub const DATA_DIRECTORY_BOUND_IMPORT: u16 = 11;
62pub const DATA_DIRECTORY_IAT: u16 = 12;
63pub const DATA_DIRECTORY_DELAY_IMPORT_DESCRIPTOR: u16 = 13;
64pub const DATA_DIRECTORY_CLR_RUNTIME_HEADER: u16 = 14;
65
66/* reserved: 0x0001, 0x0002, 0x0004, 0x0008 */
67pub const DLL_CHARACTERISTIC_HIGH_ENTROPY_VA: u16 = 0x0020;
68pub const DLL_CHARACTERISTIC_DYNAMIC_BASE: u16 = 0x0040;
69pub const DLL_CHARACTERISTIC_FORCE_INTEGRITY: u16 = 0x0080;
70pub const DLL_CHARACTERISTIC_NX_COMPAT: u16 = 0x0100;
71pub const DLL_CHARACTERISTIC_NO_ISOLATION: u16 = 0x0200;
72pub const DLL_CHARACTERISTIC_NO_SEH: u16 = 0x0400;
73pub const DLL_CHARACTERISTIC_NO_BIND: u16 = 0x0800;
74pub const DLL_CHARACTERISTIC_APPCONTAINER: u16 = 0x1000;
75pub const DLL_CHARACTERISTIC_WDM_DRIVER: u16 = 0x2000;
76pub const DLL_CHARACTERISTIC_GUARD_CF: u16 = 0x4000;
77pub const DLL_CHARACTERISTIC_TERMINAL_SERVER_AWARE: u16 = 0x8000;
78
79pub const MACHINE_UNKNOWN: u16 = 0x0000;
80pub const MACHINE_AM33: u16 = 0x01d3;
81pub const MACHINE_AMD64: u16 = 0x8664;
82pub const MACHINE_ARM: u16 = 0x01c0;
83pub const MACHINE_ARM64: u16 = 0xaa64;
84pub const MACHINE_ARMNT: u16 = 0x01c4;
85pub const MACHINE_EBC: u16 = 0x0ebc;
86pub const MACHINE_I386: u16 = 0x014c;
87pub const MACHINE_IA64: u16 = 0x0200;
88pub const MACHINE_LOONGARCH32: u16 = 0x6232;
89pub const MACHINE_LOONGARCH64: u16 = 0x6264;
90pub const MACHINE_M32R: u16 = 0x9041;
91pub const MACHINE_MIPS16: u16 = 0x0266;
92pub const MACHINE_MIPSFPU: u16 = 0x0366;
93pub const MACHINE_MIPSFPU16: u16 = 0x0466;
94pub const MACHINE_POWERPC: u16 = 0x01f0;
95pub const MACHINE_POWERPCFP: u16 = 0x01f1;
96pub const MACHINE_R4000: u16 = 0x0166;
97pub const MACHINE_RISCV32: u16 = 0x5032;
98pub const MACHINE_RISCV64: u16 = 0x5064;
99pub const MACHINE_RISCV128: u16 = 0x5128;
100pub const MACHINE_SH3: u16 = 0x01a2;
101pub const MACHINE_SH3DSP: u16 = 0x01a3;
102pub const MACHINE_SH4: u16 = 0x01a6;
103pub const MACHINE_SH5: u16 = 0x01a8;
104pub const MACHINE_THUMB: u16 = 0x01c2;
105pub const MACHINE_WCEMIPSV2: u16 = 0x0169;
106
107/* reserved: 0x00000001, 0x00000002, 0x00000004 */
108pub const SECTION_CHARACTERISTIC_TYPE_NO_PAD: u32 = 0x00000008;
109/* reserved: 0x00000010 */
110pub const SECTION_CHARACTERISTIC_CNT_CODE: u32 = 0x00000020;
111pub const SECTION_CHARACTERISTIC_CNT_INITIALIZED_DATA: u32 = 0x00000040;
112pub const SECTION_CHARACTERISTIC_CNT_UNINITIALIZED_DATA: u32 = 0x00000080;
113pub const SECTION_CHARACTERISTIC_LNK_OTHER: u32 = 0x00000100;
114pub const SECTION_CHARACTERISTIC_LNK_INFO: u32 = 0x00000200;
115/* reserved: 0x00000400 */
116pub const SECTION_CHARACTERISTIC_LNK_REMOVE: u32 = 0x00000800;
117pub const SECTION_CHARACTERISTIC_LNK_COMDAT: u32 = 0x00001000;
118/* reserved: 0x00002000, 0x00004000 */
119pub const SECTION_CHARACTERISTIC_GPREL: u32 = 0x00008000;
120pub const SECTION_CHARACTERISTIC_MEM_PURGEABLE: u32 = 0x00020000;
121pub const SECTION_CHARACTERISTIC_MEM_16BIT: u32 = 0x00020000;
122pub const SECTION_CHARACTERISTIC_MEM_LOCKED: u32 = 0x00040000;
123pub const SECTION_CHARACTERISTIC_MEM_PRELOAD: u32 = 0x00080000;
124pub const SECTION_CHARACTERISTIC_ALIGN_1BYTES: u32 = 0x00100000;
125pub const SECTION_CHARACTERISTIC_ALIGN_2BYTES: u32 = 0x00200000;
126pub const SECTION_CHARACTERISTIC_ALIGN_4BYTES: u32 = 0x00300000;
127pub const SECTION_CHARACTERISTIC_ALIGN_8BYTES: u32 = 0x00400000;
128pub const SECTION_CHARACTERISTIC_ALIGN_16BYTES: u32 = 0x00500000;
129pub const SECTION_CHARACTERISTIC_ALIGN_32BYTES: u32 = 0x00600000;
130pub const SECTION_CHARACTERISTIC_ALIGN_64BYTES: u32 = 0x00700000;
131pub const SECTION_CHARACTERISTIC_ALIGN_128BYTES: u32 = 0x00800000;
132pub const SECTION_CHARACTERISTIC_ALIGN_256BYTES: u32 = 0x00900000;
133pub const SECTION_CHARACTERISTIC_ALIGN_512BYTES: u32 = 0x00a00000;
134pub const SECTION_CHARACTERISTIC_ALIGN_1024BYTES: u32 = 0x00b00000;
135pub const SECTION_CHARACTERISTIC_ALIGN_2048BYTES: u32 = 0x00c00000;
136pub const SECTION_CHARACTERISTIC_ALIGN_4096BYTES: u32 = 0x00d00000;
137pub const SECTION_CHARACTERISTIC_ALIGN_8192BYTES: u32 = 0x00e00000;
138pub const SECTION_CHARACTERISTIC_LNK_NRELOC_OVFL: u32 = 0x01000000;
139pub const SECTION_CHARACTERISTIC_MEM_DISCARDABLE: u32 = 0x02000000;
140pub const SECTION_CHARACTERISTIC_MEM_NOT_CACHED: u32 = 0x04000000;
141pub const SECTION_CHARACTERISTIC_MEM_NOT_PAGED: u32 = 0x08000000;
142pub const SECTION_CHARACTERISTIC_MEM_SHARED: u32 = 0x10000000;
143pub const SECTION_CHARACTERISTIC_MEM_EXECUTE: u32 = 0x20000000;
144pub const SECTION_CHARACTERISTIC_MEM_READ: u32 = 0x40000000;
145pub const SECTION_CHARACTERISTIC_MEM_WRITE: u32 = 0x80000000;
146
147pub const SUBSYSTEM_UNKNOWN: u16 = 0x0000;
148pub const SUBSYSTEM_NATIVE: u16 = 0x0001;
149pub const SUBSYSTEM_WINDOWS_GUI: u16 = 0x0002;
150pub const SUBSYSTEM_WINDOWS_CUI: u16 = 0x0003;
151pub const SUBSYSTEM_OS2_CUI: u16 = 0x0005;
152pub const SUBSYSTEM_POSIX_CUI: u16 = 0x0007;
153pub const SUBSYSTEM_NATIVE_WINDOWS: u16 = 0x0008;
154pub const SUBSYSTEM_WINDOWS_CE_GUI: u16 = 0x0009;
155pub const SUBSYSTEM_EFI_APPLICATION: u16 = 0x0010;
156pub const SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: u16 = 0x0011;
157pub const SUBSYSTEM_EFI_RUNTIME_DRIVER: u16 = 0x0012;
158pub const SUBSYSTEM_EFI_ROM: u16 = 0x0013;
159pub const SUBSYSTEM_XBOX: u16 = 0x0014;
160pub const SUBSYSTEM_WINDOWS_BOOT_APPLICATION: u16 = 0x0016;
161
162// aligned on 8-byte boundary
163#[repr(C)]
164pub struct Header {
165    pub machine: U16Le,
166    pub number_of_sections: U16Le,
167    pub time_date_stamp: U32Le,
168    pub pointer_to_symbol_table: U32Le,
169    pub number_of_symbols: U32Le,
170    pub size_of_optional_header: U16Le,
171    pub characteristics: U16Le,
172}
173
174#[repr(C)]
175pub struct OptionalHeader<FORMAT: format::Type = format::Pe> {
176    pub magic: U16Le,
177    pub major_linker_version: U8Le,
178    pub minor_linker_version: U8Le,
179    pub size_of_code: U32Le,
180    pub size_of_initialized_data: U32Le,
181    pub size_of_uninitialized_data: U32Le,
182    pub address_of_entry_point: U32Le,
183    pub base_of_code: U32Le,
184    pub base_of_data: FORMAT::BaseOfData,
185}
186
187pub type OptionalHeader32P = OptionalHeader::<format::Pe32P>;
188
189#[repr(C)]
190pub struct OptionalHeaderExt<FORMAT: format::Type = format::Pe> {
191    pub image_base: FORMAT::AddressSpace,
192    pub section_alignment: U32Le,
193    pub file_alignment: U32Le,
194    pub major_operating_system_version: U16Le,
195    pub minor_operating_system_version: U16Le,
196    pub major_image_version: U16Le,
197    pub minor_image_version: U16Le,
198    pub major_subsystem_version: U16Le,
199    pub minor_subsystem_version: U16Le,
200    pub win32_version_value: U32Le,
201    pub size_of_image: U32Le,
202    pub size_of_headers: U32Le,
203    pub check_sum: U32Le,
204    pub subsystem: U16Le,
205    pub dll_characteristics: U16Le,
206    pub size_of_stack_reserve: FORMAT::AddressSpace,
207    pub size_of_stack_commit: FORMAT::AddressSpace,
208    pub size_of_heap_reserve: FORMAT::AddressSpace,
209    pub size_of_heap_commit: FORMAT::AddressSpace,
210    pub loader_flags: U32Le,
211    pub number_of_rva_and_sizes: U32Le,
212}
213
214pub type OptionalHeaderExt32P = OptionalHeaderExt::<format::Pe32P>;
215
216#[repr(C)]
217pub struct DataDirectory {
218    pub virtual_address: U32Le,
219    pub size: U32Le,
220}
221
222#[repr(C)]
223pub struct SectionHeader {
224    pub name: [u8; 8],
225    pub virtual_size: U32Le,
226    pub virtual_address: U32Le,
227    pub size_of_raw_data: U32Le,
228    pub pointer_to_raw_data: U32Le,
229    pub pointer_to_relocations: U32Le,
230    pub pointer_to_linenumbers: U32Le,
231    pub number_of_relocations: U16Le,
232    pub number_of_linenumbers: U16Le,
233    pub characteristics: U32Le,
234}
235
236/// Format Parameter Customization
237///
238/// The PE format comes in multiple types. This module provides a trait named
239/// `format::Type` which describes all the possible customizations for the
240/// PE format. The PE types are parameterized with this trait if they allow
241/// customizations.
242///
243/// The `Pe` and `Pe32P` types are predefined instances for the Pe and Pe32+
244/// types of the format.
245pub mod format {
246    pub trait Type {
247        type AddressSpace;
248        type BaseOfData;
249    }
250
251    pub struct Pe {}
252
253    impl Type for Pe {
254        type AddressSpace = super::U32Le;
255        type BaseOfData = super::U32Le;
256    }
257
258    pub struct Pe32P {}
259
260    impl Type for Pe32P {
261        type AddressSpace = super::U64Le;
262        type BaseOfData = ();
263    }
264}
265
266#[cfg(test)]
267mod tests {
268    use core::mem::{
269        align_of,
270        size_of,
271    };
272    use super::*;
273
274    #[test]
275    fn verify_types() {
276        assert_eq!(size_of::<Header>(), 20);
277        assert_eq!(align_of::<Header>(), 4);
278
279        assert_eq!(size_of::<OptionalHeader>(), 28);
280        assert_eq!(align_of::<OptionalHeader>(), 4);
281        assert_eq!(size_of::<OptionalHeader32P>(), 24);
282        assert_eq!(align_of::<OptionalHeader32P>(), 4);
283
284        assert_eq!(size_of::<OptionalHeaderExt>(), 68);
285        assert_eq!(align_of::<OptionalHeaderExt>(), 4);
286        assert_eq!(size_of::<OptionalHeaderExt32P>(), 88);
287        assert_eq!(align_of::<OptionalHeaderExt32P>(), 8);
288    }
289}