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 ================================================================ 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 | ....................................................... ....................................................... 80h | import table RVA | ------------------------------------------------------- 84h | import table size | ....................................................... ....................................................... A0h | fixup table RVA | ------------------------------------------------------- A4h | fixup table size | ....................................................... ....................................................... 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://www.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