x86 Win32 PE COFF files All multi-byte values are LITTLE ENDIAN xxx - to do - finish description of a.out file header - PE file exports - resources - demo code for fixups and dynamic linking offset size description ------ ---- ----------- 0 4 PE header 4 20 COFF header 4 2 COFF file magic (=0x014C) 6 2 number of sections 8 4 time/date stamp 12 4 file offset of symbol table 16 4 number of symbol table entries 20 2 a.out header size 22 2 COFF file flags 24 120+ aout header 24 2 aout magic (=0x010B) 26 2 aout version 28 4 .text size 32 4 .data size 36 4 .bss size 40 4 entry point (initial EIP) 44 4 file offset of .text 48 4 file offset of .data 52 4 image base 56 4 section alignment 60 4 file alignment 64 2 major OS version 66 2 minor OS version 68 2 major image version 70 2 minor image version 72 2 major subsystem version 74 2 minor subsystem version 76 4 reserved (=0) 80 4 size of image 84 4 size of headers 88 4 checksum 92 2 subsystem 94 2 DLL characteristics 96 4 size of stack reserve 100 4 size of stack commit 104 4 size of heap reserve 108 4 size of heap commit 112 4 loader flags 116 4 number of entries in data directory 120 4 export table RVA (0th data directory entry) 124 4 export table size 128 4 import table RVA (1st data directory entry) 132 4 import table size 136 4 resource table RVA (2nd data directory entry) 140 4 resource table size 144 4 ? RVA (3rd data directory entry) 148 4 ? size 152 4 ? RVA (4th data directory entry) 156 4 ? size 160 4 base relocations RVA (5th data directory entry) 164 4 base relocations size 168 ================================================================ DOS .EXE FILE HEADER (MUST BE 64 BYTES OR MORE) ================================================================ Only fields relevant to Win32 PE COFF are shown. The DOS .EXE file header is not present for Win32 PE COFF relocatable files. file offset ------------------------------------------------------- 0 | EXE file magic | | ------------------------------------------------------- 4 | | | ------------------------------------------------------- 8 | header size | | ....................................................... 3Ch | offset of new executable header | ------------------------------------------------------- 40h EXE file magic =5A4Dh ("MZ") header size =size of .EXE file header and fixups, in 16-byte paragraphs. This value is the file offset of the "load module" (combined code and data segments). Some OSes and/or programs may fail if the header is not a multiple of 512 bytes. offset of new executable header =0 for normal DOS .EXE This field is not valid unless header size >= 4 ================================================================ WIN32 PE COFF FILE HEADER (24 BYTES) ================================================================ offset into new executable ------------------------------------------------------- 0 | new executable file magic | ------------------------------------------------------- 4 | COFF file magic | number of sections | ------------------------------------------------------- 8 | time/date stamp | ------------------------------------------------------- 0Ch | file offset of symbol table | ------------------------------------------------------- 10h | number of symbol table entries | ------------------------------------------------------- 14h | aout header size | COFF file flags | ------------------------------------------------------- 18h new executable file magic =45500000h ("PE\x00\x00") This field is not present for relocatable files. COFF file magic =014Ch number of sections (self-explanatory) time/date stamp =number of seconds since Dec 31, 1969, 4:00 PM (?) file offset of symbol table (self-explanatory) number of symbol table entries (self-explanatory) aout header size =00E0h for Win32 PE COFF executable, 0 for relocatable COFF file flags 01h=relocation info stripped from file 02h=executable file (no unresolved externals) 04h=line numbers stripped from file 08h=local symbols stripped from file 200h=debug info stripped from file 1000h="system" file 2000h=file is a DLL ================================================================ WIN32 PE COFF A.OUT FILE HEADER (224 BYTES) ================================================================ The a.out header is not present for relocatable files. offset into new executable ------------------------------------------------------- 18h | aout magic | aout version | ------------------------------------------------------- 1Ch | code size | ------------------------------------------------------- 20h | data size | ------------------------------------------------------- 24h | bss size | ------------------------------------------------------- 28h | entry point (initial EIP) | ------------------------------------------------------- 2Ch | file offset of .text section | ------------------------------------------------------- 30h | file offset of .data section | ------------------------------------------------------- 34h | image base | ....................................................... : : ....................................................... 74h | number of data directory entries | ------------------------------------------------------- 78h | DD entry #0: export table RVA | ------------------------------------------------------- 7Ch | export table size | ------------------------------------------------------- 80h | DD entry #1 import table RVA | ------------------------------------------------------- 84h | import table size | ------------------------------------------------------- 88h | DD entry #2 resource table RVA | ------------------------------------------------------- 8Ch | resource table size | ------------------------------------------------------- 90h | DD entry #3 exception table RVA (?) | ------------------------------------------------------- 94h | exception table size (?) | ------------------------------------------------------- 98h | DD entry #4 security table RVA (?) | ------------------------------------------------------- 9Ch | security table size (?) | ------------------------------------------------------- A0h | DD entry #5 base relocations RVA | ------------------------------------------------------- A4h | base relocations size | ------------------------------------------------------- A8h | DD entry #6 debug RVA | ------------------------------------------------------- ACh | debug size | ------------------------------------------------------- B0h | DD entry #7 copyright RVA | ------------------------------------------------------- B4h | copyright size | ------------------------------------------------------- B8h | DD entry #8 globalptr RVA (?) | ------------------------------------------------------- BCh | globalptr size (?) | ------------------------------------------------------- C0h | DD entry #9 TLS RVA | ------------------------------------------------------- C4h | TLS size | ------------------------------------------------------- C8h | DD entry #10 load config RVA (?) | ------------------------------------------------------- CCh | load config size (?) | ------------------------------------------------------- D0h | DD entry #11 bound import RVA (?) | ------------------------------------------------------- D4h | bound import size (?) | ------------------------------------------------------- D8h | DD entry #12 IAT RVA (?) | ------------------------------------------------------- DCh | IAT size (?) | ------------------------------------------------------- E0h ....................................................... ....................................................... F8h aout magic =010Bh aout version =linker version; MSB=major, LSB=minor (e.g. 2.23) code size =combined and rounded-up size of all code sections data size =combined and rounded-up size of all data sections bss size =combined and rounded-up size of all bss sections entry point (initial EIP) (self-explanatory) file offset of .text section (self-explanatory) file offset of .data section (self-explanatory) image base ? import table RVA relative virtual address of import table -- "relative" because you must add the image base value to get the true VMA import table size number of entries in import table fixup table RVA relative virtual address of fixups fixup table size number of fixups xxx - finish ================================================================ WIN32 PE COFF SECTION HEADER (40 BYTES) ================================================================ offset into new executable for first section header ------------------------------------------------------- F8h | section | | name | | | ------------------------------------------------------- 100h | virtual section size (size-in-memory) | ------------------------------------------------------- 104h | section RVA | ------------------------------------------------------- 108h | raw data size (size-on-disk) | ------------------------------------------------------- 10Ch | file offset of section | ------------------------------------------------------- 110h | file offset of relocations | ------------------------------------------------------- 114h | file offset of line number info | ------------------------------------------------------- 118h | num. relocations | num. line numbers | ------------------------------------------------------- 11Ch | section flags | ------------------------------------------------------- 120h section name =.text .data .bss .stab .stabstr or user-defined section name (xxx - long section names?) virtual section size (size-in-memory) size of section in memory. If greater than size-on-disk, this section contains a BSS, and the difference should be zeroed. section RVA relative virtual address of section -- "relative" because you must add the image base value (from the a.out header) to get the true VMA raw data size (size-on-disk) size of section on disk file offset of section (self-explanatory) file offset of relocations (self-explanatory) file offset of line number info (self-explanatory) number of relocations (self-explanatory) number of line number entries (self-explanatory) section flags 20h=.text (code) section 40h=.data section 80h=.bss section 200h=informational section (e.g. comments) 800h=do not put this section in final .EXE file 2000000h=discardable section (e.g. .reloc) 10000000h=shareable section (used by DLLs) 20000000h=executable section 40000000h=readable section 80000000h=writable section ================================================================ COFF LINE NUMBER RECORDS (6 BYTES) ================================================================ record offset ------------------------------------------------------- 0 | physical address or symbol table index | ------------------------------------------------------- 4 | line number | --------------------------- 6 physical address or symbol table index =(line number != 0) physical address of line, or (line number == 0) symbol table index of line label ================================================================ COFF RELOCATION RECORDS (10 BYTES) ================================================================ record offset ------------------------------------------------------- 0 | virtual address | ------------------------------------------------------- 4 | symbol table index | ------------------------------------------------------- 8 | relocation type | --------------------------- 0Ah relocation type =0006h for 32-bit absolute address =0014h for 32-bit EIP-relative address Demo code for performing Win32 PE COFF relocations: http://my.execpc.com/~geezer/osd/exec/runreloc.zip ================================================================ COFF SYMBOL TABLE RECORDS (18 BYTES) ================================================================ record offset ------------------------------------------------------- 0 | 8-char symbol name | | or 32-bit zeroes followed by 32-bit | | index into string table | ------------------------------------------------------- 8 | symbol value | ------------------------------------------------------- 0Ch | section number | symbol type | ------------------------------------------------------- 10h | sym class | num aux | --------------------------- 12h xxx - finish ================================================================ COFF STRING TABLE ================================================================ If end of symbol table < end of COFF file, the remainder of the COFF file is the string table. This table is used to store symbol names that are too long (9 characters or more) to fit into the symbol table entries. The first 4 bytes of the string table are the size of the string table itself. These 4 bytes should be zeroed after the size value has been read. Offsets into the string table are from the start of these 4 bytes. An offset of 0 is legal, and will result in a NULL string because of these 4 zeroes. Strings in the string table are normal, C-style (0-terminated) strings. ================================================================ WIN32 PE COFF FIXUPS (BASE RELOCATIONS) ================================================================ These relocations allow the executable file or DLL to load at any virtual address (similar to DOS .EXE fixups). They are sometimes (not always) stored in the ".reloc" section of the Win32 PE COFF executable or DLL. The fixup section is divided into "chunks". Each chunk contains the fixups for one 4K memory page: offset into chunk ------------------------------------------------------- 0 | page RVA | ------------------------------------------------------- 4 | chunk size | ------------------------------------------------------- 8 | fixup #0 | fixup #1 | ------------------------------------------------------- 0Ch | fixup #2 | . ----------------------------........................... page RVA relative virtual address of 4K memory page to which the fixups in this chunk will be applied chunk size total size of this fixup chunk, including page RVA and chunk size fixup 16-bit fixup records. Top 4 bits are fixup type, bottom 12 bits are offset of fixup within 4K page. Each fixup applies to a 32-bit memory locations (a dword). The complete virtual address of the relocation is: image_base + page_RVA + (fixup & 0xFFF); The top four bits specify the fixup type: 0=ABSOLUTE=dummy, padding, do nothing 1=relocate high 16 bits of dword 2=relocate low 16 bits of dword 3=HIGHLOW=relocate full 32 bits of dword There are other fixup types, but they aren't used for x86. ================================================================ WIN32 PE COFF IMPORTS ================================================================ The import and export tables are used for dynamic linking. The import table is sometimes (not always) stored in the ".idata" section of the Win32 PE COFF executable or DLL. record offset ------------------------------------------------------- 0 | characteristics | ------------------------------------------------------- 4 | time/date stamp | ------------------------------------------------------- 8 | forwarder chain | ------------------------------------------------------- 0Ch | DLL name | ------------------------------------------------------- 10h | first thunk | ------------------------------------------------------- characteristics ? time/date stamp ? forwarder chain ? DLL name ? first thunk ? Demo code for performing Win32 PE COFF fixups and dynamic linking: xxx - to do