At the offset that e_lfanew gives are the PE signature and the COFF file header, the same 20-byte header that starts a COFF object file. It says which processor the code is for, how many sections there are, when the file was linked, how big the optional header is, and what kind of image this is.
The PE signature
Four bytes, 50 45 00 00: the letters PE and two zero
bytes. A file whose e_lfanew points anywhere else is not a PE file; it
may be one of the older .exe formats, whose headers
start NE, LE or LX.
The COFF file header
IMAGE_FILE_HEADER, 20 bytes, straight after the signature:
| Offset | Size | Type | Field | Meaning |
|---|---|---|---|---|
| 0 | 2 | u16 | Machine | The processor the code is for; see Machine types. |
| 2 | 2 | u16 | NumberOfSections | The number of entries in the section table. |
| 4 | 4 | u32 | TimeDateStamp | When the file was linked; see Time stamp. |
| 8 | 4 | u32 | PointerToSymbolTable | File offset of the COFF symbol table, or 0 when there is none. |
| 12 | 4 | u32 | NumberOfSymbols | The number of 18-byte symbol records. The string table follows them. |
| 16 | 2 | u16 | SizeOfOptionalHeader | The size of the optional header: 240 with the usual 16 data directories. The section table starts this many bytes after the end of this header. |
| 18 | 2 | u16 | Characteristics | Flags; see Characteristics. |
000000F0 50 45 00 00 64 86 06 00 2D 09 1C 56 00 00 00 00
00000100 00 00 00 00 F0 00 22 20
0xF0: PE\0\0; machine 0x8664 (AMD64); 6 sections; linked at 0x561C092D; no COFF symbols; a 240-byte optional header; characteristics 0x2022: EXECUTABLE_IMAGE, LARGE_ADDRESS_AWARE and DLLMachine types
The values Microsoft’s specification lists. In a PE32+ file the machine is nearly
always 0x8664 (x64) or 0xAA64 (ARM64), and in the oldest
ones 0x0200 (Itanium). An ARM64EC image says 0x8664 in its
header, as an x64 image does; an ARM64X image says 0xAA64. The 32-bit
machines belong in 32-bit PE files.
| Value | Name | Processor |
|---|---|---|
0x0000 | UNKNOWN | Any processor |
0x014C | I386 | Intel 386 and later, and compatible processors |
0x0160 | R3000BE | MIPS R3000, big-endian |
0x0162 | R3000 | MIPS R3000, little-endian |
0x0166 | R4000 | MIPS R4000, little-endian |
0x0168 | R10000 | MIPS R10000, little-endian |
0x0169 | WCEMIPSV2 | MIPS, Windows CE version 2 |
0x0184 | ALPHA | DEC Alpha AXP |
0x01A2 | SH3 | Hitachi SH-3 |
0x01A3 | SH3DSP | Hitachi SH-3 DSP |
0x01A6 | SH4 | Hitachi SH-4 |
0x01A8 | SH5 | Hitachi SH-5 |
0x01C0 | ARM | ARM, little-endian |
0x01C2 | THUMB | ARM Thumb |
0x01C4 | ARMNT | ARM Thumb-2 (32-bit ARM Windows) |
0x01D3 | AM33 | Matsushita AM33 |
0x01F0 | POWERPC | PowerPC, little-endian |
0x01F1 | POWERPCFP | PowerPC with floating point |
0x0200 | IA64 | Intel Itanium |
0x0266 | MIPS16 | MIPS16 |
0x0284 | ALPHA64 | DEC Alpha AXP 64-bit (AXP64) |
0x0366 | MIPSFPU | MIPS with FPU |
0x0466 | MIPSFPU16 | MIPS16 with FPU |
0x0EBC | EBC | EFI byte code |
0x5032 | RISCV32 | RISC-V, 32-bit |
0x5064 | RISCV64 | RISC-V, 64-bit |
0x5128 | RISCV128 | RISC-V, 128-bit |
0x6232 | LOONGARCH32 | LoongArch, 32-bit |
0x6264 | LOONGARCH64 | LoongArch, 64-bit |
0x8664 | AMD64 | x64 |
0x9041 | M32R | Mitsubishi M32R, little-endian |
0xA641 | ARM64EC | ARM64 code that interoperates with x64 (seen in objects) |
0xA64E | ARM64X | ARM64 and ARM64EC code side by side (seen in objects) |
0xAA64 | ARM64 | ARM64, little-endian |
The explorer disassembles the code only for 0x8664; see
The code. Among the PE32+ files examined
for this site, almost all were x64, and about one in a hundred ARM64.
Time stamp
TimeDateStamp is the time the linker made the file, in seconds since
1 January 1970 UTC. In the example, 0x561C092D is 1,444,677,933:
12 October 2015, 19:25:33 UTC. The same value appears in that file’s export directory
and debug directory.
A reproducible build, one whose output must be the same every time, puts a hash there instead of a time. Such a file has a REPRO debug entry, and then its time stamps are not times. Some linkers and packers write 0 or a fixed value, so a time stamp is a clue, not a fact.
Characteristics
| Bit | Name | Meaning |
|---|---|---|
0x0001 | RELOCS_STRIPPED | The file has no base relocations and must load at its image base. |
0x0002 | EXECUTABLE_IMAGE | The image is valid and can run. Set in every program and DLL. |
0x0004 | LINE_NUMS_STRIPPED | COFF line numbers removed (deprecated). |
0x0008 | LOCAL_SYMS_STRIPPED | COFF local symbols removed (deprecated). |
0x0010 | AGGRESSIVE_WS_TRIM | Obsolete. |
0x0020 | LARGE_ADDRESS_AWARE | The program can handle addresses above 2 GB. Microsoft’s linker sets it in 64-bit images by default. |
0x0040 | – | Reserved. |
0x0080 | BYTES_REVERSED_LO | Obsolete. |
0x0100 | 32BIT_MACHINE | The machine has 32-bit words. Not set in 64-bit images. |
0x0200 | DEBUG_STRIPPED | Debug information removed from the file. |
0x0400 | REMOVABLE_RUN_FROM_SWAP | If the file is on removable media, copy it to the swap file and run it from there. |
0x0800 | NET_RUN_FROM_SWAP | The same for a file on the network. |
0x1000 | SYSTEM | A system file, such as a driver. |
0x2000 | DLL | A library. Without it the image is a program. |
0x4000 | UP_SYSTEM_ONLY | Run only on a single-processor machine. |
0x8000 | BYTES_REVERSED_HI | Obsolete. |