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: 224 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. |
00000100 50 45 00 00 4C 01 05 00 21 09 1C 56 00 00 00 00
00000110 00 00 00 00 E0 00 02 21
0x100: PE\0\0; machine 0x014C (i386); 5 sections; linked at 0x561C0921; no COFF symbols; a 224-byte optional header; characteristics 0x2102: EXECUTABLE_IMAGE, 32BIT_MACHINE and DLLMachine types
The values Microsoft’s specification lists. In a PE32 file the machine is nearly
always 0x014C; the others are those of Windows NT on other processors,
Windows CE, 32-bit ARM Windows and EFI. The 64-bit values belong in a PE32+
file.
| 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 0x014C; see
The code. Among the PE32 files examined for
this site, almost all were i386; a few were ARMNT, Alpha AXP or MIPS R4000.
Time stamp
TimeDateStamp is the time the linker made the file, in seconds since
1 January 1970 UTC. In the example, 0x561C0921 is 1,444,677,921:
12 October 2015, 19:25:21 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. A PE32 program with this flag gets a 4 GB address space on 64-bit Windows. |
0x0040 | – | Reserved. |
0x0080 | BYTES_REVERSED_LO | Obsolete. |
0x0100 | 32BIT_MACHINE | The machine has 32-bit words. Set in PE32 files. |
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. |