Table of contents


UNIX a.out file format (for assembly output)

File extensions
Magic code
various: x0107, x0108, x010B, x0105, x00CC, x0101, x0109, x010C, x010D, x010E, x0111, x0118, x0119, x011F
Architecture
DEC PDP-11, DEC VAX, Motorola 68000, Intel 386 and others (Interdata 7/32, IBM 370, MIPS, SPARC)
Operating systems
  • between 1969 and 1971-11-03: PDP-11 UNIX version 1 (old format)
  • 1972-06-12: PDP-11 UNIX version 2
  • 1979-06: UNIX/32V before System V
  • 1983-11: SunOS 1.0
  • 1989: DJGPP DOS extender before version 1.11
  • 1991-09-17: Linux before version 1.2
  • 1993-04-19: NetBSD before version 1.5
  • 1993-11-01: FreeBSD up to 2.2 until version 2.2
  • 1997-05-18: PDOS32 0.10
Influences
DEC PDP-11, DEC VAX, Motorola 68000, Intel 386 and others (Interdata 7/32, IBM 370, MIPS, SPARC)

Contents

  1. Contents
  2. a.out header
    1. Magic numbers
    2. UNIX v1 PDP-11 a.out header
    3. UNIX 16-bit PDP-11 a.out header
    4. UNIX 32-bit a.out header
      1. UNIX/32V for VAX
      2. System III format
      3. Ultrix
      4. SunOS
      5. Linux
      6. The BSDs
    5. UNIX 32-bit Interdata 7/32 a.out header
    6. UNIX 32-bit IBM 370 a.out header
    7. UNIX 32-bit NS16032 a.out header
    8. Xenix b.out header
    9. HP-UX a.out header
  3. Runtime memory layout
  4. References

a.out header

Magic numbers

The first word in an a.out file contains a 16-bit magic number, which specifies how the file should be processed, linked and loaded. The types and values have evolved through the various branches of UNIX-like systems.

The first versions of UNIX were produced by AT&T for the 16-bit PDP-11. Later these were ported to various 32-bit architectures, most notably the VAX, Motorola 68000 and Intel 80386. The AT&T versions progressed from version 1 to 7, after which UNIX was commercialized and sold as System III and then System V.

The other important branch are the BSD distributions. In this table we see mentions of versions 2.11BSD, which supported all Version 7 formats, then 3BSD, 4.1cBSD, after which the sources were reused by FreeBSD and NetBSD, OpenBSD. Linux is currently the most widely used UNIX-like system.

Magic Systems Introduced Dropped Description
x00CC 32 NetBSD 0.9
FreeBSD 2.0
Linux 0.99.13
(QMAGIC) compact demand load format
x0101 16, 32 System III UNIX/RT "lpd"
x0105 16 Version 1 Version 2 Version 1 format
x0105 16, 32 Version 7 4.1cBSD overlay
x0107 16, 32 Version 2 (OMAGIC) normal
x0108 16, 32 Version 4 (NMAGIC) read-only text
x0109 16, 32 Version 6 4.1cBSD separated instruction and data
x010B 16, 32 3BSD (ZMAGIC) demand paged
x010C 32 NetBSD demand paged pure
x010C 32 ? (SPRITE_ZMAGIC)
x010C 32 NS16032 (XMAGIC) demand load (like ZMAGIC), locations 0-1023 unmapped
x010D 32 ? (UNIX_ZMAGIC)
x010E 32 NetBSD readable demand paged pure
x0111 32 Linux 0.96c (CMAGIC) Linux core dump
x0118 16 2.11 3BSD overlay, non-separate
x0119 16 2.11 3BSD overlay, separate
x011F 16, 32 System V system overlay, separated instruction and data

The following sections will discuss the layout of the headers of the various versions.

UNIX v1 PDP-11 a.out header

Version 1 had a different header format from later versions.

x00 i16le x0105
x02 i16le Size of the combined program text (code) and initialized data segment
x04 i16le Size of the symbol table
x06 i16le Relocation bits
x08 i16le Size of uninitialized data (bss), not stored in binary
x0A i16le unused

UNIX 16-bit PDP-11 a.out header

This format was introduced in Version 2 and targetted the PDP-11 architecture.

The 16-bit header format evolved through various branches. Version 6 and 7 is the last common version, then it evolved separately at BSD (from 2.11BSD on) and AT&T. Version 7 was followed by System III then System V. Internally, Version 7 evolved to Version 8, 9, 10, separately from the commercial branch. These were allegedly based on the 4.1cBSD codebase and later, but the 16-bit a.out format is more similar to the commercial versions.

x00 i16le Magic number
0x0101 UNIX/RT "lpd"[3] (System III)
0x0105 overlay[3] (around Version 7, dropped support in 4.1cBSD[3])
0x0107 (OMAGIC) normal
0x0108 (NMAGIC) read-only text
0x0109 Separated instruction and data (dropped support in 4.1cBSD[3])
0x010B (ZMAGIC) demand paged separated instruction and data (since 3BSD[3])
0x0118 2.11BSD overlay, non-separate (dropped support in 3BSD[3])
0x0119 2.11BSD overlay, separate (dropped support in 3BSD[3])
0x011F system overlay, separated I&D (since System V)
x02 i16le Size of program text (code)
x04 i16le Size of initialized data
x06 i16le Size of uninitialized data (bss), not stored in binary
x08 i16le Size of symbol table
x0A i16le Entry location[3], always 0 before version 4[2]
x0C i16le reserved (stack required in version 2 and 3[2])
(System III) environment stamp[3]
x0E i16le Non-zero if relocations have been suppressed
Xinu uses the least significant byte to mark Version 6 compatibility, and the most significant byte for its own flag[3]

Xenix also uses the System 7 format.[5]

Overlays in 2.9BSD have an extended header with the following fields:

x10 i16le Maximum size of overlays
x12 i16le[7] Size of each overlay

They are extended in 2.11BSD to 15 overlays:

x10 i16le Maximum size of overlays
x12 i16le[15] Size of each overlay

Since System V, the final fields are slightly altered:[3]

x0C i8 reserved
x0D i8 High bits of size of program text
x0E i8 Non-zero if relocations have been suppressed
x0F i8 Environment stamp
x10 i32le filler (only Version 8 and later)

UNIX 32-bit a.out header

The first version was created for UNIX/32V for the VAX (little endian). It was later extended to other 32-bit targets as well. By System V, all 32-bit versions switched to COFF except for the IBM 370 (the Interdata 7/32 port was apparently not maintained). However, competitors to AT&T such as SunOS and the BSD variants still kept using the format.

While most formats had a similar layout, the first word was often subdivided into various fields for machine type and flags. Most variants use the native byte order to store the values, which further complicates determination of the file type.

UNIX/32V for VAX

The entries were extended from the 16-bit version to full 32 bits. Also the last two fields were replaced with the size of the relocation section for text and initialized data, respectively.

x00 i32 Magic number
0x00CC (QMAGIC) compact demand load format (Linux, FreeBSD*, NetBSD*, OpenBSD)[3]
0x0101 UNIX/RT "lpd" (System III)
0x0105 overlay (dropped support in 4.1cBSD)
0x0107 (OMAGIC) normal (used by PDOS32 before switching to PE)
0x0108 (NMAGIC) read-only text
0x0109 separated instruction and data (dropped support in 4.1cBSD)
0x010B (ZMAGIC) demand paged separated instruction and data (since 3BSD[3], used by early DJGPP)
0x010C demand paged pure for NetBSD[13]
0x010C (XMAGIC) demand load (like ZMAGIC), locations 0-1023 unmapped (NS16032)
0x010C (SPRITE_ZMAGIC) ?
0x010D (UNIX_ZMAGIC) UNIX binary compatible
0x010E readable demand paged pure for NetBSD[13]
0x0111 (CMAGIC) core dump (Linux)[6]
0x011F system overlay, separated I&D (since System V and 3BSD)
x04 i32 Size of program text (code)
x08 i32 Size of initialized data
x0C i32 Size of uninitialized data (bss), not stored in binary
x10 i32 Size of symbol table
x14 i32 Entry location
x18 i32 Size of relocations for program text
x1C i32 Size of relocations for initialized data

System III format

Since System III, subfields of the extended magic number field got reused for additional information. The ways this was extended was sometimes incompatible between systems. System III VAX introduced an environment stamp, similarly to System III PDP-11 (albeit at a different position). 4.3BSD-Reno also switched over to this format for non-VAX targets, possibly to stay compatible with SunOS, and early NetBSD kept this format.

x00 i32
Bits 0:15 Magic number
Bits 16:31 Environment stamp (System III VAX)
Machine type (4.3BSD-Reno)

Ultrix

Ultrix had a different use for the new field:

x00 i32
Bits 0:15 Magic number
Bits 16:31 Mode (Ultrix)
0x0000 BSD executable
0x0001 System V compatible executable
0x0002 POSIX compatible executable

SunOS

SunOS versions had a different format for the first word:

x00 i32
Bits 0:15 Magic number
Bits 16:23 Machine type
Bits 24:30 Tool version
Bit 31 Dynamic

Sun 4 also offered a few additional fields:

x20 i32 Size of string segment
x24 i32 Size of sdata segment
x28 i32 Size of sdata relocations
x2C i32 0 (spare segment)
x30 i32 0 (spare segment)
x34 i32 0 (spare segment)
x38 i32 0 (spare segment)
x3C i32 0 (spare segment)

Linux

Linux used the following format:

x00 i32
Bits 0:15 Magic number
Bits 16:23 Machine type
Bits 24:31 Flags (Linux)

The BSDs

4.4BSD-Lite2[14] used different versions for different targets: it used the UNIX/32V VAX version for VAX and Intel 386, the SunOS version (without additional fields) for SPARC, the System III format with machine type for HP300 and MIPS, and COFF for other systems.

Since FreeBSD 2.0 and NetBSD 0.9, the following layout is used for the magic number field. FreeBSD prior to 2.0 for all ports and NetBSD prior to 0.9 on VAX and 386 used the UNIX/32V VAX format.

x00 i32
Bits 0:15 Magic number
Bits 16:25 Machine type
0x0000 unknown, old Sun-2
0x0001 SunOS, 68010+
0x0002 SunOS, 68020
0x0003 SunOS, SPARC (likely 4.0.3)
0x0064 Intel 80386 for PC (4.4BSD, Linux, FreeBSD, NetBSD, OpenBSD)
0x0065 AMD 29000 (4.4BSD)
0x0068 old IBM RT (OpenBSD)
0x0086 Intel 80386 BSD (FreeBSD, NetBSD, OpenBSD)
0x0087 Motorola 68K BSD with 8K pages (NetBSD, OpenBSD)
0x0088 Motorola 68K BSD with 4K pages (NetBSD, OpenBSD)
0x0089 National Semiconductor NS32532 (NetBSD, OpenBSD)
0x008A Intel SPARC BSD (FreeBSD*, NetBSD, OpenBSD)
0x008B PMAX (MIPS R2000 based DECstation) (NetBSD, OpenBSD)
0x008C VAX with 1K pages (NetBSD, OpenBSD)
0x008D MIPS big endian (NetBSD, OpenBSD)
0x008D Alpha code (NetBSD)[13]
0x008E MIPS (NetBSD)[13]
0x008F ARM6 (FreeBSD*, NetBSD, OpenBSD)
0x0090 Motorola 68K with 2K pages (NetBSD)
0x0091 SH3 (NetBSD, OpenBSD)
0x0094 PowerPC 64-bit big endian (NetBSD)
0x0095 PowerPC big endian (NetBSD, OpenBSD)
0x0096 VAX (NetBSD, OpenBSD)
0x0097 MIPS I R2000/R3000 (4.4BSD, NetBSD, Linux 1.3.48)
0x0097 SPARC 64-bit (OpenBSD)
0x0098 MIPS II (4.4BSD, NetBSD, OpenBSD)
([3] claims R4000 but actually that was MIPS III, this should be R6000)
0x0099 Motorola 88K BSD (NetBSD, OpenBSD)
0x009A HP PA-RISC (NetBSD, OpenBSD)
0x009B SH5 with LP64 model (NetBSD)
0x009C SPARC with LP64 model (NetBSD)
0x009D AMD64/x86-64 (NetBSD, OpenBSD)
0x009E SH5 with ILP32 model (NetBSD)
0x009E MIPS 64-bit big endian (OpenBSD)
0x009F Intel Itanium (NetBSD)
0x009F AArch64/ARM64 (OpenBSD)
0x00A0 PowerPC 64-bit big endian (OpenBSD)
0x00A1 RISC-V 64-bit little endian (OpenBSD)
0x00B7 AArch64/ARM64 (NetBSD)
0x00B8 OpenRISC 1000 (NetBSD)
0x00B9 RISC-V (NetBSD)
0x00C8 HP200 68010 (4.3BSD, FreeBSD, NetBSD)
0x012C HP300 68020+68881 (4.3BSD, FreeBSD, NetBSD)
0x0208 HP s500[13]
0x020A HP s200 2.x[13]
0x020B HP/UX HP800 (4.3BSD, FreeBSD, NetBSD), PA-RISC1.0[13]
0x020C HP/UX HP200 or HP300 (4.3BSD, NetBSD), PA-RISC1.0 (OpenBSD), HP s200[13]
0x0210 HP700 HP-UX PA-RISC1.1 (OpenBSD)[13]
0x0214 HP700 HP-UX PA-RISC2.0 (OpenBSD)[13]
Bits 26:31 Flags (FreeBSD)[3]
Bit 30 Position independent code (FreeBSD, NetBSD)
Bit 31 Dynamic (SunOS, unknown version?, FreeBSD, NetBSD, OpenBSD)

In NetBSD and OpenBSD, the fields are in the native byte order, except for the magic number which is in the big endian ("network") format (most significant byte first, like the Motorola 68000). As an exception, on little endian machines, little endian order is allowed if the machine type field and flags are 0.

In FreeBSD since 2004-06-22, entries are always stored in the little endian format (least significant byte first, like the VAX and Intel 80386). However since 1994-05-25 it recognizes big endian entries for the magic number (the other entries are still read in the little endian order).

UNIX 32-bit Interdata 7/32 a.out header

This version was introduced in Version 7 for the Interdata 7/32 (big endian). It is identical to the PDP-11 version, except that the word sizes are 32-bit and the byte order is big endian.

x00 i32be Magic number
x04 i32be Size of program text (code)
x08 i32be Size of initialized data
x0C i32be Size of uninitialized data (bss), not stored in binary
x10 i32be Size of symbol table
x14 i32be Entry location
x18 i32be reserved
x1C i32be Non-zero if relocations have been suppressed

UNIX 32-bit IBM 370 a.out header

This version was introduced in System V for the IBM 370 (big endian). It is a variant of the VAX format.

x00 i32be Magic number
x04 i32be Stamp
x08 i32be Size of program text (code)
x0C i32be Size of initialized data
x10 i32be Size of uninitialized data (bss), not stored in binary
x14 i32be Size of symbol table
x18 i32be Entry location
x1C i32be Size of relocations for program text
x20 i32be Size of relocations for initialized data
x24 i32be Starting address of binary image
x28 i32be Size of program text without padding to page boundary
x2C i32be Size of initialized data without padding to page boundary

UNIX 32-bit NS16032 a.out header

There was a different version for National Semiconductor NS32K executables (little endian).

x00 i32le Magic number
x04 i32le Size of program text (code)
x08 i32le Size of initialized data
x0C i32le Size of uninitialized data (bss), not stored in binary
x10 i32le Size of symbol table
x14 i32le Entry location
x18 i32le Entry mod
x1C i32le Size of relocations for program text
x20 i32le Size of relocations for initialized data
x24 i32le Size of mod table, part of program text
x28 i32le Size of link table, part of program text
x2C i32le Size of string table

Xenix b.out header

The Xenix b.out header is very similar to the 32-bit VAX a.out header, with the field order slightly changed:

x00 i32 Magic number
x04 i32 Size of program text (code)
x08 i32 Size of initialized data
x0C i32 Size of uninitialized data (bss), not stored in binary
x10 i32 Size of symbol table
x14 i32 Size of relocations for program text
x18 i32 Size of relocations for initialized data
x1C i32 Entry location

HP-UX a.out header

HP-UX used a different format for a.out.[14]

x00 i32be Magic number
x04 i16be Version ID
x06 i16be Reserved
x08 i32be Miscellaneous information
x0C i32be Size of program text (code)
x10 i32be Size of initialized data
x14 i32be Size of uninitialized data (bss), not stored in binary
x18 i32be[5] Reserved
x2C i32be Entry location
x30 i32be[4] Reserved

Runtime memory layout

This section requires further work.

References


MINIX a.out file format

File extensions
Magic code
x01x03
Architecture
various, typically Intel 8086/80286, Intel 80386, Motorola 68000, SPARC
Operating systems
  • 1987: MINIX 1.0 before version 3.2
  • 1999-05-20: ELKS (Linux-8086)
Influences
various, typically Intel 8086/80286, Intel 80386, Motorola 68000, SPARC

Contents

  1. Contents
  2. Header
  3. References

Header

x00 i8[2] x01, x03
x02 i8 Flags (x10 for combined text/data executables, x20 for split text/data executables)
Bit 0 Unmapped zero page
Bit 1 Page aligned
Bit 2 New style symbol table
Bit 4 Executable
Bit 5 Separate instruction/data space
Bit 6 Pure text (not used)
Bit 7 Text overlay (not used)
x03 i8 CPU
Bit 0 encodes byte order in 16-bit word: 0 for little endian, 1 for big endian
Bit 1 encodes 16-bit word order in 32-bit longword: 0 for little endian, 1 for big endian
0x00 Unknown
0x04 Intel 8086
0x0B Motorola 68000
0x0C National Semiconductor 16032 (32016)
0x10 Intel 80368
0x17 Sun SPARC
x04 i8 Length of header, should be x20 or x30
x05 i8 Reserved
x06 i16 Version stamp (unused)
x08 i32 Size of text segment
x0C i32 Size of data segment
x10 i32 Size of bss segment
x14 i32 Entry point
x18 i32 Total memory allocated, including heap
x1C i32 Size of symbol table

The following fields are optional and only appear for a header of length x30.

x20 i32 Size of text relocations
x24 i32 Size of data relocations
x28 i32 Base of text relocations
x2C i32 Base of data relocations

References


COFF format (Common Object File Format)

File extensions
Magic code
various, encodes architecture
Architecture
various
Operating systems
  • 1983-01: UNIX System V Release 1.0
  • 1985: Concurrent DOS 68K
  • 1987-06: FlexOS 386
  • Around 1992: DJGPP DOS extender version 1.11
Influences
various

Contents

  1. Contents
  2. Overall layout
  3. File header
    1. ECOFF file header
    2. XCOFF64 file header
  4. Optional header
    1. 3B20 optional header
    2. NS32000 fields
    3. Concurrent DOS additional fields
    4. GNU_AOUT header fields
    5. Additional optional header fields for MIPS
    6. ECOFF optional header
    7. XCOFF32 additional fields
    8. XCOFF64 format
  5. Section header
    1. ECOFF section header
    2. XCOFF64 section header
  6. Relocation information
    1. Concurrent DOS 68K relocation information
  7. Line numbers
  8. Symbol table
  9. String table
  10. Further work
  11. References

Overall layout

Optional MZ stub (DJGPP only)
File header
Optional header (executables only)
Section header
Section data
Relocation information
Line numbers
Symbol table
String table

File header

x00 i16 f_magic, Magic number
x014C x4C x01 (SVR4) Intel 80386 programs[2][4][7] (used by DJGPP, reserved for Intel since SVR3)
x0150 x01 x50 (SVR2) Motorola 68000[5][7] (used by Concurrent DOS 68K)
Motorola MC68000[3]
x0088 x00 x88 (SVR2) Motorola 68000[3]
x0089 x00 x89 (SVR2) Motorola 68000 pure text[3]
x0093 x00 x93 (Sun 4.1.4) "C30" magic[3]
x0101 x01 x01 (Magic number for a.out PDP-11 "UNIX-rt ldp"[3])
x0105 x05 x01 (Magic number for a.out PDP-11 overlay[3])
x0107 x07 x01 (Magic number for a.out PDP-11, pre-System V VAX executable[3])
x0108 x08 x01 (Magic number for a.out PDP-11, pre-System V VAX executable, pure[3])
x0109 x09 x01 (Magic number for a.out PDP-11 separate I&D[3])
x011F x1F x01 (Magic number for a.out PDP-11 kernel overlay[3])
x0140 x01 x40 ECOFF MIPSEB, MIPS III[7]
x0140 x40 x01 ECOFF MIPSEB-LE, MIPS III[7]
x0142 x01 x42 ECOFF MIPSEL-BE, MIPS III[7]
x0142 x42 x01 ECOFF MIPSEL, MIPS III[7]
x0142 x42 x01 (SVR1) Intel x86 "Basic-16"[3][7]
x0143 x43 x01 (SVR1) Intel x86 "Basic-16" pure text[3][7]
x0144 x44 x01 (SVR3) Intel x86 "IAPX16" (used with cross compilers)[3]
x0145 x45 x01 (SVR3) Intel x86 "IAPX16" pure text (used with cross compilers)[3]
x0146 x46 x01 (SVR3) Intel x86 "IAPX20" (used with cross compilers)[3]
x0147 x47 x01 (SVR3) Intel x86 "IAPX20" pure text (used with cross compilers)[3]
x0148 x48 x01 (SVR1) Intel x86[3][7]
x0148 x48 x01 (Mach92) National Semiconductor NS160000
x0149 x49 x01 (SVR1) Intel x86 pure text[3][7]
x014A x4A x01 (SVR3) Intel 80286 small model program[3][2][7]
x014D (SVR4) Intel i860
x014D x4D x01 (Mach92) National Semiconductor NS160000 pure text
x014E x4E x01 (SVR3) Reserved for Intel[3]
x014F x4F x01 (SVR3) Reserved for Intel[3]
x0151 x01 x51 (SVR2) Motorola MC68000 pure text[3][7]
x0152 x52 x01 (SVR3) Intel 80286 large model program[3][2][7]
x0152 x01 x52 (SVR3) Motorola MC68000 demand paged text segment[3][7]
x0154 x54 x01 (SVR3) Reserved for National Semiconductor[3]
x0154 x54 x01 (Mach92) National Semiconductor NS32000
x0154 x54 x01 Linux 2.6.33.2 unused but mentioned for 386 PTX[3]
x0155 x55 x01 (SVR3) Reserved for National Semiconductor[3]
x0155 x55 x01 (Mach92) National Semiconductor NS32000 pure text
x0158 x01 x58 (SVR2) IBM 370[3]
x0159 x01 x59 (SVR3) Amdahl 470/580[3]
x015A x01 x5A (SVR3) Reserved for IBM 370
x015B x01 x5B (SVR3) Reserved for IBM 370
x015C x01 x5C (SVR3) Amdahl 470/580 pure text segments[3]
x015D x01 x5D (SVR2) IBM 370 pure text[3]
x0160 (SVR2 only) XL[3]
x0160 x01 x60 ECOFF MIPSEB[7]
x0160 x60 x01 ECOFF MIPSEB-LE[7]
x0160 (OpenBSD 4.6) i960[3]
x0161 (OpenBSD 4.6) i960 pure[3]
x0162 x01 x62 ECOFF MIPSEL-BE[7]
x0162 x62 x01 ECOFF MIPSEL[7]
x0163 x01 x63 ECOFF MIPSEB MIPS II[7]
x0163 x63 x01 ECOFF MIPSEB-LE MIPS II[7]
x0164 x01 x64 (SVR3) Reserved for Zilog[3] (presumably the Z8000/Z80000)
x0165 x01 x65 (SVR3) Reserved for Zilog[3] (presumably the Z8000/Z80000)
x0166 x01 x66 ECOFF MIPSEL-BE MIPS II[7]
x0166 x66 x01 ECOFF MIPSEL MIPS II[7]
x0168 x01 x68 (SVR1) AT&T 3B20[2][3][7]
x0168 x68 x01 (NetBSD 5.0.2) SH3 little endian[3]
x0169 x01 x69 (SVR1) AT&T 3B20 pure text[2][3][7]
x016C x01 x6C UniSoft 68K Binary Compatibility Standard[7]
x016D x01 x6D UniSoft 88K Binary Compatibility Standard[7]
x0170 x01 x70 (SVR1) AT&T 3B2, 3B15[2][3], WE 32000[3][7], MAC-80/MAC-32
x0171 x01 x71 (SVR1) AT&T 3B2, 3B15, WE 32000 pure text[3], MAC-80/MAC-32
x0172 x01 x72 (SVR2) Reserved for AT&T 3B2, 3B15, WE 32000 pure text[3], MAC-80/MAC-32
x0175 x75 x01 (OpenBSD 4.6) 386 Danbury AIX C[3]
x0178 x78 x01 (SVR1) VAX[3][2][7]
x017A x01 x7A (OpenBSD 4.6) Am29K big endian[3][7]
x017B x7B x01 (OpenBSD 4.6) Am29K little endian[3]
x017D x7D x01 (SVR1) VAX pure text[3][2][7], CLIPPER (VAX)[7]
x017F CLIPPER[7]
x0180 x01 x80 ECOFF MIPSEB u-code[7]
x0182 x01 x82 ECOFF MIPSEL-BE u-code[7]
x0183 x01 x83 ECOFF Alpha for Digital UNIX[7][9]
x0185 x01 x85 ECOFF NetBSD Alpha[7]
x0188 x01 x88 ECOFF Alpha compressed COFF[7][9]
x018F x01 x8F ECOFF Alpha u-code object[7], obsolete[9]
x0194 x01 x94 Apollo Motorola 88K COFF[7]
x0197 x01 x97 Apollo Motorola 68K COFF[7]
x01DF x01 xDF XCOFF 32-bit PowerPC[8]
x01F7 x01 xF7 XCOFF 64-bit PowerPC[8]
x1572 x15 x72 Am29K "prebar"[7]
x521C x1C x52 DSP21k[7]
SHARC[7]
x02 i16 f_nscns, Number of Sections
x04 i32 f_timdat, Time stamp, (CDOS COFF utility[5]: 0)
x08 i32 f_symptr, Offset to symbol table (CDOS COFF utility[5]: 0)
x0C i32 f_nsyms, Number of symbols in symbol table (CDOS COFF utility[5]: 0)
x10 i16 f_opthdr, Size of optional header
28 Standard UNIX a.out header (AOUTHDR)[1][4] (used by DJGPP[4])
32 GNU extensions (GNU_AOUT)[4]
36 CDOS coff utility[5]
x12 i16 f_flags, Flags (CDOS utility: x020F)
Bit 0 F_RELFLG, No relocations[1][2][4][5], also in XCOFF[8] and ECOFF[9]
Bit 1 F_EXEC, No unresolved symbols, executable[1][2][4][5], also in XCOFF[8] and ECOFF[9]
Bit 2 F_LNNO, No line number information[1][2][4][5], also in XCOFF[8] and ECOFF[9]
Bit 3 F_LSYMS, No local symbols[1][2][4][5], also in XCOFF[8] and ECOFF[9]
Bit 4 F_MINMAL, "minimal object file"[2][3], produced by fextract[3]
F_FDPR_PROF (XCOFF), profiled using fdpr[8]
F_NO_SHARED (ECOFF), unused[9]
Bit 5 F_UPDATE, "update file", produced by ogen[2][3]
F_FDPR_OPTI (XCOFF), reordered using fdpr[8]
F_NO_CALL_SHARED (ECOFF), cannot be used to create dynamic executable file[9]
Bit 6 F_SWABD, file is "pre-swabbed"[2], in name[3]
F_DSA (XCOFF), very large program support[8]
F_LOMAP (ECOFF), static executable may be loaded below VM_MIN_ADDRESS (x10000), invalid for dynamic executables[9]
Bit 7 F_AR16WR, Little endian, 16-bit (like PDP-11/70)[1][2][3]
F_DEP_1 (XCOFF), data-execute permissions[8]
Bit 8 F_AR32WR, Little endian, 32-bit (like VAX)[1][2][3][4]
F_VARPG (XCOFF), the medium page size specified in the auxiliary header is 0[8]
Bit 9 F_AR32W, Big endian, 32-bit, "non-DEC host" (like 3B)[2][3][5]
reserved (XCOFF)[8]
Bit 10 F_PATCH, optional header contains "patch" list[2][3]
F_NODF, minimal object files contain no decision functions for replaced functions[3]
F_LPTEXT (XCOFF), reserved[8]
Bit 11 F_LPDATA (XCOFF), requires large page data[8]
Bit 12 F_BM32RST, contains "restore work-around"[2][3]
F_LPTEXT (XCOFF), reserved[8]
Bit 13-15 F_BM32ID, Bellmac-32/WE32000 family ID fields (V9 and later)[2][3]
Bit 13 F_BM32B, contains WE32100 instructions (V9 and later)[2][3]
Bit 14 F_BM32MAU, requires "math arithmetic unit" (V10 and later)[2][3]
Bit 12 F_80186, contains Intel 80186 instructions (V10 and later)[2][3]
Bit 13 F_80286, contains Intel 80286 instructions (V10 and later)[2][3]
Bit 12 F_DYNLOAD (XCOFF), dynamically executable[8]
Bit 12-13 (ECOFF)
0x2000 F_SHARABLE, shared library[9]
0x3000 F_CALL_SHARED, dynamic executable file[9]
Bit 13 F_SHROBJ (XCOFF), shared library[8]
Bit 14 F_LOADONLY (XCOFF), for shared objects, ignore when part of a library[8]
F_NO_REORG (ECOFF), do not reorder sections[9]
Bit 15 F_DEP_1 (XCOFF), data-execute permissions[8]
F_NO_REMOVE (ECOFF), do not remove NOPs[9]

ECOFF file header

The ECOFF header is nearly identical to the standard COFF header, with one field enlarged.[9]

x00 i16 f_magic, Magic number
x02 i16 f_nscns, Number of Sections
x04 i32 f_timdat, Time stamp
x08 i64 f_symptr, Offset to symbol table
x10 i32 f_nsyms, Number of symbols in symbol table
x14 i16 f_opthdr, Size of optional header
x16 i16 f_flags, Flags

XCOFF64 file header

The XCOFF32 header is identical to the standard COFF header. However, the XCOFF64 header has an 8-byte f_symptr entry, requiring f_nsyms to be moved after the final field.[8]

x00 i16 f_magic, Magic number
x02 i16 f_nscns, Number of Sections
x04 i32 f_timdat, Time stamp
x08 i64 f_symptr, Offset to symbol table
x10 i16 f_opthdr, Size of optional header
x12 i16 f_flags, Flags
x14 i32 f_nsyms, Number of symbols in symbol table

Optional header

The first variant presented here is the standard Unix a.out header (AOUTHDR).

The values used by DJGPP and Concurrent DOS 68K will be remarked on.

x00 i16 magic - Magic (CDOS COFF utility[5]: 0)
x0107 OMAGIC
Contiguous text and data segments
Text segment is not write-protected or sharable[1]
x0108 NMAGIC
Data segment starts at segment boundary following text segment
Text segment is write-protected[1]
x010B ZMAGIC (used by DJGPP[4])
Text and data segments are page aligned[1]
x0123 SHMAGIC[6]
Shared library[1]
x02 i16 vstamp - Version stamp[1][4] (DJGPP ignores this field[4], CDOS COFF utility[5]: 0)
x04 i32 tsize - Text size in bytes (DJGPP ignores this field[4])
x08 i32 dsize - Data size in bytes (DJGPP ignores this field[4])
x0C i32 bsize - Bss size in byte (DJGPP ignores this field[4])
x10 i32 entry - Entry point (CDOS COFF utility[5]: 0)
x14 i32 text_start - Address of text start (DJGPP ignores this field[4], CDOS COFF utility[5]: 0)
x18 i32 data_start - Address of data start (DJGPP ignores this field[4])

3B20 optional header

x00 i16 magic - Magic
x02 i16 vstamp - Version stamp
x04 i32 tsize - Text size in bytes
x08 i32 dsize - Data size in bytes
x0C i32 bsize - Bss size in byte
x10 c[8] Padding
x18 i32 entry - Entry point
x1C i32 text_start - Address of text start
x20 i32 data_start - Address of data start

NS32000 fields

x00 i16 magic - Magic
x02 i16 vstamp - Version stamp
x04 i32 tsize - Text size in bytes
x08 i32 dsize - Data size in bytes
x0C i32 bsize - Bss size in byte
x10 i32 msize - Module size in bytes
x14 i32 mod_start - Address of module
x18 i32 entry - Entry point
x1C i32 text_start - Address of text start
x20 i32 data_start - Address of data start
x24 i16 entry_mod - Entry module
x26 i16 flags
Bits 0:2 section alignment
0x00 fullword alignment
0x01 512 B
0x02 1 KiB
0x03 2 KiB
0x04 4 KiB
0x05 8 KiB
Bit 3 data
Bit 4 text
Bit 5 module
Bit 8 System V relocations
Bit 9 SVR4.2 BSD relocations

Concurrent DOS additional fields

The following additional fields are defined, after regular AOUTHDR fields in Optional header:[5]

x1C i32 relptr - Relocation information (CDOS coff utility: directly after text, data and bss images)
x20 i32 ssize - Stack size

GNU_AOUT header fields

DJGPP seems to support the following format aside from the original System V format[GNUAOUT.H]

Additional optional header fields for MIPS

The following fields are used additionally for MIPS.[10]

x1C i32 bss_start - Address of bss start
x20 i32 gprmask - general purpose register mask
x24 i32[4] cprmask - coprocessor purpose register masks
x34 i32 gp_value - the gp value for this object

ECOFF optional header

x00 i16 magic - Magic
x02 i16 vstamp - Version stamp, must be x030D[9]
x04 i16 bldrev - Revision number of the build tools
0x0000 1.2
0x0002 1.3
0x0004 2.0
0x0006 3.0
0x0008 3.2
0x000A 4.0
0x000C 5.0
x06 i16 padcell - Unused
x08 i64 tsize - Text size in bytes
x10 i64 dsize - Data size in bytes
x18 i64 bsize - Bss size in byte
x20 i64 entry - Entry point
x28 i64 text_start - Address of text start
x30 i64 data_start - Address of data start
x38 i64 bss_start - Address of bss start
x40 i32 gprmask - Unused
x44 i32 fprmask - Unused
x48 i64 gp_value - Initial value of the GP (global pointer) register

XCOFF32 additional fields

XCOFF redefines the value of the magic field.[8]

x00 i16 mflag - Flags, only used if vstamp is greater than 1, or 1 in XCOFF32 with flags having _AOUT_ALGNTDATA set
0x003F Bits for ASLR properties in XCOFF32 executable
0x03FF Bits for ASLR properties in XCOFF64 executable
0x3C00 Reserved
0x4000 AOUT_MFLAG_ASLR_TEXTRLD, the text section has relocations
0x8000 AOUT_MFLAG_ASLR_MARKED, uses address space layout randomization fields

The following additional fields are defined:[8]

x1C i32 toc - Address of TOC (table of contents) anchor
x20 i32 snentry - Entry point section number
x22 i16 sntext - Section number for text segment
x24 i16 sndata - Section number for data segment
x26 i16 sntoc - Section number for TOC segment
x28 i16 snloader - Section number for loader data
x2A i16 snbss - Section number for bss segment
x2C i16 algntext - Maximum alignment for text segment
x2E i16 algndata - Maximum alignment for data segment
x30 i16 modtype - Module type
x32 i8 cpuflag - CPU flag (reserved)
x33 i8 cputype - CPU type (reserved)
x34 i32 maxstack - Maximum stack
x38 i32 maxdata - Maximum data
x3C i32 debugger - Reserved
x40 i8 textpsize - Text page size
x41 i8 datapsize - Data page size
x42 i8 stackpsize - Stack page size
x43 i8 flags - Flags
Bit 0-3 _AOUT_ALGNTDATA, alignment of thread-local data
0x0-0x8 Base 2 logarithm of alignment
0xC 4KiB page alignment
0xD 64KiB page alignment
Bit 6 _AOUT_RAS, key and recovery safe kernel extension
Bit 7 _AOUT_TLS_LE, uses local-exec model, cannot be loaded dynamically
x44 i16 sntdata - Section number for tdata segment
x46 i16 sntbss - Section number for tbss segment

XCOFF64 format

The 64-bit version enlarges some fields and moves them around, maintaining their natural alignment:[8]

x00 i16 mflag - Flags
x02 i16 vstamp - Version stamp
x04 i32 debugger - Reserved
x08 i64 text_start - Address of text start
x10 i64 data_start - Address of data start
x18 i64 toc - Address of TOC (table of contents) anchor
x20 i32 snentry - Entry point section number
x22 i16 sntext - Section number for text segment
x24 i16 sndata - Section number for data segment
x26 i16 sntoc - Section number for TOC segment
x28 i16 snloader - Section number for loader data
x2A i16 snbss - Section number for bss segment
x2C i16 algntext - Maximum alignment for text segment
x2E i16 algndata - Maximum alignment for data segment
x30 i16 modtype - Module type
x32 i8 cpuflag - CPU flag (reserved)
x33 i8 cputype - CPU type (reserved)
x34 i8 textpsize - Text page size
x35 i8 datapsize - Data page size
x36 i8 stackpsize - Stack page size
x37 i8 flags - Flags
x38 i64 tsize - Text size in bytes
x40 i64 dsize - Data size in bytes
x48 i64 bsize - Bss size in byte
x50 i64 entry - Entry point
x58 i64 maxstack - Maximum stack
x60 i64 maxdata - Maximum data
x68 i16 sntdata - Section number for tdata segment
x6A i16 sntbss - Section number for tbss segment
x6C i16 x64flags - XCOFF64 flags
x6E i16 shmpsize64 - Shared memory page size

Section header

x00 c[8] s_name - Section name, padded with nulls
x08 i32 s_paddr - Physical address for section data
x0C i32 s_vaddr - Virtual address (identical to physical address for DJGPP[4] and CDOS[5])
x10 i32 s_size - Size of data in image in bytes
x14 i32 s_scnptr - Offset to section data from COFF file start
x18 i32 s_relptr - Offset to relocation data (CDOS coff utility[5]: 0)
x1C i32 s_lnnoptr - Offset to line number entries (CDOS coff utility[5]: 0)
x20 i16 s_nreloc - Number of relocations (CDOS coff utility[5]: 0)
x22 i16 s_nlnno - Number of line numbers (CDOS coff utility[5]: 0)
x24 i32 s_flags - Flags
x00000000 STYP_REG - Regular section (allocated, relocated, loaded)[1], also ECOFF[9], reserved in XCOFF[8]
x00000001 STYP_DSECT - Dummy section (not allocated, relocated, not loaded)[1]
x00000002 STYP_NOLOAD - Noload section (allocated, relocated, not loaded)[1]
x00000004 STYP_GROUP - Grouped section[1]
x00000008 STYP_PAD - Padding section (not allocated, not relocated, loaded)[1] also XCOFF[8]
x00000010 STYP_COPY - Copy section, for a decision function used in updating fields
(not allocated, not relocated, loaded, relocation and line numbers are processed normally)[1]
STYP_DWARF (XCOFF) - DWARF debugging section[8]
x00000020 STYP_TEXT - Executable text code, also XCOFF[8] and ECOFF[9]
x00000040 STYP_DATA - Initialized data, also XCOFF[8] and ECOFF[9]
x00000080 STYP_BSS - Uninitialized data, also XCOFF[8] and ECOFF[9]
x00000100 STYP_EXCEPT (XCOFF) - Exception section[8]
STYP_RDATA (ECOFF) - Read-only data[9]
x00000200 STYP_INFO - Comment section (not allocated, not relocated, not loaded)[1], also XCOFF[8]
STYP_SDATA (ECOFF) - Small initialized data[9]
x00000400 STYP_OVER - Overlay section (not allocated, relocated, not loaded)[1]
STYP_TDATA (XCOFF) - thread-local initialized data section[8]
STYP_SBSS (ECOFF) - Small uninitialized data[9]
x00000800 STYP_LIB - .lib section, treated like a comment section[1]
STYP_TBSS (XCOFF) - thread-local uninitialized data section[8]
STYP_UCODE (ECOFF) - Obsolete[9]
x00001000 STYP_LOADER (XCOFF) - Loader section[8]
STYP_GOT (ECOFF) - Global offset table[9]
x00002000 STYP_DEBUG (XCOFF) - Debug section[8]
STYP_DYNAMIC (ECOFF) - Dynamic linking information[9]
x00004000 STYP_TYPCHK (XCOFF) - Type-check section[8]
STYP_DYNSYM (ECOFF) - Dynamic linking symbol table[9]
x00008000 STYP_OVRFLO (XCOFF32 only) - Overflow section[8]
STYP_REL_DYN (ECOFF) - Dynamic relocation information[9]
x00010000 STYP_DYNSTR (ECOFF) - Dynamic linking symbol table[9]
x00020000 STYP_HASH (ECOFF) - Dynamic symbol hash table[9]
x00040000 STYP_DSOLIST (ECOFF) - Shared library dependency list[9]
x00080000 STYP_MSYM (ECOFF) - Additional dynamic linking symbol table[9]
x0FF00000 STYP_EXTMASK (ECOFF) - Mask for multiple bit flag values[9]
x00100000 STYP_CONFLICT (ECOFF) - Additional dynamic linking information[9]
x01000000 STYP_FINI (ECOFF) - Termination text only[9]
x02000000 STYP_COMMENT (ECOFF) - Comment section[9]
x02200000 STYP_RCONST (ECOFF) - Read-only constants[9]
x02400000 STYP_XDATA (ECOFF) - Exception scope table[9]
x02500000 STYP_TLSDATA (ECOFF) - Initialized TLS data[9]
x02600000 STYP_TLSBSS (ECOFF) - Uninitialized TLS data[9]
x02700000 STYP_TLSINIT (ECOFF) - Initialization for TLS data[9]
x02800000 STYP_PDATA (ECOFF) - Exception procedure table[9]
x04000000 STYP_LITA (ECOFF) - Address literals only[9]
x08000000 STYP_LIT8 (ECOFF) - 8-byte literals only[9]
x10000000 STYP_LIT4 (ECOFF) - 4-byte literals only[9]
x20000000 S_NRELOC_OVFL (ECOFF) - The s_nreloc field has overflowed and contains xFFFF[9]
In this case, the first relocation entry contains the actual relocation count
x80000000 STYP_INIT (ECOFF) - Initialization text only[9]

ECOFF section header

x00 c[8] s_name - Section name, padded with nulls
x08 i64 s_paddr - Physical address for section data
x10 i64 s_vaddr - Virtual address
x18 i64 s_size - Size of data in image in bytes
x20 i64 s_scnptr - Offset to section data from COFF file start
x28 i64 s_relptr - Offset to relocation data
x30 i64 s_lnnoptr - Offset to line number entries
x38 i16 s_nreloc - Number of relocations
x3A i16 s_nlnno - Number of line numbers
x3C i32 s_flags - Flags

XCOFF64 section header

x00 c[8] s_name - Section name, padded with nulls
x08 i64 s_paddr - Physical address for section data
x10 i64 s_vaddr - Virtual address
x18 i64 s_size - Size of data in image in bytes
x20 i64 s_scnptr - Offset to section data from COFF file start
x28 i64 s_relptr - Offset to relocation data
x30 i64 s_lnnoptr - Offset to line number entries
x38 i32 s_nreloc - Number of relocations
x3C i32 s_nlnno - Number of line numbers
x40 i32 s_flags - Flags

Relocation information

The typical relocation information is a sequence of relocation records as shown below.

x00 i32 r_vaddr - Virtual address of reference
x04 i32 r_symndx - Symbol table index
x08 i16 r_type - Symbol type
x00 R_ABS - Absolute reference, no relocation necessary[1]
x01 R_DIR16 - (80286 only) Direct 16-bit reference to symbol's virtual address[1]
x02 R_REL16 - (80286 only) PC-relative 16-bit reference to symbol's virtual address[1]
x06 R_DIR32 - Direct 32-bit reference to symbol's virtual address[1]
RELOC_ADDR32 for DJGPP[4]
x09 R_SEG12 - (80286 only) Direct 16-bit reference to symbol's segment-selector bits of a 32-bit virtual address[1]
x14 R_PCRLONG - (80386 only) PC-relative 32-bit reference to symbol's virtual address[1]
RELOC_REL32 for DJGPP[4]

Concurrent DOS 68K relocation information

Concurrent DOS 68K uses a different relocation structure. Its position is stored in the optional header instead of the file header. The contents of the relocations are identical to crunched relocations in the CP/M-68K file format.

Line numbers

x00 i32 Symbol table index (if line number is 0) or virtual address
x04 i16 1-based line number
0 for symbol table index

Symbol table

x00 c[8] name - Symbol name, zero-padded (first 4 bytes should not be all zero)
x00 i32 zeroes - If zero, the symbol is inlined
x04 i32 offset - Offset to name in symbol table (only if first 4 bytes are zero)
x08 i32 value - Value of symbol
x0C i16 scnum - Section number, 1-based
0x0000 N_UNDEF - External/undefined symbol
0xFFFF N_ABS - Absolute symbol
0xFFFE N_DEBUG - Debugging symbol
x0E i16 type - Symbol type: base type
x0000 T_NULL - No symbol
x0001 T_ARG - Function argument[1]
T_VOID - void[4]
x0002 T_CHAR - char, int8
x0003 T_SHORT - short int, int16
x0004 T_INT - int
x0005 T_LONG - long int, int32
x0006 T_FLOAT - float
x0007 T_DOUBLE - double
x0008 T_STUCT - struct ...
x0009 T_UNION - union ...
x000A T_ENUM - enum ...
x000B T_MOE - Member in enumeration
x000C T_UCHAR - unsigned char, uint8
x000D T_USHORT - unsigned short int, uint16
x000E T_UINT - unsigned int
x000F T_ULONG - unsigned long int, uint32
x0010 T_LNGDBL - long double[4]
x0000 DT_NON - Not a derived type
x0010 DT_PTR - Pointer
x0020 DT_FUN - Function
x0030 DT_ARY - Array
x10 i8 sclass - Storage class
x00 C_NULL - No entry
x01 C_AUTO - Automatic
x02 C_EXT - External/public
x03 C_STAT - Static/private
x04 C_REG - Register
x05 C_EXTDEF - External definition
x06 C_LABEL - Label
x07 C_ULABEL - Undefined label
x08 C_MOS - Member of structure
x09 C_ARG - Function argument
x0A C_STRTAG - Structure tag
x0B C_MOU - Member of union
x0C C_UNTAG - Union tag
x0D C_TPDEF - Type definition
x0E C_USTATIC - Undefined static
x0F C_ENTAG - Enumeration tag
x10 C_MOE - Member of enumeration
x11 C_REGPARM - Register parameter
x12 C_FIELD - Bitfield
x13 C_AUTOARG - Auto argument[4]
x14 C_LASTENT - Dummy argument[4]
x64 C_BLOCK - Beginning/end of block (.bb, .eb)
x65 C_FCN - Beginning/end of function (.bf, .ef)
x66 C_EOS - End of structure
x67 C_FILE - File name
x68 C_LINE - Line number as symbol[4], Used only by utility programs[1]
x69 C_ALIAS - Duplicated tag
x6A C_HIDDEN - Shadow symbol[1], ext symbol in dmert public lib[4]
x6B C_WEAKEXT - Weak linkage C_EXT[1]
xFF C_EFCN - Physical end of function
x11 i8 numaux - Number of auxiliary entries, each entry occupying a symbol record

String table

A sequence of null-terminated strings. The first 4 bytes specify the size of the string table in bytes, including the first 4 bytes. References to string must be between 4 and this value.

Further work

The XCOFF and ECOFF formats require further work.

References


XENIX x.out file format

File extensions
Magic code
x0206
Architecture
various, including PDP-11, Z8000, Intel 8086/80186/80286 and Intel 80386, Motorola 68000, Zilog Z80, VAX, NS32000
Operating systems
1984: XENIX Release 3
Influences
various, including PDP-11, Z8000, Intel 8086/80186/80286 and Intel 80386, Motorola 68000, Zilog Z80, VAX, NS32000

Contents

  1. Contents
  2. Header
  3. Header extension
  4. Segment table
  5. Further work
  6. References

Header

x00 i16 x_magic, x0206
x02 i16 x_ext, size of Header extension
x04 i32 x_text, size of text segment
for segmented images, sum of all the corresponding segment sizes (xs_psize or xs_vsize)
x08 i32 x_data, size of initialized data segment
for segmented images, sum of all the corresponding segment sizes (xs_psize or xs_vsize)
x0C i32 x_bss, size of uninitialized data segment
for segmented images, sum of all the corresponding segment sizes (xs_psize or xs_vsize)
x10 i32 x_syms, size of symbol table
for segmented images, sum of all the corresponding segment sizes (xs_psize or xs_vsize)
x14 i32 x_reloc, size of relocation table
for segmented images, sum of all the corresponding segment sizes (xs_psize or xs_vsize)
x18 i32 x_entry, entry point
x1C i8 x_cpu, CPU type and word order
Bits 0:4
0x01 PDP-11
0x02 PDP-11/23 (?)
0x03 Zilog Z8000
0x04 Intel 8086
0x05 Motorola 68000
0x06 Zilog Z80
0x07 VAX 780/750
0x08 National Semiconductor 32000 (NS16032)
0x09 Intel 80286
0x29 Intel 80286 (?)
0x0A Intel 80386
0x0B Intel 80186
Bit 5 set if least significant word comes first in 32-bit word (little-endian)
Bit 6 set if most significant byte comes first in 16-bit word (big-endian)
x1D i8 x_relsym, relocation & symbol format, only valid for non-segmented binaries
Bits 0:3 symbol table format
Bits 4:7 relocation table format
x1E i16 x_renv, run-time environment
Bit 0 XE_EXEC, executable
Bit 1 XE_SEP, separate I & D
Bit 2 XE_PURE, pure text
Bit 3 XE_FS, fixed stack
Bit 4 XE_OVER, text overlay
Bit 5 XE_LDATA, large model data
Bit 6 XE_LTEXT, large model text
Bit 7 XE_FPH, floating point hardware required
Bit 8 XE_HDATA, XE_VMOD, virtual module or huge model data (not used)
Bit 9 XE_ITER, iterated text/data present
Bit 10 XE_ABS, absolute memory image with physical addresses, standalone
Bit 11 XE_SEG, segment table present
Bit 12 XE_LOCK, use advisory locking (0)
Bit 13 XE_5_3, 5.3 functionality required (0)
Bits 14:15 XE_VERS, Version
0x40 XE_V2, Version 2.x
0x80 XE_V3, Version 3.x
0xC0 XE_OSV, XE_V5, Version 5.x

On a 386, bits 0, 8, 10 of x_renv must take one the following values:

x0001 executable, no shared libraries
x0100 shared library
x0101 executable, uses shared libraries
x0401 standalone program, kernel
x0500 virtual kernel module

Header extension

x20 i32 xe_trsize, size of text relocations
for segmented images, sum of all corresponding segment sizes
not used
x24 i32 xe_drsize, size of initialized data relocations
for segmented images, sum of all corresponding segment sizes
not used
x28 i32 xe_tbase, text relocation base
unused for segmented images
not used
x2C i32 xe_dbase, text relocation base
unused for segmented images
not used
x30 i32 xe_stksize, fixed stack size, only if XE_FS is set

The following fields are mandatory in segmented executables:

x34 i32 xe_segpos, offset to Segment table
x38 i32 xe_segsize, size of Segment table
x3C i32 xe_mdtpos, offset to machine dependent table
x40 i32 xe_mdtsize, size of machine dependent table
x44 i8 xe_mdttype, type of machine dependent table
0x00 XE_MDTNONE
0x01 XE_MDT286, Intel 80286 LDT
x45 i8 xe_pagesize, size of file page, in 512 bytes
x46 i8 xe_ostype, type of operating system
0x00 XE_OSNONE
0x01 XE_OSXENIX, Xenix
0x02 XE_OSRMX, Intel iRMX
0x03 XE_OSCCPM, Concurrent CP/M
x47 i8 xe_osvers, version of operating system
0x00 XE_OSXV2, Xenix 2.x
0x01 XE_OSXV3, Xenix 3.x
0x02 XE_OSXV5, Xenix 5.x
x48 i16 xe_eseg, segment for entry (machine dependent)
x4A i16 xe_sres, reserved

Segment table

x00 i16 xs_type, type of segment
0x00 XS_TNULL, unused
0x01 XS_TTEXT, text segment
0x02 XS_TDATA, data segment
0x03 XS_TSYMS, symbol table segment
0x04 XS_TREL, relocation segment
0x05 XS_TSESTR, string table for segment table
0x06 XS_TGRPS, group definition segment
0x40 XS_TIDATA, iterated data
0x41 XS_TTSS, TSS segment
0x42 XS_TLFIX, "lodfix"
0x43 XS_TDNAME, descriptor names
0x44 XS_TDTEXT/XS_TIDBG, debug text segment
0x45 XS_TDFIX, debug relocation
0x46 XS_TOVTAB, overlay table
0x47 XS_T71
0x48 XS_TSYSTR, string table for symbols
x02 i16 xs_attr, attributes
Bit 0 XS_AITER, contains iteration records (XS_TTEXT/XS_TDATA)
Bit 1 XS_AHUGE, contains huge elements (XS_TTEXT/XS_TDATA)
Bit 2 XS_ABSS, contains implicit bss (XS_TTEXT/XS_TDATA)
Bit 3 XS_APURE, read-only shareable (XS_TTEXT/XS_TDATA)
Bit 4 XS_AEDOWN, expand down segment such as stack (XS_TTEXT/XS_TDATA)
Bit 5 XS_APRIV, segment may not be combined, private (XS_TTEXT/XS_TDATA)
Bit 6 XS_A32BIT, 32-bit segment
Bits 0:14 for XS_TSYMS segment, symbol table format
0x0000 Bell 5.2
0x0001 x.out segmented
0x0002 island debugger support
Bits 0:14 for XS_TREL segment, enumerated relocation table format
0x0001 x.out segmented
0x0002 8086 x.out segmented
Bit 15 XS_AMEM, segment represents memory image
x04 i16 xs_seg, segment number
x06 i8 xs_align, alignment, as base 2 logarithm
x07 i8 xs_cres, unused
x08 i32 xs_filpos, offset to segment image in file, in pages for 386 (see xe_pagesize)
x0C i32 xs_psize, size of segment in file
x10 i32 xs_vsize, size of segment in memory
x14 i32 xs_rbase, base address for relocations, modulo page size for 386 (see xe_pagesize)
x18 i16 xs_noff, offset to segment name in string table
x1A i16 xs_sres, reserved
x1C i32 xs_lres, reserved

Further work

This format requires further research.

References

  • [1] XENIX 286 C Library Guide, Appendix B (1984-11)
  • [2] ACS-586 XENIX C Compiler Release Notes (1984-05-29)
  • [3] XENIX System V Development System C Language Guide, Section 7.17 (1987-06-28)
  • [4] XENIX System V Development System C Language Guide, Section 7.17 (1988-10)
  • [5] XENIX System V Operating System User's Guide

Mach-O format (for Mach object)

File extensions
Magic code
xFEEDFACE for 32-bit, xFEEDFACF for 64-bit, xCAxFExBAxBE for fat binary
Architecture
various
Operating systems
  • not before 1985: Mach
  • 1988-10-12: NeXTSTEP 0.8
  • 1992-01: OSF/1?
  • 2001-03-24: Mac OS X/macOS, iOS
Influences
various

Contents

  1. Contents
  2. Further work
  3. References

Further work

This format requires documentation.

References


ELF format (Executable and Linkable Format)

File extensions
.exe for OS/2 Warp PowerPC Edition
Magic code
"\x7FELF"
Architecture
various
Operating systems
  • 1988-10-18: System V Release 4.0 (replacing COFF)
  • ?: BeOS Developer Release 4 for AT&T Hobbit
  • 1995-03: Linux 1.2 (replacing a.out)
  • 1995-12: OS/2 Warp PowerPC Edition (replacing LE)
  • 1997-05-12?: PowerUP for Amiga (replacing Hunk)
  • 2004-04: AmigaOS 4.0 (replacing and complementing Hunk)
  • 1998-10: FreeBSD 3.0 (replacing a.out)
  • 1998-11-04: BeOS Release 4 on Intel 80386 (replacing PE)
  • 2000-12: NetBSD 1.5 (replacing a.out)
  • 2012-02-29: MINIX 3.2.0 (replacing a.out for MINIX)
Influences
various

Contents

  1. Contents
  2. Notes on the format
  3. Overall layout
  4. ELF header
  5. Program header
  6. Section header
    1. Symbol table
  7. OS/2 resource file format
    1. Resource collection array entry
    2. Resource collection
  8. OS/2 operating system information (.osinfo)
  9. OS/2 import table (.imports)
  10. OS/2 export table (.exports)
  11. BeOS Developer Release 4 resources
  12. Segment contents
  13. Dynamic linking
  14. Further work
  15. References

Notes on the format

The ELF format is well documented in an accessible format online. This section also focuses on some of the more obscure features, such as the extensions provided by IBM's port of OS/2 to the PowerPC architecture.[3]

Overall layout

ELF header
Program header, optional for objects, required for executables
Segment/section data
Section header, required for objects, optional for executables

ELF header

x00 c[0x10] e_ident, machine-independent data to interpret the file's content, such as word size and byte order
x00 c[4] EI_MAG = ELFMAG = "\x7F" "ELF", signature
x04 i8 EI_CLASS, file class
0 ELFCLASSNONE, invalid
1 ELFCLASS32, offsets and addresses are encoded as 32-bit fields
2 ELFCLASS64, offsets and addresses are encoded as 64-bit fields
x05 i8 EI_DATA, data encoding
0 ELFDATANONE, invalid
1 ELFDATA2LSB, 2's complement, least significant byte first (little endian)
2 ELFDATA2MSB, 2's complement, most significant byte first (big endian)
x06 i8 EI_VERSION, file version
0 EV_NONE, invalid
1 EV_CURRENT, current version
x07 i8 EI_OSABI, operating system and ABI
x08 i8 EI_ABIVERSION, ABI version
x09 c[9] EI_PAD, padding, filled with zeros
x0F EI_NIDENT, end of e_ident
x10 i16 e_type, object type
0x0000 ET_NONE, no type
0x0001 ET_REL, relocatable
0x0002 ET_EXEC, executable
0x0003 ET_DYN, shared object
0x0004 ET_CORE, core dump
0xFE00 ET_LOOS, first operating system specific
0xFEFF ET_HIOS, last operating system specific
0xFF00 ET_LOPROC, first processor specific
0xFFFF ET_HIPROC, last processor specific
x12 i16 e_machine, architecture type (partial list)
0x0000 EM_NONE, no machine
0x0001 EM_M32, "AT&T WE 32100"
0x0002 EM_SPARC, "SPARC"
0x0003 EM_386, "Intel 80386"
0x0004 EM_68K, "Motorola 68000"
0x0005 EM_88K, "Motorola 88000"
0x0008 EM_MIPS, "MIPS I"
0x0014 EM_PPC, 32-bit "PowerPC"
0x0015 EM_PPC64, "64-bit PowerPC"
0x0028 EM_ARM, "ARM 32-bit architecture (AARCH32)"
0x0029 EM_ALPHA, "Digital Alpha"
0x002B EM_SPARCV9, "SPARC Version 9"
0x0032 EM_IA_64, "Intel IA-64 processor architecture", Itanium
0x003E EM_X86_64, "AMD x86-64 architecture", AMD64
0x0040 EM_PDP10, "Digital Equipment Corp. PDP-10"
0x0041 EM_PDP11, "Digital Equipment Corp. PDP-11"
0x004B EM_VAX, "Digital VAX"
0x0050 EM_MMIX, "Donald Knuth's educational 64-bit processor"
0x005C EM_OPENRISC, "OpenRISC 32-bit embedded processor"
0x0061 EM_NS32K, "National Semiconductor 32000 series"
0x00B7 EM_AARCH64, "ARM 64-bit architecture (AARCH64)"
0x00DC EM_Z80, "Zilog Z80"
0x00F3 EM_RISCV, "RISC-V"
0x00F4 EM_LANAI, "Lanai 32-bit processor"[2]
0x00F5 EM_CEVA, "CEVA Processor Architecture Family"[2]
0x00F6 EM_CEVA_X2, "CEVA X2 Processor Family"[2]
0x00F7 EM_BPF, "Linux BPF"[2]
0x00F8 EM_GRAPHCORE_IPU, "Graphcore Intelligent Processing Unit"[2]
0x00F9 EM_IMG1, "Imagination Technologies"[2]
0x00FA EM_NFP, "Netronome Flow Processor"[2]
0x00FB EM_VE, "NEC Vector Engine"[2]
0x00FC EM_CSKY, "C-SKY processor family"[2]
0x00FD EM_ARC_COMPACT3_64, "Synopsys ARCv2.3 64-bit"[2]
0x00FE EM_MCS6502, "MOS Technologies MCS 6502 processor"[2]
0x00FF EM_ARC_COMPACT3, "Synopsys ARCv2.3 32-bit"[2]
0x0100 EM_KVX, "Kalray VLIW core of the MPPA processor family"[2]
0x0101 EM_65816, "WDC 65816/65C816"[2]
0x0102 EM_LOONGARCH, "LoongArch"[2]
0x0103 EM_KF32, "ChipON KungFu32"[2]
0x0104 EM_U16_U8CORE, "LAPIS nX-U16/U8"[2]
0x0105 EM_TACHYUM, "Tachyum"[2]
0x0106 EM_56800EF, "NXP 56800EF Digital Signal Controller (DSC)"[2]
0x1966 EM_MOS, MOS 6502 family (duplicates EM_MCS6502 and EM_65816)LLVM-MOS
x14 i32 e_version, object file format version
0 EV_NONE, invalid
1 EV_CURRENT, current version
x18 i32i64 e_entry, virtual address of entry point
x1Cx20 i32i64 e_phoff, offset to Program header in bytes from file start
x20x28 i32i64 e_shoff, offset to Section header in bytes from file start
x24x30 i32 e_flags, processor specific flags
x28x32 i16 e_ehsize, size of ELF header in bytes
for EV_CURRENT, it should be x34 for 32-bit objects, x3E for 64-bit objects
x2Ax34 i16 e_phentsize, size of a single entry in Program header in bytes
for EV_CURRENT, if non-zero, it should be x20 for 32-bit objects, x38 for 64-bit objects
x2Cx36 i16 e_phnum, number of entries in Program header
x2Ex38 i16 e_shentsize, size of a single entry in Section header in bytes
for EV_CURRENT, if non-zero, it should be x28 for 32-bit objects, x40 for 64-bit objects
x30x3A i16 e_shnum, number of entries in Section header
If greater or equal than xFF00, 0 is stored here, and the sh_size field in the first entry of the Section header contains the value
x32x3C i16 e_shstrndx, section header index for section name string table
If greater or equal than xFF00, 0 is stored here, and the sh_link field in the first entry of the Section header

Program header

A single entry has the following form. Note that the offset between entries is e_phentsize as found in the ELF header. Its format is slightly different between 32-bit and 64-bit versions.

x00 i32 p_type
x00000000 PT_NULL, unused
x00000001 PT_LOAD, loadable segment
x00000002 PT_DYNAMIC, dynamic linking information
x00000003 PT_INTERP, null-terminated path name for interpreter to invoke
must have at most 1 entry, only defined for executables
x00000004 PT_NOTE, auxiliary information
x00000005 PT_SHLIB, reserved
x00000006 PT_PHDR, program header, must have at most 1 entry
only occurs if program header is part of memory image, must precede all other segment entries
x00000007 PT_TLS, thread-local storage template
x60000000 PT_LOOS, first operating system specific type
x6FFFFFFF PT_HIOS, last operating system specific type
x70000000 PT_LOPROC, first processor specific type
x7FFFFFFF PT_HIPROC, last processor specific type
x80000000 PT_LOUSER, first application specific type
x8FFFFFFF PT_HIUSER, last application specific type
x60000001 PT_OS, IBM OS/2 extension, identifies the target operating system[3]
x60000002 PT_RES, IBM OS/2 extension, read-only resource data[3]
x6474E550 PT_SUNW_EH_FRAME, PT_GNU_EH_FRAME, Solaris extension, frame unwind information[2]
x6474E551 PT_GNU_STACK, GNU extension, stack flags[2]
x6474E552 PT_GNU_RELRO, GNU extension, read-only after relocation[2]
x6474E553 PT_GNU_PROPERTY, GNU extension, GNU property[2]
x6474E554 PT_GNU_SFRAME, GNU extension, stack trace information[2]
x6474E555 PT_GNU_MBIND_LO, GNU extension[2]
x6474F554 PT_GNU_MBIND_HI, GNU extension[2]
x65A3DBE5 PT_OPENBSD_MUTABLE, OpenBSD extension, mutable .bss[2]
x65A3DBE6 PT_OPENBSD_RANDOMIZE, OpenBSD extension, fill with random data[2]
x65A3DBE7 PT_OPENBSD_WXNEEDED, OpenBSD extension, program does W^X violation[2]
x65A3DBE8 PT_OPENBSD_NOBTCFI, OpenBSD extension, no branch target CFI[2]
x65A41BE6 PT_OPENBSD_BOOTDATA, OpenBSD extension, section for boot arguments[2]
   x04    i32 p_flags
Bit 0 PF_X, executable
Bit 1 PF_W, writable
Bit 2 PF_R, readable
Bits 20:27 PF_MASKOS, operating system specific
Bits 28:31 PF_MASKPROC, processor specific
Bit 24 PF_S, IBM OS/2 extension, shared segment[3]
Bit 25 PF_K, IBM OS/2 extension, mapped to kernel address space
kernel extension, executes at supervisor privilege, implicitly memory resident
only valid for DLLs, must be specified for all PT_LOAD segments if used[3]
Bit 26 PF_M, IBM OS/2 extension, memory resident
must be specified for all PT_LOAD segments if used[3]
x04x08 i32i64 p_offset, offset to data from start of file
x08x10 i32i64 p_vaddr, virtual address to load at
x0Cx18 i32i64 p_paddr, physical address to load at, unused for System V executables and shared objects
x10x20 i32i64 p_filesz, number of bytes in the file image
x14x28 i32i64 p_memsz, number of bytes in the memory image
x18    i32    p_flags, see above
x1Cx30 i32i64 p_align, alignment constraint, 0 or 1 means no constraint, otherwise must be a power of 2

Section header

A single entry has the following form. Note that the offset between entries is e_shentsize as found in the ELF header. Its format is slightly different between 32-bit and 64-bit versions.

x00 i32 sh_name, index into the section header table (e_shstrndx) for the name, or 0
x04 i32 sh_type
x00000000 SHT_NULL, inactive entry, entry 0 must be of this type
x00000001 SHT_PROGBITS, program data (instructions, initialized data, etc.)
x00000002 SHT_SYMTAB, symbol table, expected to have at most 1, used for linking
x00000003 SHT_STRTAB, string table
x00000004 SHT_RELA, relocation table with explicit addends
x00000005 SHT_HASH, symbol hash table, expected to have at most 1
x00000006 SHT_DYNAMIC, information for dynamic linking, expected to have at most 1
x00000007 SHT_NOTE, information to mark the file
x00000008 SHT_NOBITS, program data, not present in file (uninitialized data)
x00000009 SHT_REL, relocation table without explicit addends
x0000000A SHT_SHLIB, reserved
x0000000B SHT_DYNSYM, symbol table, expected to have at most 1, used for dynamic linking
x0000000E SHT_INIT_ARRAY
x0000000F SHT_FINI_ARRAY
x00000010 SHT_PREINIT_ARRAY
x00000011 SHT_GROUP, defines a group of sections, only allowed in relocatable objects, entry must precede contained sections
x00000012 SHT_SYMTAB_SHNDX
x60000000 SHT_LOOS, first operating system specific type
x6FFFFFFF SHT_HIOS, last operating system specific type
x70000000 SHT_LOPROC, first processor specific type
x7FFFFFFF SHT_HIPROC, last processor specific type
x80000000 SHT_LOUSER, first application specific type
x8FFFFFFF SHT_HIUSER, last application specific type
x60000001 SHT_OS, IBM OS/2 extension, identifies the target operating system[3]
x60000002 SHT_IMPORTS, IBM OS/2 extension, external symbol references[3]
x60000003 SHT_EXPORTS, IBM OS/2 extension, exported symbols[3]
x60000004 SHT_RES, IBM OS/2 extension, read-only resource data[3]
x6FFF4700 SHT_GNU_INCREMENTAL_INPUTS, GNU extension, incremental build data[2]
x6FFFFFF5 SHT_GNU_ATTRIBUTES, GNU extension, object attributes[2]
x6FFFFFF6 SHT_GNU_HASH, GNU extension, GNU style symbol hash table[2]
x6FFFFFF7 SHT_GNU_LIBLIST, GNU extension, list of prelinked dependencies[2]
x6FFFFFFD SHT_SUNW_verdef, SHT_GNU_verdef, Solaris extension, versions defined by file[2]
x6FFFFFFE SHT_SUNW_verneed, SHT_GNU_verneed, Solaris extension, versions needed by file[2]
x6FFFFFFF SHT_SUNW_versym, SHT_GNU_versym, Solaris extension, symbol versions[2]
x08 i32i64 sh_flags, section properties
Bit 0 SHF_WRITE, writable during execution
Bit 1 SHF_ALLOC, resides in memory during execution
Bit 2 SHF_EXECINSTR, contains machine instructions
Bit 4 SHF_MERGE, data may be merged during linking, sh_entsize contains an element size, unless SHF_STRINGS is set
Bit 5 SHF_STRINGS, contains null-terminated strings, sh_entsize gives the character size
Bit 6 SHF_INFO_LINK, sh_info contains a section header index
Bit 7 SHF_LINK_ORDER, must preserve order with section index sh_link when linking
Bit 8 SHF_OS_NONCONFORMING, requires OS-specific processing
Bit 9 SHF_GROUP, member of a section group
Bit 10 SHF_TLS, holds thread-local storage, each thread will have a separate copy during execution
Bit 11 SHF_COMPRESSED, data is compressed, must not be used for SHT_NOBITS or together with SHF_ALLOC
Bits 20:27 SHF_MASKOS, mask for operating system semantics
Bits 24:27 Value for SHF_MASKOS before 1999-10-04[2]
Bits 28:31 SHF_MASKPROC, mask for processor semantics
Bit 24 SHF_BEGIN, IBM OS/2 extension, signals that this must be placed before other like-named sections[3]
Bit 25 SHF_END, IBM OS/2 extension, signals that this must be placed after other like-named sections[3]
Bit 21 SHF_GNU_RETAIN, GNU extension, section should not be garbage collected by linker[2]
Bit 24 SHF_GNU_MBIND, GNU extension[2]
Bit 31 SHF_EXCLUDE, exclude from linking into non-relocatable objects[2]
x0Cx10 i32i64 sh_addr, address at which section should appear, or 0
x10x18 i32i64 sh_offset, offset to section data from start of file; a section of type SHT_NOBITS will contain a conceptual offset
x14x20 i32i64 sh_size, size of section in bytes; unless sh_type is SHT_NOBITS, this many bytes appear in the file
x18x28 i32 sh_link
x1Cx2C i32 sh_info
x20x30 i32i64 sh_addralign, alignment constraint, 0 or 1 mean no alignment, otherwise it must be a power of 2
x24x38 i32i64 sh_entsize, for tables, the size of a single entry

Sections are indexed from 0, but the first section entry should be an SHT_NULL type with all fields, except for sh_size which contains the number of sections if greater or equal to xFF00, and sh_link which contains the index of of the section header string table if greater or equal to xFF00.

Some section values are reserved and have special semantics:

x0000 SHN_UNDEF, section index is missing or irrelevant
xFF00 SHN_LORESERVE, first special semantics
xFF00 SHN_LOPROC, first processor specific entry
xFF1F SHN_HIPROC, last processor specific entry
xFF20 SHN_LOOS, first operating system specific entry
xFF3F SHN_HIOS, last operating system specific entry
xFFF1 SHN_ABS, absolute reference, no associated section
xFFF2 SHN_COMMON, unallocated variables (FORTRAN COMMON, C external uninitialized)
xFFFF SHN_XINDEX, signals that actual value greater or equal than xFF00
xFFFF SHN_HIRESERVE, last special semantics

The field entries sh_link and sh_info have semantics that depend on the section type:

name sh_link sh_info
SHT_DYNAMIC string table 0
SHT_HASH symbol table 0
SHT_REL
SHT_RELA
symbol table section to relocate
SHT_SYMTAB
SHT_DYNSYM
string table index after last local symbol (STB_LOCAL)
SHT_GROUP symbol table symbol table index for group signature
SHT_SYMTAB_SHNDX symbol table 0
SHT_IMPORTS string table 0
SHT_EXPORTS symbol table string table

Some sections have special semantics.

name type attributes
.bss SHT_NOBITS SHF_ALLOC+SHF_WRITE
.data SHT_PROGBITS SHF_ALLOC+SHF_WRITE
.debug SHT_PROGBITS 0
.dynamic SHT_DYNAMIC SHF_ALLOC, depending on processor, also SHF_WRITE
.dynstr SHT_STRTAB SHF_ALLOC
.dynsym SHT_DYNSYM SHF_ALLOC
.got SHT_PROGBITS ???
.hash SHT_HASH SHF_ALLOC
.interp SHT_PROGBITS optionally SHF_ALLOC
.line SHT_PROGBITS 0
.plt SHT_PROGBITS ???
.relname SHT_REL optionally SHF_ALLOC
.rodata SHT_PROGBITS SHF_ALLOC
.shstrtab SHT_STRTAB 0
.strtab SHT_STRTAB optionally SHF_ALLOC
.symtab SHT_SYMTAB optionally SHF_ALLOC
.tbss SHT_NOBITS SHF_ALLOC+SHF_WRITE+SHF_TLS
.tdata SHT_PROGBITS SHF_ALLOC+SHF_WRITE+SHF_TLS
.text SHT_PROGBITS SHF_ALLOC+SHF_EXECINSTR
.osinfo SHT_OS 0
.imports SHT_IMPORTS SHF_ALLOC
.exports SHT_EXPORTS SHF_ALLOC
.res SHT_RES 0

Symbol table

A symbol table is a section that contains an array of the following entries.

x00 i32 st_name
x04    i32    st_value, semantics depend on type
x08    i32    st_size, size of symbol or 0 if unknown
x0Cx04 i8 st_info
Bits 0:3 st_type
x0 STT_NOTYPE, unspecified
x1 STT_OBJECT, symbol is a data object (variable, array)
x2 STT_FUNC, symbol is a function
x3 STT_SECTION, symbol is a section, typically STB_LOCAL
x4 STT_FILE, symbol name is the source file name
if present, it conventionally precedes all other symbols, has section SHN_ABS and type SHB_LOCAL
x5 STT_COMMON, symbol for an uninitialized common block
x6 STT_TLS, symbol for a thread-local storage entry, contains the offset, not the address of the symbol
xA STT_LOOS, first operating system specific symbol type
xC STT_HIOS, last operating system specific symbol type
xD STT_LOPROC, first processor specific symbol type
xF STT_HIPROC, last processor specific symbol type
xB STT_IMPORT, IBM OS/2 extension: a function symbol that must be imported, st_value contains offset of import table entry[3]
Bits 4:7 st_bind
x0 STB_LOCAL, not visible outside object file
x1 STB_GLOBAL, visible to all files, undefined symbols will match a global symbol
x2 STB_WEAK, global symbol of lower precedence when matching
xA STB_LOOS, first operating system specific binding type
xC STB_HIOS, last operating system specific binding type
xD STB_LOPROC, first processor specific binding type
xF STB_HIPROC, last processor specific binding type
xC STB_ENTRY, IBM OS/2 extension: entry point
only for relocatable objects, must have at most 1[3]
x0Dx05 i8 st_other
Bits 0:1 st_visibility
x00 STV_DEFAULT
x01 STV_INTERNAL
x02 STV_HIDDEN
x03 STV_PROTECTED
x0Ex06 i16 st_shndx, section relative to which this symbol is defined
SHN_ABS st_value is an absolute value
SHN_COMMON st_value contains an alignment constraint
SHN_UNDEF the symbol is undefined, must be defined in another object
SHN_XINDEX actual value is stored in a section of type SHT_SYMTAB_SHNDX
   x08    i64 st_value, semantics depend on type
   x10    i64 st_size, size of symbol or 0 if unknown

Symbols are indexed from 0, but the first symbol entry should contain all zeroes and st_shndx should be SHN_UNDEF.

OS/2 resource file format

A resource file begins with a Res32_File header.[3]

x00 c[0x10] rf_ident
x00 c[4] RF_MAG = '\x02RES', signature
x04 i8 RF_CLASS, file class
0 RESCLASSNONE, invalid
1 RESCLASS32, offsets and addresses are encoded as 32-bit fields
2 RESCLASS64, reserved for 64-bit architectures
x05 i8 RF_DATA, data encoding
0 RESDATANONE, invalid
1 RESDATA2LSB, 2's complement, least significant byte first (little endian)
2 RESDATA2MSB, 2's complement, most significant byte first (big endian)
x06 i8 RF_VERSION, file version
0 RV_NONE, invalid
1 RV_CURRENT, current version
x07 c[0xB] RF_PAD, padding, filled with zeros
x10 i32 rf_rfsize, size of header
x14 i32 rf_rcnum, number of resource collections
x18 i32 rf_rcoff, offset of resource collection array, from the start of the resource file
expected value: x1C

Resource collection array entry

A resource collection array entry is a Res32_Col structure.[3]

x00 i32 rc_collection, offset to the resource collection relative to the resource file, must be word aligned
x04 i32 rc_size, total size of the resource collection in bytes

Resource collection

A resource collection starts with the following header Res32_Hdr.[3]

x00 i16 rh_version, version of resource collection, should be 1
x02 i16 rh_flags, currently no flags are defined
x04 i32 rh_name, index into the resource string table
x08 i32 rh_rioff, offset to resource item array
x0C i32 rh_rientsize, size of a resource item array entry, should be x14
x10 i32 rh_rinum, number of resources
x14 i32 rh_rhsize, header's size in bytes, should be x20
x18 i32 rh_strtab, offset to resource string table, relative to start of resource collection
x1C i32 rh_locale, offset to the locale information, relative to the start of the resource collection
if present, it should follow the header

The resource collection locale information, if present, is a Res32_Locale structure.[3]

x20 c16[2] rl_country, two UCS-2 characters
x24 c16[2] rl_language, two UCS-2 characters

An array of Res32_Item entries follow.[3]

x00 i32 ri_type
x04 i32 ri_ordinal, each resource has a unique ordinal within its resource type
x08 i32 ri_name, offset to the resource string table
x0C i32 ri_data, data offset, relative to the start of the resource collection
x10 i32 ri_size, size of resource data

OS/2 operating system information (.osinfo)

The system information is stored in a structure named Elf32_Os.[3]

x00 i32 os_type
x00000000 EOS_NONE
x00000001 EOS_PN, IBM Microkernel personality neutral
x00000002 EOS_SVR4, UNIX System V Release 4
x00000003 EOS_AIX, IBM AIX
x00000004 EOS_OS2, IBM OS/2, 32-bit environment
x04 i32 os_size, size of operating system specific information directly following this entry
for OS/2 it should be x10

For OS/2, the following entries should be part of the structure Elf32_OS2Info.[3]

x08 i8 os2_sessiontype
x00 OS2_SES_NONE, only valid for DLLs
x01 OS2_SES_FS, full screen session
x02 OS2_SES_PM, presentation manager session
x03 OS2_SES_VIO, Windows character mode session
x09 i8 os2_sessionflags, session flags, none currently defined
x0A c[0xE] os2_reserved, reserved

OS/2 import table (.imports)

Each import table entry has the following structure.[3]

x00 i32 imp_ordinal, ordinal number of export, or -1 if referenced by name
x04 i32 imp_name, string table index for name, or 0 if referenced by ordinal
x08 i32 imp_info
Bits 0:23 imp_dll, interpretation depends on the type
Bits 24:31 imp_type
x00 IMP_IGNORED, ignored
x01 IMP_STR_IDX, value is string table index of name of load module
x02 IMP_DT_IDX, value is a 1-based reference to a DT_NEEDED entry in the dynamic segment
x0C i32 imp_reserved, reserved

OS/2 export table (.exports)

Each export table entry has the following structure.[3]

x00 i32 exp_ordinal, ordinal number of export, or -1 if exported by name
x04 i32 exp_symbol, symbol table index
x08 i32 exp_name, string table index for name, or 0 if exported by ordinal
x0C i32 exp_reserved, reserved

BeOS Developer Release 4 resources

This section requires documentation, see [4].

Segment contents

A PT_INTERP segment will contain an .interp section.

A PT_PHDR segment will point to the program header section.

A text segment will contain .text, .rodata, .hash, .dynsym, .dynstr, .plt, .rel.got sections.

A data segment will contain .data, .dynamic, .got, .bss sections.

A PT_DYNAMIC segment will point to a .dynamic section.

A PT_OS segment will contain a .osinfo section. It should precede all other segments.[3]

A PT_RES segment will contain a .res section. It should follow all other segments.[3]

Dynamic linking

TODO

Further work

This format requires documentation.

References


flat binary CP/M

File extensions
.com, but .r for Human68k
Magic code
Architecture
usually Intel 8080, Zilog Z80 (CP/M-80), Intel 8086 (MS-DOS) or Motorola 68000 (Human68k), but MOS 6502 (OUP/M, DOS/65), PDP-11 (DX-DOS) are also possible
Operating systems
  • 1974: CP/M-80 and compatibles
  • 1981-08-12: MS-DOS 1.0 and compatibles
  • 1983: OUP/M
  • 1987-03-28: Human68k
  • 1989: DOS/65
  • 1995: DX-DOS
Influences
usually Intel 8080, Zilog Z80 (CP/M-80), Intel 8086 (MS-DOS) or Motorola 68000 (Human68k), but MOS 6502 (OUP/M, DOS/65), PDP-11 (DX-DOS) are also possible

Contents

  1. Contents
  2. Program Information
  3. References

Program Information

For MS-DOS .com files, the PIFED[1] utility from Concurrent DOS 386 embeds a special structure to encode program information data. It immediately follows the last data byte in the file. It can be recognized by its special signature. For the layout, refer to the Program Information section for the MZ format.

References

  • [1] Concurrent DOS 386 PIFED.EXE

FLEX executable (.CMD)

File extensions
.cmd
Magic code
x02
Architecture
Motorola 6800, Motorola 6809
Operating systems
1976: FLEX
Influences
Motorola 6800, Motorola 6809

Contents

  1. Contents
  2. Overall layout
  3. Binary record
  4. Transfer address record
  5. Terminating record
  6. References

Overall layout

A binary file is composed of several binary records.

Binary record

Load a series of bytes into a specified address in memory.

x00 i8 x02
x01 i16be Load address
x03 i8 Number of following bytes in record[2] (Note: [1] claims this includes first 4 bytes, disk image does not comply with this)
x04 c[*] Binary data

Transfer address record

Specifies the entry point of a command.

x00 i8 x16[2] (Note: [1] is claims this is an ACK but actually it's a SYN)
x01 i16be Transfer address

Only the last transfer address is used

Terminating record

Terminates the list of records.[2]

x00 i8 x00

References


Page relocatable

File extensions
  • .prl (Page Relocatable) for programs (replaced by .cmd in MP/M-86)
  • .spr (System PRL) for system modules (replaced by .obj in CP/M-86 Plus, .mpm in MP/M-86, .con in Concurrent CP/M-86)
  • .rsp for resident system processes
  • .brs for banked RSP (MP/M 2)
  • .ovl for overlays (replaced by .ovr in CP/M-86)
  • .rsx for resident system extensions
  • .rsm for resident system modules (RSXs backported to CP/M 2)
  • .fid for Amstrad CP/M field installable device drivers
Magic code
x00
Architecture
Intel 8080 and Zilog Z80
Operating systems
  • 1979: MP/M-80
  • 1983: CP/M-80 Plus
Influences
Intel 8080 and Zilog Z80

Contents

  1. Contents
  2. Overall layout
  3. Executable Header
  4. Relocation information
  5. References

Overall layout

Executable Header
Program image
Relocation information

Executable Header

x00 i8 =0
x01 i16le Size of program image in bytes
x03 i8 =0
x04 i16le Size of bss, data to clear out
x06 i8 =0
x07 i16le Load address, only used for .ovl, 0 for other files.
.prl and .rsp files are assembled to be loaded at x0100, .spr files at x0000.
x09 i8 =0
x0A i16le Base address of code group, only used with LINK-80
x0C c[0xF4] Reserved, must be 0

Relocation information

Except for .ovl files, a bitmap follows with one bit for each byte in the program image, for a total of (size + 7) / 8 bytes. Each bit specifies whether the corresponding byte in the image encodes the most significant byte of an address, which the system can use to relocate the image to another 256 byte page boundary.

The first byte of the image corresponds to the most significant bit of the first byte of the relocations.

References


CP/M-80 Plus executable (.COM)

File extensions
.com
Magic code
xC9
Architecture
Intel 8080 and Zilog Z80
Operating systems
1983: CP/M-80 Plus
Influences
Intel 8080 and Zilog Z80

Contents

  1. Contents
  2. Overall layout
  3. Executable Header
    1. RSX record
  4. References

Overall layout

Executable Header
Program image
RSX 1 image
RSX 2 image
...

Executable Header

When this header is present, the entire file is loaded at address x0100. After the pre-initialization code is executed, the header is removed and the image is relocated to address x0100 from the previous x0200.

x00 i8 xC9, corresponds to an Intel 8080/Zilog Z80 RET instruction that would immediately return to the system
x01 i16le Size of program image in bytes, without this header or the RSX images
x03 c[10] Pre-initialization code, executed before relocating the image, must return with RET. Intended for SCBs.
x0D i8 Loader flag: normally if no RSXs are present, the loader does not stay active after loading
0xFF No RSXs are attached, but Loader must remain active
x0E i8 Reserved
x0F i8 Number of RSXs
x10 c[0xF0] Up to 15 RSX records

RSX record

x00 i16le Offset of RSX image from file base
x02 i16le Size of RSX initialized data
x04 i8 Non-banked flag
0xFF RSX must only be loaded for non-banked systems
x05 i8 Reserved
x06 c[8] Original RSX filename
x0E c[2] Reserved

The actual RSX image comes without the PRL header, but with relocations present.

References


CP/M-86 executable (.CMD)

File extensions
  • .cmd for applications
  • .sys for drivers
  • .mpm (MP/M-86) or .con (Concurrent CP/M-86, Concurrent DOS, Multiuser DOS) for system modules
  • .rsp for resident system processes
  • .ovr for overlays
  • .rsx for resident system extensions
  • .186 for FlexOS 186 applications
  • .286 for FlexOS 286 applications
  • .srl for FlexOS 286 shared run-time libraries
Magic code
Architecture
Intel 8086/80286
Operating systems
  • 1981-09-25: MP/M-86 2.0
  • 1981-11: CP/M-86 1.0
Influences
Intel 8086/80286

Contents

  1. Contents
  2. Overall layout
  3. Executable Header
    1. SRTL identifier
  4. Shared run-time library group
  5. FASTLOAD group
  6. Relocation data
  7. RSX index
  8. CP/M-86 runtime layout
  9. References

Overall layout

The CMD file format has evolved through several versions. The original version only contained the header and group data, with relocations and RSXs added later. Later FlexOS added shared run-time library (SRTL) support, and then a fast load section.

Executable Header
Shared run-time library group (FlexOS only)
FASTLOAD group (FlexOS only)
Group 1 image
Group 2 image
...
Relocation data
RSX index (CP/M Plus and DOSPlus only)

Executable Header

x00 c[9 × 8] Up to 8 descriptors
x00 i8 Group type (only the low 4 bits are actually used[1])
0x00 End of descriptors (not a descriptor)
0x01 Code, may be written to (loaded into CS, also DS and ES if no data/extra groups provided)
0x02 Data (loaded into DS, also ES if no extra group provided)
0x03 Extra (loaded into ES)
0x04 Stack (not loaded into SS)
0x05 Auxiliary 1 (not FlexOS)
0x06 Auxiliary 2 (not FlexOS)
0x07 Auxiliary 3 (not FlexOS)
0x08 Auxiliary 4 (not FlexOS)
Relocations[4] (FlexOS, group is optional)
0x09 Pure code, can be shared between processes (loaded into CS)
0x0A-0x0E Reserved
0x0F Escape code for additional types (not FlexOS)
0xFE FASTLOAD group descriptor (must appear at x51)
0xFF Shared run-time library group descriptor (must appear at x48)[4]
x01 i16le Length of group in 16 byte paragraphs, as stored in file
x03 i16le Base address of group in 16 byte paragraphs, 0 if relocatable (normally non-zero only in executable files)
x05 i16le Minimum size in memory in 16 byte paragraphs (corresponds to data and bss)
x07 i16le Maximum size in memory in 16 byte paragraphs (includes heap)
x48 c[9] (FlexOS only): Shared run-time library group descriptor (GDSRTL)
0xFF Shared run-time library group present, program includes shared libraries[4] (the group sizes seem to be filled[6])
x51 c[9] (FlexOS only): File is in fast load format
0xFE FASTLOAD group[6]
x5A c[6] Reserved
x60 c[0x10] (FlexOS only): SRTL identifier, present for shared run-time libraries[4]
x70 c[0x0B] Reserved
x7B i16le Offset to RSX index in 128 byte records[3]
x7D i16le Offset to Relocation data in 128 byte records
x7F i8 Bit field
Bit 3 Must be suspended when running in background, used for applications with direct video access[2]
Bit 4 This is an RSX (system extension) file, not a CMD (command) file[3]
Bits 5:6 8087 usage
0 Does not use 8087
1 Requires 8087
2 Optional 8087 support
Bit 7 Requires relocation

SRTL identifier

This record can be found in the header as well as in the Shared runtime library group.[4]

x00 c[8] SRTL (shared run-time library) name; the full filename has extension '.SRL'
x08 i16le Major version
x0A i16le Minor version
x0C i32le Flags (reserved)

Shared run-time library group

This group stores the shared run-time libraries required for execution.[4]

x00 i16le Number of included shared run-time libraries
x02 c[*] Sequence of SRTL (shared run-time libraries) identifiers and relocation count entries

For non-FASTLOAD files, each entry has the following format:

x00 c[8] SRTL identifier
x10 i16le Number of relocations for this library

For FASTLOAD files, the entries are extended:

x00 c[8] SRTL identifier
x10 i16le Number of relocations for this library (0)[5]
x12 i16le Index of first selector referencing this library[5]
x14 i16le =1 (unknown)[5]

FASTLOAD group

The FASTLOAD group is typically x650 bytes, it starts with an 8 byte header:[6]

x00 i16le Maximum allowed LDT entries[5], typically xC8 or 2 after the first free index after LDT
x02 i16le First free index after LDT[5]
x04 i16le Index base[5], typically x0C
x06 i16le First used index[5], typically x00 or x0C

Then a descriptor table follows, similar to a 286 LDT structure.

x00 i16le Offset to last byte in 286 segment (limit)
x02 i24le Base address of first byte in 286 segment
x05 i8 Segment group type of 286 segment[5]
SRTL fixups also reference the code group, with 0 for the limit
x06 i16le 0

Relocation data

The relocation data appears on a 128 byte record boundary, and it is a collection of 4 byte structures.[3]

x00 i8 0 if end of relocations, otherwise a bitfield
Bits 0:3 Destination group type (1 for pure code)
Bits 4:7 Source group type (1 for pure code)
x01 i16le 16 byte paragraph offset from source group
x03 i8 Byte offset from paragraph within source group

If there are any shared libraries, they can also have relocations. Each group of shared library relocations is separated by a 4 byte sequence of 0 that terminates the previous list. The format for these relocations is almost identical to those of internal relocations.[6]

x00 i8 0 if end of relocations, otherwise a bitfield
Bits 0:3 Must be 0
Bits 4:7 Source group type (1 for pure code)
x01 i16le 16 byte paragraph offset from source group
x03 i8 Byte offset from paragraph within source group

RSX index

The RSX index may contain up to 7 RSX record entries plus a terminator.[3]

x00 i16le Offset of RSX in 128 byte records
0x0000 Must be loaded from disk
0xFFFF End of list (not an entry)
x02 c[8] Name of the RSX; for dynamically loaded RSXs, append '.RSX' to the file name
x0A c[6] Reserved

CP/M-86 runtime layout

Documentation[1] describe 3 modes of operation: 8080 model, small model and compact model. However the real difference is between the 8080 model and the other models. The 8080 model is selected when there is no data group. In CP/M-86, only a single code group is permitted.[6] Later versions allow other groups as well.

When starting the program, the first 256 bytes of one of the groups is overwritten by a structure called the zero page. For an 8080 model program, it is the first 256 bytes of the code group, otherwise the data group.

Then the segment registers are initialized: the CS to the start segment of the code group, the DS to the start of the data group if available, otherwise CS, the ES to the start of the extra group if available, otherwise DS. The IP is loaded with x0100 for 8080 model programs and x0000 otherwise. Notably, the SS:SP registers are not loaded with the stack segment, the rationale being that the actual length of the stack group cannot be known at compile time, and it might exceed 64 KiB. Instead it points to a small memory range allocated by the system.

Register 8080 model Small/compact model
CS code group code group
DS CS data group or CS
ES extra group or DS extra group or DS
SS system stack system stack
SP system stack system stack
IP x0100 x0000

References


CP/M-68K executable (.68K)

File extensions
  • .68k CP/M-68K and Concurrent DOS 68K executables (Concurrent DOS also uses COFF)
  • .prg for GEMDOS text applications, TOS graphical applications
  • .app for GEMDOS and Atari TOS graphical applications
  • .acc for GEMDOS and Atari TOS graphical accessories
  • .tos for Atari TOS text applications
  • .ttp for Atari TOS text applications that take parameters
  • .gtp for Atari TOS (since version 2.0) graphical applications that take parameters
  • .slb for shared libraries for MagiC (Atari TOS extension)
  • .z for Human68k
Magic code
  • x60x1A for contiguous executables (all of them)
  • x60x1B for non-contiguous executables (CP/M-68K only)
  • x60x1C for contiguous executables with crunched relocations (Concurrent DOS 68K only)
Architecture
Motorola 68000
Operating systems
  • 1982: CP/M-68K
  • 1985: GEMDOS, GEM, Concurrent DOS 68K
  • 1985-11-20: Atari TOS
  • 1987-03-28: Human68k
Influences
Motorola 68000

Contents

  1. Contents
  2. Overall layout
  3. Header
    1. CP/M-68K and Concurrent DOS 68K header for contiguous executables
    2. CP/M-68K non-contiguous executables
    3. Header for early versions of GEMDOS
    4. Atari TOS header
    5. Human68k .Z header
  4. Symbol Table
  5. Relocation Table
    1. CP/M-68K relocations
    2. Crunched relocations
    3. GEMDOS/Atari TOS relocations
    4. Human68k relocations
  6. References

Overall layout

Multiple systems support multiple versions of the file format. Executables can be contiguous or non-contiguous (the latter only supported on CP/M-68K). The header fields have some variations between the various operating systems. The format of the relocations between CP/M-68K, GEMDOS/Atari TOS, and crunched relocations. The symbol table has a standardized format for CP/M-68K, but other linkers can use different formats.

Header
Text segment image
Data segment image
Symbol Table
Relocation Table

Header

There are multiple versions of the header. They are very similar, but for ease of navigation, we will separate them according to versions. The following is the general layout:

x00 i16be Magic number
0x601A Contiguous executable
0x601B Non-contiguous executable[1]
0x601C Contiguous executable with crunched relocations[2]
x02 i32be Size of text segment
x06 i32be Size of data segment
x0A i32be Size of bss segment
x0E i32be Size of symbol table
x12 i32be Size of stack[2]
x16 i32be Address of text segment[1] or program flags[6]
x1A i16be Relocations suppressed
x1C i32be Address of data segment[1] (optional)
x20 i32be Address of bss segment[1] (optional)

CP/M-68K and Concurrent DOS 68K header for contiguous executables

Format used by CP/M-68K[1] and Concurrent DOS 68K[2] for contiguous executables:

x00 i16be Magic number
0x601A Contiguous executable
0x601C Contiguous executable with crunched relocations (Concurrent DOS 68K only)[2]
x02 i32be Size of text segment
x06 i32be Size of data segment
x0A i32be Size of bss segment (image not included in file)
x0E i32be Size of symbol table
x12 i32be CP/M-68K: Reserved, must be 0
Concurrent 68K: Size of stack[2]
x16 i32be Address of text segment, start of execution
x1A i16be
0x0000 Relocations exist
non-0 No relocations present
x1C c[*] Start of image

CP/M-68K non-contiguous executables

Format used by CP/M-68K[1] for non-contiguous executables:

x00 i16be x601B (Magic number for Non-contiguous executable)
x02 i32be Size of text segment
x06 i32be Size of data segment
x0A i32be Size of bss segment (image not included in file)
x0E i32be Size of symbol table
x12 i32be Reserved, must be 0
x16 i32be Address of text segment, start of execution
x1A i16be
0x0000 Relocations exist
non-0 No relocations present
x1C i32be Address of data segment
x20 i32be Address of bss segment
x24 c[*] Start of image

Header for early versions of GEMDOS

Format used by early versions of GEMDOS[4]:

x00 i16be x601A (Magic number for Contiguous executable)
x02 i32be Size of text segment
x06 i32be Size of data segment
x0A i32be Size of bss segment (image not included in file)
x0E i32be Size of symbol table
x12 i32be Reserved, must be 0
x16 i32be Reserved, must be 0
x1A i32be Reserved, must be 0
x1E c[*] Start of image

Atari TOS header

Format used by Atari TOS:

x00 i16be x601A (Magic number for Contiguous executable)
x02 i32be Size of text segment
x06 i32be Size of data segment
x0A i32be Size of bss segment (image not included in file)
x0E i32be Size of symbol table
x12 i32be Reserved, must be 0
x16 i32be Program flags
Bit 0 Only clear bss, not heap
Bit 1 May load program into alternative RAM
Bit 2 May use alternative RAM for Malloc calls
Bit 3 Only requires basepage, text, data, bss segments and symbol tables, used for shared libraries[7]
Bit 4-5
0 All memory is private
1 All memory is public
2 Supervisor mode can access memory
3 All memory is read only
Bit 6-11 Reserved, must be 0
Bit 12 Text segment is shared, no absolute address refers to DATA and BSS (unsure if bit 11 or bit 12)
Bit 13-27 Reserved, must be 0
Bit 28-31 Maximum amount of memory to allocate in alternate RAM, in 128KiB
x1A i16be
0x0000 Relocations exist
non-0 No relocations present
x1C c[*] Start of image

Human68k .Z header

Format used by Human68k for .Z executables:

x00 i16be x601A (Magic number for Contiguous executable)
x02 i32be Size of text segment
x06 i32be Size of data segment
x0A i32be Size of bss segment, including common and stack (image not included in file)
x0E i32be Reserved, must be 0
x12 i32be Reserved, must be 0
x16 i32be Load address, start of execution
x1A i16be xFFFF (Magic number)
x1C c[*] Start of image

Symbol Table

CP/M-68K has the following format for each symbol.

x00 c[8] Symbol name, null padded
x08 i16be Type
0x0100 Bss based relocatable
0x0200 Text based relocatable
0x0400 Data based relocatable
0x0800 External reference
0x1000 Equated register
0x2000 Global
0x4000 Equated
0x8000 Defined
x0A i32be Value

Relocation Table

CP/M-68K relocations

For CP/M-68K relocations are stored as a sequence of 16-bit words, one for each 16-bit word in the text and data sections. The least significant 3 bits of the word determine if the word requires a relocation.

x00 i16be Relocation information
Bit 0-3 Relocation type
0 Absolute reference, no relocation required
1 Reference relative to the base address of the data segment
2 Reference relative to the base address of the text segment
3 Reference relative to the base address of the bss segment
4 Undefined symbol, bits 4-15 index the symbol table
5 The upper word of a 32-bit longword.
The following word contains the relocation type, and the longword to be relocated is at the address of the first word
6 PC-relative reference
7 Instruction word, no relocation required
Bit 4-15 References a symbol in the symbol table (optional)

Crunched relocations

Concurrent DOS 68K also recognizes CP/M-68K relocations. It also supports crunched relocations. The type of relocations is determined by the magic word, if it is x601C, it uses crunched relocations, otherwise CP/M-68K relocations. Relocations are represented as a sequence of offsets between 16-bit words and 32-bit longwords that need to be relocated. Each byte has the following format.[3]

x00 i8
Bit 0-6
00 End of relocations
01-7C Advance with the quantity, relocate next quantity
7D Read next u8, advance as much, relocate next quantity
7E Read next u16be, advance as much, relocate next quantity
7F Read next u32be, advance as much, relocate next quantity
Bit 7 Set for 16-bit relocations, cleared for 32-bit relocations

GEMDOS/Atari TOS relocations

GEMDOS relocations are represented as a sequence of offsets between the 32-bit longwords that need to be relocated. The first offset is stored directly in the code.

x00 i32be The first offset to relocate, or 0 if there are none

Every other offset is stored as a command to a pointer that gets moved and updates 32-bit longwords as it advances.

x00 i8
00 End of list
01 Advance 254 bytes, do not relocate
02-FE (even) advance N bytes, relocate the next 32-bit longword
03-FF (odd) undefined

Human68k relocations

Human68k .Z files do not contain relocations.

References


CP/M-8000 executable (.Z8K)

File extensions
.z8k
Magic code
xEEx00, xEEx01, xEEx02, xEEx03, xEEx06, xEEx07, xEEx0A, xEEx0B
Architecture
Zilog Z8000
Operating systems
1982: CP/M-8000
Influences
Zilog Z8000

Contents

  1. Contents
  2. Overall layout
  3. Executable Header
  4. Segment Information Array
  5. Relocation Data
  6. Symbol Table
  7. References

Overall layout

Executable Header
Segment Information Array
Segment 1 image
Segment 2 image
...
Relocation Data
Symbol Table

Executable Header

x00 i16be Magic number, denotes file type
0xEE00 Segmented, nonexecutable
0xEE01 Segmented, executable
0xEE02 Nonsegmented, nonexecutable
0xEE03 Nonsegmented, executable, nonshared Instruction & Data space
0xEE06 Nonsegmented, nonexecutable, shared Instruction & Data space
0xEE07 Nonsegmented, executable, shared Instruction & Data space (apparently CP/M-8000 cannot execute these[2])
0xEE0A Nonsegmented, nonexecutable, split Instruction & Data space
0xEE0B Nonsegmented, executable, split Instruction & Data space
x02 i16be Number of entries in Segment Information Array
x04 i32be Combined size of all segment data in bytes
x08 i32be Size of Relocation Data in bytes
x0C i32be Size of Symbol Table in bytes

Segment Information Array

This table contains one entry for each segment.

x00 i8 Segment's assigned number
For segmented executables, this is the segment number that will be used[2]
xFF lets the linker choose a value
x01 i8 Segment type
01 Bss (no data in file)
02 Stack (no data in file)
03 Code
04 Constant data (rodata)
05 Data
06 Mixed code/data, not protectable (might write data in it)
07 Mixed code/data, protectable (may be put in ROM)
x02 i16be Length of segment

Note: [1] (likely erroneously) claims that there is another byte following this record indicating the number of segment entries in the table.[2]

Relocation Data

x00 i8 Segment number
x01 i8 Relocation type
0x01 OFF: A 16-bit offset value to segment
0x02 SSG: A 16-bit short form segment:offset value to segment
0x03 LSG: A 32-bit long form segment:offset value to segment
0x05 XOFF: A 16-bit offset value to external item
0x06 XSSG: A 16-bit short form segment:offset value to external item
0x07 XLSG: A 32-bit long form segment:offset value to external item
x02 i16be Location within segment
x04 i16be Index into symbol table or segment number

Symbol Table

x00 i8 Segment number
x01 i8 Symbol type
0x01 Local (for debugging)
0x02 Undefined, external
0x03 Global definition
0x04 Segment name
x02 i16be Value
x04 c[8] Name, null padded

References


Human68k executable (HU)

File extensions
.x
Magic code
"HU"
Architecture
Motorola 68000
Operating systems
1987-03-28: Human68K, SX-Window
Influences
Motorola 68000

Contents

  1. Contents
  2. Overall layout
  3. Executable Header
  4. Relocation Table
  5. Symbol Table
  6. References

Overall layout

Executable Header
Text segment
Data segment
Relocation Table
Symbol Table

Executable Header

x00 c[2] "HU"
x02 i8 Reserved
x03 i8 Load mode[1]
0 Normal
1 Smallest block
2 High address
x04 i32be Base address[1]
x08 i32be Initial PC (entry)[1]
x0C i32be Size of text segment
x10 i32be Size of data segment
x14 i32be Size of bss segment
x18 i32be Size of relocation table
x1C i32be Size of symbol table
x20 i32be Size of SCD (debug[3]) line number table in bytes[1]
x24 i32be Size of SCD (debug[3]) symbol table in bytes[1]
x28 i32be Size of SCD (debug[3]) string table in bytes[1]
x2C c[0x10] Reserved
x3C i32be Position of bound module list from beginning of file[1]

Relocation Table

Relocations are represented as a sequence of offsets between 16-bit words and 32-bit longwords that need to be relocated. Each 16-bit word has the following format.[1]

x00 i16be Relocation type
0x0001 Read next i32be, then
Even Move to position, relocate i32be
Odd Move to position - 1, relocate i16be
Even Advance by amount of bytes, relocate i32be
Odd Advance by amount-1 of bytes, relocate i16be

Symbol Table

x00 i8 Location
0x00 External[3]
0x02 Local[3]
x01 i8 Section
0x00 Absolute[2]
0x01 Text
0x02 Data
0x03 Bss or common[2] (if external)
0x04 Stack
x02 i32be Value
x04 c[*] Name (zero terminated)[2]

References


MZ executable (named after Mark Zbikowski)

File extensions
  • .exe, sometimes .com for console applications (.com extension supported since MS-DOS 2.0)
  • .ovl for overlays
  • .app for GEM graphics applications
  • .acc for GEM graphics accessories
  • .exm for HP 100LX/200LX System Manager modules
Magic code
  • "MZ" (reportedly also "ZM" in early versions)
  • "DL" for HP 100LX/200LX System Manager modules
Architecture
Intel 8086
Operating systems
1981-08-12: MS-DOS 1.0 and compatibles
Influences
Intel 8086

Contents

  1. Contents
  2. Overall layout
  3. EXE Header
  4. Relocation Table
  5. Program Information
  6. References

Overall layout

EXE Header including Relocation Table and Program Information
Program image

EXE Header

x00 c[2] "MZ" (for Mark Zbikowksi, a lead developer of MS-DOS)
alternatively "ZM"[2]
"DL"[2][3] for System Manager module
x02 i16le Number of bytes in the last 512 byte pages in file, 0 if entire page is used
x04 i16le Size of entire file in 512 byte pages; if value at x02 is non-zero, only that much of the last page is used
x06 i16le Number of relocations
x08 i16le Offset to load image from start of file; size of header in 16 byte paragraphs (including the Relocation Table)
x0A i16le Minimum supplementary 16 byte paragraphs allocated after program image. Corresponds to bss+stack.
If both this and the next field are zero, the program is loaded in the highest possible memory
x0C i16le Maximum supplementary 16 byte paragraphs allocated after program image. This will be used as the heap
x0E i16le Initial SS value (segment of stack), relative to start of program image
x10 i16le Initial SP value (top of stack)
x12 i16le Checksum, the sum of all 16-bit words in the file should be zero. Alternatively, it is the negation of the modular sum of all 16-bit words except this one
x14 i16le Initial IP value (segment of entry)
x16 i16le Initial CS value (entry point), relative to start of program image
x18 i16le Offset of Relocation Table from file start in bytes. Relocation table is typically part of the header.
Some extensions of the file format expect this to be at least x40
x1A i16le Overlay number, 0 for main program
for "DL" executables, starting paragraph of data relative to program image[3]
x1C c[*] Other proprietary fields

Relocation Table

A sequence of address of 16-bit words that have to be incremented by the physical first paragraph of the loaded program image. Note that the offset, paragraph pair of an address is not unique.

x00 i16le Offset of word to relocate
x02 i16le Paragraph of word to relocate

Program Information

The PIFED[5] utility from Concurrent DOS 386 embeds a special structure to encode program information data. It either immediately follows the last relocation in the file, or if there are no relocations (the relocation offset is 0), it starts at offset x1E.

x00 c[4] Signature, always xC1 xED x13 x00
x04 i16le Maximum number of extra paragraphs (PIFED asks in KiBs, default: 1023KiB[5])
x06 i16le Minimum number of extra paragraphs (PIFED asks in KiBs, default: 65KiB[5])
x08 i8 Flags
Bit 0 Requires 8087 coprocessor
Bit 1 May run in banked memory
Bit 2 Runs only in the foreground
Bit 4 Waits in idle loop
Bit 5 Requires aligned memory
x09 i8 x00
x0A i8 Lowest used interrupt (default: x08[5])
x0B i8 Highest used interrupt (default: x2F[5])
x0C i8 COM port usage
Bit 4 Direct access to COM1
Bit 5 Direct access to COM1
x0D i8 LPT port usage
Bit 0 Direct access to LPT1
Bit 1 Direct access to LPT2
Bit 2 Direct access to LPT3
x0E i8 Screen usage
Bit 1
0 Uses 24 lines
1 Uses 25 lines
Bit 2 Uses ANSI escape sequences
Bit 3 Uses ROS calls
Bit 4 Direct video access
x0F c[4] Signature, always x13 x00 xC1 xED

References


New executable (NE)

File extensions
.exe, .dll for OS/2 libraries (Multitasking MS-DOS and usually 16-bit Windows uses .exe for libraries as well)
Magic code
"NE" ("DX" for DOS/16M DOS extender)
Architecture
Intel 8086/80286
Operating systems
  • 1985-11-20: Windows 1.0
  • 1986: Multitasking MS-DOS 4.0
  • 1987-12: OS/2 1.0
  • ?: Rational Systems DOS/16M DOS extender
  • ?: Phar Lap 286|DOS-Extender
Influences
Intel 8086/80286

Contents

  1. Contents
  2. Overall layout
  3. Segmented EXE Format
  4. Segmented EXE Header
  5. Segment Table
  6. Resource Table
    1. Windows resource table
    2. OS/2 resource table
  7. Resident Name Table
  8. Module Reference Table
  9. Imported Name Table
  10. Entry Table
    1. Normal entries
    2. Constant
    3. Moveable entries
  11. Non-Resident Name Table
  12. Segment Data
  13. Relocations
    1. Internal reference to a fixed segment
    2. Internal reference to a movable segment
    3. Import by ordinal
    4. Import by name
    5. OSFIXUP
  14. References

Overall layout

Old-style Segmented EXE Format stub
Segmented EXE Header
Segment Table
Resource Table
Resident Name Table
Module Reference Table
Imported Name Table
Entry Table
Non-Resident Name Table
Segment Data and Relocations

Segmented EXE Format

After Windows 1.0 Development Release 5 (where a .mod file until Development Release 4, or .exe file in Development Release 5 starts immediately with an earlier version of the Segmented EXE Header[7]), a new executable file starts with an MZ stub program, with the following additional or modified field.

x18 i16le Must be x40[1] or greater [2]
x3C i32le Offset to Segmented EXE Header from file start in bytes

Segmented EXE Header

The segmented EXE header[1] or information block [2]

x00 c[2] 'NE'
DOS/16M can patch this to 'DX' to distinguish it from Windows applications
x02 i8 Linker version number
x03 i8 Linker revision number
x04 i16le Offset of Entry Table from Segmented EXE Header start in bytes
x06 i16le Size of Entry Table in bytes
x08 i32le 32-bit CRC of entire file[1], calculated with this field being 0[3]
x0C i16le Module flag word
Bits 0:1 Executable file format
0 NOAUTODATA, no automatic data segment. Only for DLLs[3]
1 SINGLEDATA, one[2] shared[1] automatic data segment. Set for DLLs
2 MULTIPLEDATA, multiple[2] or instanced[1] automatic data segments. Set for Windows applications
Bit 2 For DLLs, per-process initialization[4]
([5] claims global initialization)
1 if module runs in real mode[3]
Bit 3 Runs in protected mode[3], protected mode only[4][5]
Bit 4 (Windows) Uses LIM EMS directly[4]
([5] claims 8086 instructions)
Bit 5 (OS/2) Requires 80286[4][5]
(Windows) Each instance has separate EMS bank[4]
Bit 6 (OS/2) Requires 80386[4][5]
(Windows) For DLLs, global memory above EMS line[4]
Bit 7 Needs 80x87[4][5]
Bits 8:9 Presentation Manager compatibility (OS/2 GUI)[4][5]
1 Incompatible[4], fullscreen[5]
2 Compatible
3 Requires Presentation Manager
Bit 11 (Windows) First segment contains code that loads application[2]
(OS/2) Family Application, runs in DOS as well[5]
Bit 13 Errors detected during linking, module will not load
Bit 14 (Windows) For DLLs, set if private DLL and only one program can access it[4]
Non-conforming program, valid stack is not maintained[5][3]
Bit 15 Library module. SS:SP is invalid[1]. CS:IP points to initialization procedure, called with AX set to the module handle, return far with nonzero AX on success. DS is set to the automatic data segment for SINGLEDATA, to caller data otherwise
x0E i16le Automatic segment number, starting at 1. Set to 0 for NOAUTODATA
x10 i16le Size of initial heap in bytes, added to the automatic data segment following initial stack
x12 i16le Size of initial stack in bytes, added to the automatic data segment
x14 i16le Initial IP (entry)
x16 i16le Segment of initial CS (entry), starting at 1
x18 i16le Initial SP (stack). If SS is the automatic data segment and SP is 0, SP is set to top of the automatic segment below the initial heap
x1A i16le Segment of initial SS (stack), starting at 1. 0 for library modules
x1C i16le Number of entries in Segment Table
x1E i16le Number of entries in Module Reference Table
(official Windows 2.0 documentation mistakenly has this field missing and the other fields shifted)
x20 i16le Size of Non-Resident Name Table in bytes
x22 i16le Offset of Segment Table from Segmented EXE Header start in bytes
x24 i16le Offset of Resource Table from Segmented EXE Header start in bytes
x26 i16le Offset of Resident Name Table from Segmented EXE Header start in bytes
x28 i16le Offset of Module Reference Table from Segmented EXE Header start in bytes
x2A i16le Offset of Imported Name Table from Segmented EXE Header start in bytes
x2C i32le Offset of Non-Resident Name Table from file start in bytes
x30 i16le Number of movable entries in Entry Table
x32 i16le Logical sector alignment shift count. A 0 value represents 9[3]
x34 i16le Number of resource segments, and entries in Resource Table[2]
Under OS/2, the last segments correspond to resources[4]
x36 i8 Executable type
00 unknown[2]
01 OS/2[4][5]
02 Windows
03 Multitasking (a.k.a. "European") MS-DOS 4.0[5][4]
04 Windows 386[5]
05 BOSS (Borland Operating System Services)[5]
81 Phar Lap 286|DOS-Extender, OS/2[5]
81 Phar Lap 286|DOS-Extender, Windows[5]
x37 i8 Additional information[2]
Bit 0 (OS/2) Supports long filenames[4][5]
Bit 1 Windows 2.x application supporting proportional fonts[4]
(The official documentation[2][5] mistakenly claims this is bit 2)
Bit 2 Windows 2.x application running in Windows 3.x protected mode[4]
(The official documentation[2][5] mistakenly claims this is bit 1)
Bit 3 (Windows) Contains fast-load (gangload) area
x38 i16le (Windows) Offset of fast-load area (gangload area[5][4]) in sectors[2]
x3A i16le (Windows) Size of fast-load area (gangload area[5][4]) in sectors[2]
x3C i16le Minimum code swap area[5][4]
x3E i16le (Windows) Expected Windows version number[2]

Segment Table

Each entry has the following format

x00 i16le Offset to segment data and following segment information from file start in sectors. Zero if no data appears in file
x02 i16le Size of segment data stored in file in bytes. Zero for 65536 bytes
x04 i16le Flag word
Bit 0
0 Code segment
1 Data segment
Bit 1
1 Loader has allocated memory for segment[2]
Bit 2
1 Segment is loaded[2]
Real mode segment[5]
Bit 3
1 Iterated data[3][4][5]
Bit 4
0 FIXED[2][3]
1 MOVABLE[2][3]
Bit 5
0 IMPURE or NONSHAREABLE[2][3]
1 PURE or SHAREABLE[2][3][4][5]
Bit 6
0 LOADONCALL[2][3]
1 PRELOAD[2][3]
Bit 7
1 Code segment: EXECUTEONLY[2][3][5]
Data segment: READONLY[2][3][4][5]
Bit 8
1 Relocation information is present, follows segment data
Bit 9
1 Debugging information is present (former meaning)[3][4][5]
Conforming code segment[4]
Bits 10:11 Descriptor privilege level (DPL)[3][4][5]
Bit 12 Discardable segment[2][4][5]
Bits 12:15 Discard priority[3][1]
Bits 13:15 Discard priority[5]
Bit 13 32-bit segment[4]
Bit 14 Part of huge segment[4]
Bit 15 RESRC_HIGH[4]
x06 i16le Minimum allocated size of segment in bytes. Zero means 65536 bytes

Resource Table

Windows resource table

The resource table consists of an alignment shift count field, an array of types and a sequence of resource names.

x00 i16le Alignment shift count, for encoding the offsets to resources

A list of types follow. There must be a single entry for each type.

x00 i16le Type ID
A value of 0 terminates the resource table
If the high order bit is clear, it is an offset to a type string, relative to the beginning of the resource table
Otherwise, it is a resource type value:[8]
01 RT_CURSOR — cursor
02 RT_BITMAP — bitmap
03 RT_ICON — icon
04 RT_MENU — menu
05 RT_DIALOG — dialog box
06 RT_STRING — string table
07 RT_FONTDIR — font directory
08 RT_FONT — font component
09 RT_ACCELERATOR — keyboard accelerator table
0A RT_RCDATA — resource data
0C RT_GROUP_CURSOR — cursor directory
0E RT_GROUP_ICON — icon directory
x02 i16le Number of resources for this type
x04 i32le Reserved
x08 ... Table of resources for this type

Each resource has one entry for it:

x00 i16le Offset to resource data from file start, must be shifted by alignment shift count to get offset
x02 i16le Length of resource, shifted by alignment shift count[3][4] ([1] and [2] mistakenly claim it is in bytes)
x04 i16le Flags, similar to segment flags
Bit 4 MOVEABLE
Bit 5 PURE, can be shared
Bit 6 PRELOAD
Bits 12:15 Discard priority[3]
x06 i16le Resource ID
If the high order bit is clear, it is an offset to a resource string, relative to the beginning of the resource table
Otherwise, it is an integer
x08 i16le Handle, reserved
x0A i16le Usage, reserved

These structures are followed by a resource name table that contains the names of entries exported by name, with the entry number included.

x00 i8 Length of the string or 0 to terminate the table
x01 c[*] ASCII text of the string name, not terminated with null

OS/2 resource table

Contains a series of resources, identified by their type and name IDs. Each entry corresponds to a segment, and the last segments (out of the total list of segments) are the resources.[4]

x00 i16le Type ID
x02 i16le Name ID

Resident Name Table

The table contains the names of entries exported by name, with the entry number included.

x00 i8 Length of the string or 0 to terminate the table
x01 c[*] ASCII text of the string name, not terminated with null
... i16le Ordinal number

Module Reference Table

The table contains a list of module references, each of which is identified by the module name within the Imported Name Table.

x00 i16le Offset to module name in Imported Name Table

Imported Name Table

A list of names of imported modules and procedures. Names are identified via their offsets within the table.

x00 i8 Length of the string
x01 c[*] ASCII text of the string name, not terminated with null

Entry Table

Contains a sequence of entry bundles

x00 i8 Number of entries in bundle. A zero value terminates the table
x01 i8 Segment indicator for bundle
00 Unused entries, skip entry numbers
* Normal entries
FE Constant defined in module[2]
FF Moveable entries

Normal entries

x00 i8 Flag word
Bit 0 Set for exported entry
Bit 1 Set if entry uses a global/shared data segment, only valid for SINGLEDATA library modules. First instruction must be MOV AX, segment_number
Bits 3:7 On ring transition, specifies number of words to be copied on call[2]
x01 i16le Offset to entry point within segment

Constant

Undocumented

Moveable entries

x00 i8 Flag word
Bit 0 Set for exported entry
Bit 1 Set if entry uses a global/shared data segment, only valid for SINGLEDATA library modules
Bits 3:7 On ring transition, specifies number of words to be copied on call[2]
x01 c[2] An INT x3F instruction, xCD x3F
x03 i8 Segment number
x04 i16le Offset to entry point within segment

Non-Resident Name Table

The table contains the names of entries exported by ordinal, with the internal entry name included. The table has an identical format to the Resident Name Table.

x00 i8 Length of the string or 0 to terminate the table
x01 c[*] ASCII text of the string name, not terminated with null
... i16le Ordinal number

Segment Data

For iterated data, the file has the following structure[3]:

x00 i16le Number of iterations
x02 i16le Pattern length
x04 c[*] Pattern to be repeated

Relocations

Every segment data may optionally have a sequence of relocations followed, if specified in the Segment Table.

x00 i16le Number of relocations

Afterwards, relocations have the following format each.

x00 i8 Source type
Bits 0:3
00 low 8-bit
02 16-bit selector/segment
03 16:16-bit far pointer (32-bit)
05 16-bit offset within a segment
0B 16:32-bit far pointer (48-bit)[2]
0D 32-bit offset within a segment[2]
x01 i8 Flags byte
Bits 0:2 Relocation type
00 internal reference
01 imported by ordinal
02 imported by name
03 OSFIXUP
Bit 3 ADDITIVE flag
0 The source offset references the first word in a chain terminated by xFFFF. The word is replaced by the address, and the old value references the second word in the chain, which is then also replaced
1 The source offset references a word and the target value is added to it
x02 i16le Offset within this segment to source
x04 c[4] Relocation data

The interpretation of the relocation data depends on the relocation type.

Internal reference to a fixed segment

References an address within the same module.

x04 i8 Segment number in Segment Table, not equal to xFF
x05 i8 x00
x06 i16le Offset into the fixed segment

Internal reference to a movable segment

x04 i8 xFF
x05 i8 x00
x06 i16le Ordinal index into Entry Table

Import by ordinal

x04 i16le Index into Module Reference Table to module
x06 i16le Ordinal number for procedure

Import by name

x04 i16le Index into Module Reference Table to module
x06 i16le Offset within Imported Name Table to procedure name

OSFIXUP

Represents a floating point instruction that Windows will "fix up" when the coprocessor is emulated.[6]

x04 i16le Fixup type
(apparently the relocations containing the J are supposed to refer to the second byte of the command sequence[4])
(including relocations and interrupts supported by other platforms for completeness sake)
0x0001 FIARQQ, FJARQQwait; DS: esc turns into int x3C; byte x18-x1F by adding xFE32 and x4000 respectively
0x0002 FISRQQ, FJSRQQwait; SS: esc turns into int x3C; byte x58-x5F by adding x0632 and x8000 respectively
0x0003 FICRQQ, FJCRQQwait; CS: esc turns into int x3C; byte x98-x9F by adding x0E32 and xC000 respectively
0x0004 FIERQQwait; ES: esc turns into int x3C by adding x1632
0x0005 FIDRQQwait; esc turns into int x34-x3B by adding x5C32
0x0006 FIWRQQnop; wait turns into int x3D by adding xA23D
FIFRQQ, FJFRQQwait; FS: esc[4]
FIGRQQ, FJGRQQwait; GS: esc[4]
the sequence int x3E; byte xDC, x01-x08
Load 8087 registers to 8086 stack, count specified in byte[5]
the sequence int x3E; byte xDE, x01-x08
Load 8086 stack to 8087 registers, count specified in byte[5]
the sequence int x3E; byte xE0; nop
Round, compare and pop the two top elements on the
8087 stack as single precision, store status word in
AX and condition bits in FLAGS[5]
the sequence int x3E; byte xE2; nop
Round, compare and pop the two top elements on the
8087 stack as double precision, store status word in
AX and condition bits in FLAGS[5]
x06 i16le 0

References


Linear executable (LE, LX)

File extensions
.exe, .dll for libraries, .386 for Windows/386 virtual device drivers, .vxd for Windows 95 virtual device drivers and later
Magic code
"LE" or "LX" for OS/2
Architecture
various, mostly Intel 80386
Operating systems
  • probably 1987-09: Windows/386 drivers (LE)
  • 1990-05-22: Windows 3.0 and Windows 95 drivers (LE)
  • 1991-07: Rational Systems DOS/4G DOS extender (LE)
  • ?: OS/2 2.0 beta (LE)
  • 1991-10: OS/2 2.0 Limited Availability (LX)
  • ?: EMX DOS extender (LX)
Influences
various, mostly Intel 80386

Contents

  1. Contents
  2. Overall layout
  3. Old-style EXE header and executable
  4. Linear Executable Module Header
  5. Loader Section
    1. Object Table
    2. Object Page Table
    3. Object Iterated Page Table
    4. Resource Table
    5. Resident Name Table
    6. Entry Table
      1. Unused entry
      2. 16-bit entry
      3. 286 call gate entry
      4. 32-bit entry
      5. Forwarder entry
    7. Module Format Directives Table (optional)
    8. Resident Directives Data Table (optional)
    9. Per-Page Checksum
  6. Fixup Section (resident)
    1. Fixup Page Table
    2. Fixup Record Table
      1. Internal reference
      2. Imported reference by ordinal
      3. Imported reference by name
      4. Internal reference via entry table
      5. Internal chaining fixups
    3. Import Module Name Table
    4. Import Procedure Name Table
  7. Data Section
    1. Iterated data pages
    2. Non-Resident Name Table
    3. Non-Resident Directives Data
  8. Debug Section
  9. References

Overall layout

Old-style EXE header and executable
Linear Executable Module Header
Loader Section
Fixup Section (resident)
Data Section
Debug Section

Old-style EXE header and executable

A linear executable file starts with an MZ stub program, with the following additional or modified field.

x18 i16le Should be x0040
x24 i16le OEM Identifier
x26 i16le OEM Info
x3C i32le Offset to Linear Executable Module Header from file start in bytes

Linear Executable Module Header

Starts at the offset indicated in the Old-style EXE header and executable. The general layout is as follows.

Executable Info
Module Info
Loader Section Info
Table Offset Info

The following table lists the actual fields.

x00 c[2] Magic number
'LE' original version[3][4][6]
'LX' OS/2 2.0 optimizations
x02 u8 Byte ordering
0x00 little endian (8086, PDP-11)
0x01 big endian (68000)
x03 u8 Word ordering
0x00 little endian (8086)
0x01 big endian (68000, PDP-11)
x04 i32le Format level, version of executable, current version is 0
x08 i16le CPU Type
0x01 Intel 80286 or upward compatible
0x02 Intel 80386 or upward compatible
0x03 Intel 80486 or upward compatible
0x04 Intel Pentium (80586) or upward compatible[4][5][6]
0x20 Intel i860 (N10) or compatible[4][5][6]
0x21 Intel "N11" or compatible[4][5][6]
0x40 MIPS I (R2000, R3000) or compatible[4][5][6]
0x41 MIPS II (R6000) or compatible[4][5][6]
0x42 MIPS III (R4000) or compatible[4][5][6]
x0A i16le OS Type
0x00 Unknown
0x01 OS/2
0x02 Windows
0x03 DOS 4.x, Multitasking ("European") MS-DOS 4.0[4]
0x04 Windows 386
0x05 IBM Microkernel Personality Neutral[2]
x0C i32le Module version
x10 i32le Module type
Bit 1 Single data[3]
Bit 2
0 Global library initialization
1 Per-process library initialization. EIP Object number and EIP must have valid values
Bit 4 Internal fixups have been applied. If set, each object has a preferred address at which it can be loaded without internal fixups
Bit 5 External fixups have been applied
Bits 8:9 Application type
00 Unknown[5]
01 Incompatible with PM windowing
02 Compatible with PM windowing
03 Uses PM windowing API
Bit 13 Module is not loadable. Either there were errors during linking or the module is being incrementally linked
Bits 15:17 Module type
00 Program. Modules cannot contain dynamic links to program modules
01 Library
Windows 3.x device driver (must have external fixups done)[3]
03 Protected memory library
04 Physical device driver
05 Virtual device driver
(Windows VxD) Static device driver[3]
07 (Windows VxD) Dynamic device driver[3]
Bit 19 Unsafe to run in multiple-processor environment[2]
Bit 30
0 Global library termination
1 Per-process library termination. EIP Object number and EIP must have valid values
x14 i32le Number of pages physically appearing in the module. This includes pages with enumerated or iterated data, or according to [1] but not [2], zero-filled pages with relocations
x18 i32le Object number of EIP (entry or library initialization). Must be non-zero for programs
x1C i32le Initial EIP (entry or library initialization)
x20 i32le Object number of ESP (stack). Must be non-zero for programs, ignored for libraries
x24 i32le Initial ESP (stack). Ignored for libraries
x28 i32le Size of a single page in bytes. Should be 4096
x2C i32le (LE) Byte count of final page[4][6]
(LX) Page offset shift for Object Page Table entry offsets[1][2][4]
x30 i32le Size of Fixup Section (resident) in bytes
x34 i32le Checksum of Fixup Section (resident)
x38 i32le Size of Loader Section in bytes
x3C i32le Checksum of Loader Section
x40 i32le Offset of Loader Section from Linear Executable Module Header start in bytes
x44 i32le Number of objects in Object Table
x48 i32le Offset of Object Page Table from Linear Executable Module Header start in bytes
x4C i32le Offset of Object Iterated Page Table from file start in bytes
x50 i32le Offset of Resource Table from Linear Executable Module Header start in bytes
x54 i32le Number of entries in Resource Table
x58 i32le Offset of Resident Name Table from Linear Executable Module Header start in bytes
x5C i32le Offset of Entry Table from Linear Executable Module Header start in bytes
x60 i32le Offset of Module Format Directives Table (optional) from Linear Executable Module Header start in bytes
x64 i32le Number of entries in Module Format Directives Table (optional)
x68 i32le Offset of Fixup Page Table from Linear Executable Module Header start in bytes
x6C i32le Offset of Fixup Record Table from Linear Executable Module Header start in bytes
x70 i32le Offset of Import Module Name Table from Linear Executable Module Header start in bytes
x74 i32le Number of entries in Import Module Name Table
x78 i32le Offset of Import Procedure Name Table from Linear Executable Module Header start in bytes
x7C i32le Offset of Per-Page Checksum from Linear Executable Module Header start in bytes
x80 i32le Offset of data pages from file start in bytes
x84 i32le Number of preload pages. OS/2 2.0 does not respect the preload of pages
x88 i32le Offset of Non-Resident Name Table from file start in bytes
x8C i32le Size of Non-Resident Name Table in bytes
x90 i32le Checksum of Non-Resident Name Table
x94 i32le (16-bit compatibility) Automatic DS object
x98 i32le Offset of Debug Section from file start[2] in bytes. ([1] claims it is from Linear Executable Module Header but [2] clarifies that this is wrong)
x9C i32le Size of debug information in bytes
xA0 i32le Number of instance pages in preload section
xA4 i32le Number of instance pages in demand section
xA8 i32le (16-bit compatibilty) Size of initial heap in bytes
xAC i32le (OS/2 only) Size of stack in bytes[2]. Byte at offset xAD should not be x02 or x04 for OS/2 2.0
xB0 c[8] reserved
xB8 i32le (Windows VxD only) Offset of VERSIONINFO resource[3][4]
xBC i32le (Windows VxD only) Size of VERSIONINFO resource[3][4]
xC0 i16le (Windows VxD only) Device ID[3][4]
xC2 i16le (Windows VxD only) DDK version[3][4] (x030A[3])

Loader Section

Object Table
Object Page Table
Object Iterated Page Table
Resource Table
Resident Name Table
Entry Table
Module Format Directives Table (optional)
Resident Directives Data Table (optional)
Per-Page Checksum (LX only)

Object Table

The object table's location and length can be read from the Linear Executable Module Header directly. Each entry is 24 bytes long.

x00 i32le Size of object loaded into memory
x04 i32le The base address of the object. If the internal relocations have been removed, the object must be loaded at this address
x08 i32le Object flags
Bit 0 Readable
Bit 1 Writable
Bit 2 Executable
Bit 3 Resource
Bit 4 Discardable
Bit 5 Shared
Bit 6 Object has Preload pages
Bit 7 Object has Invalid pages
Bits 8:9 (LE) Type[5]
00 Normal
01 Zero-filled
02 Resident
03 Resident/contiguous
Bit 8 (LE) Object is Permanent and Swappable[3]
(LX) Object has Zero Filled pages (non-Contiguous)[3][1]
Bit 9 (device drivers only) Object is Resident[3][1]
Bit 10 (device drivers only) Object is Resident and long-lockable[3][1][5]
Bit 11 Object is marked as an IBM Microkernel extension[2]
Bit 12 (x86 specific) 16:16 alias required
Bit 13 (x86 specific) the Big bit for data segments and the Default bit for code segments
Bit 14 (x86 specific) Object is conforming code
Bit 15 (x86 specific) Object I/O privilege level, for 16:16 alias objects
x0C i32le Object Page Table index
x10 i32le Object Page Table entry count, any remaining pages are zero filled unless last defined entry is illegal, in which case all remaining pages are illegal
x14 i32le reserved

Object Page Table

Every page stored in the image has a corresponding page table entry. The format of an entry differs between the LE and LX formats.

This is the format of an LE entry.

x00 i24be Index into Fixup Page Table[4][3][5]
Note: all sources agree that the third byte stores the low order byte.
[3] handles this as a 24-bit big endian value.
[4] only documents the second and third bytes, and indicates that the first one is usually 0.
[5] clarifies that the first two bytes contain the "high page number", but does not detail its structure.
x03 i8 Flags[4][3][5]
Note: the sources disagree on its format.
[3] treats it as identical to LX flags, always generates 0.
[4] only defines values 0 and 3, with 3 being relocations required.
[5] provides a bit field:
Bits 0:1
03 Last page in file
Bits 6:7
00 Legal page
01 Iterated page
02 Invalid page
03 Zero filled page

This is the format of an LX entry.

x00 i32le Offset to page data shifted by the Page offset shift. For zero filled pages, this is 0
x04 i16le Data size. The remainder of the page size is filled with zero for a legal physical page or the iterated data records
x06 i16le Flags
00 Legal physical page, offset from start of Preload pages
01 Iterated data page, offset from start of Iterated data pages
02 Invalid page
03 Zero filled page
04 Range of pages
05 Compressed page, offset from Preload pages[2]
08 M3-packed[3]

The two formats encode different information. The LE format contains the offset into the fixup page table. For LX, the fixup page table goes in parallel with the object page table, and each entry corresponds to the accompanying other entry.

The LX format contains the offset and size of each page. For LE, every page but the last one in the file has the same size, and they come consecutively.

Object Iterated Page Table

Same structure as Object Page Table.

Resource Table

x00 i16le Type ID
01 RT_POINTER — mouse pointer shape[2]
02 RT_BITMAP — bitmap[2]
03 RT_MENU — menu template[2]
04 RT_DIALOG — dialog template[2]
05 RT_STRING — string tables[2]
06 RT_FONTDIR — font directory[2]
07 RT_FONT — font[2]
08 RT_ACCELTABLE — accelerator tables[2]
09 RT_RCDATA — binary data[2]
0A RT_MESSAGE — error message tables[2]
0B RT_DLGINCLUDE — dialog include file name[2]
0C RT_VKEYTBL — key to vkey tables[2]
0D RT_KEYTBL — key to UGL tables[2]
0E RT_CHARTBL — glyph to character tables[2]
0F RT_DISPLAYINFO — screen display information[2]
10 RT_FKASHORT — function key area short form[2]
11 RT_FKALONG — function key area long form[2]
12 RT_HELPTABLE — help table for Cary Help manager[2]
13 RT_HELPSUBTABLE — help subtable for Cary Help manager[2]
14 RT_FDDIR — DBCS uniq/font driver directory[2]
15 RT_FD — DBCS uniq/font driver[2]
x02 i16le Name ID
x04 i32le Resource size
x08 i16le Object number
x0A i32le Offset within object image

Resident Name Table

x00 i8 Length of the string or 0 to terminate the table. [1] reserved bit 7 as an Overload bit for additional information for parameter type checking, but this behavior is absent from [2]
x01 c[*] ASCII text of the string name, not terminated with null
... i16le Ordinal number

Entry Table

Entries are combined into bundles. Every bundle has the following heading:

x00 i8 Number of entries in the bundle. A 0 value indicates the end of the Entry Table
x01 i8 Bundle (entry) type
Bits 0:6
00 Unused entry
01 16-bit entry
02 286 call gate entry
03 32-bit entry
04 Forwarder entry
Bit 7 Parameter typing information

Unused entry

Unused entries have no following data, the next bundle follows directly after the first 2 bytes.

16-bit entry

The bundle has a 4 byte header followed by 3 byte entries:

x02 i16le Object number

x00 i8 Flags
Bit 0 Exported entry
Bit 1 (LE) Segment uses a global/shared data segment[5]
Bits 3:7 Parameter word count
x01 i16le Offset in object

286 call gate entry

The bundle has a 4 byte header followed by 5 byte entries:

x02 i16le Object number

x00 i8 Flags
Bit 0 Exported entry
Bits 3:7 Parameter word count
x01 i16le Offset in object
x03 i16le Call gate selector, reserved

32-bit entry

The bundle has a 4 byte header followed by 5 byte entries:

x02 i16le Object number

x00 i8 Flags
Bit 0 Exported entry
Bit 1 (LE) Segment uses a global/shared data segment[5]
Bits 3:7 Parameter word count
x01 i32le Offset in object

Forwarder entry

The bundle has a 4 byte header followed by 5 byte entries:

x02 i16le Reserved

x00 i8 Flags
Bit 0
0 Import by name
1 Import by ordinal
x01 i16le Module number
x03 i16le Procedure name offset
Import ordinal number

Module Format Directives Table (optional)

TODO

Resident Directives Data Table (optional)

TODO

Per-Page Checksum

TODO

Fixup Section (resident)

Fixup Page Table
Fixup Record Table
Import Module Name Table
Import Procedure Name Table
Per-Page Checksum (LE only)[6]

Fixup Page Table

For every page there is a 32-bit (little endian) value for the offset of the first relocation record within Fixup Record Table in bytes. There is a final 32-bit (little endian) value that is the size of the Fixup Record Table.

Fixup Record Table

A collection of variable length fixup records, each referring to a fixup within a specific page. The header is either 3 or 4 bytes long, depending on the Source list flag.

x00 u8 Source flags
Bits 0:3 Source type
00 low 8-bit
02 16-bit selector
03 16:16-bit far pointer (32-bit)
05 16-bit offset within a segment
06 16:32-bit far pointer (48-bit)
07 32-bit offset within a segment
08 32-bit self relative fixup, [4]for 16-bit segments, 16-bit self relative fixup
Bit 4 Fixup to 16:16-bit alias
Bit 5 Source list, providing a list of source offsets instead of a single one
x01 u8 Target flags
Bits 0:1 Target type
00 Internal reference
01 Imported reference by ordinal
02 Imported reference by name
03 Internal reference via entry table
Bit 2 Additive fixup, an additive field follows the record (but before the source offset list, if the Source list flag is set)
Bit 3 Internal chaining fixup. When set, the source offset is an offset to the first entry of a chain of fixups[2]
Bit 4 Target offset width
0 16-bit
1 32-bit
Bit 5 Additive value width
0 16-bit
1 32-bit
Bit 6 Object number/module ordinal number width
0 8-bit
1 16-bit
Bit 7 Ordinal number width
0 16-bit or 32-bit
1 8-bit
x02 i16le If the Source list flag is 0, this is the offset to the source
x02 i8 If the Source list flag is 1, this is the number of source offsets appearing after the target data
x03x<sub>04 c[*] Target data, depending on the reference type
... i16le[*] If Source list flag is 1, this is a list of offsets

Internal reference

Target object number Object number width (8-bit/16-bit)
Target offset Target offset width (16-bit/32-bit)

Imported reference by ordinal

Module index Object number/module ordinal number width (16-bit/32-bit)
Imported ordinal Ordinal number width (8-bit)
Target offset width (16-bit/32-bit)
Additive value (Additive fixup) Additive value width (16-bit/32-bit)

Imported reference by name

Module index Object number/module ordinal number width (16-bit/32-bit)
Procedure name offset into Import Procedure Name Table Target offset width (16-bit/32-bit)
Additive value (Additive fixup) Additive value width (16-bit/32-bit)

Internal reference via entry table

Index into entry table Object number/module ordinal number width (16-bit/32-bit)
Additive value (Additive fixup) Additive value width (16-bit/32-bit)

Internal chaining fixups

When the internal chaining fixup flag is set, the source address becomes the first element of a chain. Each chain element contains a 32-bit value at the source which is used to determine the next chain element and a relocation addend.[2]

x00 i32le
Bits 0:19 Target offset, added to the base address, which is the target address minus the first target offset.
Bits 20:31 Source offset, to the next fixup within the same page, or xFFF

Import Module Name Table

x00 i8 Length of the string or 0 to terminate the table
x01 c[*] ASCII text of the string name, not terminated with null

Import Procedure Name Table

The first entry must be the null string.

x00 i8 Length of the string or 0 to terminate the table. reserved bit 7 as an Overload bit for additional information for parameter type checking, but this behavior is absent from
x01 c[*] ASCII text of the string name, not terminated with null

Data Section

Preload pages
Demand load pages
Iterated data pages
Non-Resident Name Table
Non-Resident Directives Data

Iterated data pages

x00 i16le Number of iterations
x02 i16le Pattern length
x04 c[*] Pattern to be repeated

Non-Resident Name Table

Same format as the Resident Name Table.

Non-Resident Directives Data

TODO

Debug Section

TODO

References


Portable executable (PE)

File extensions
.exe, .dll for libraries, etc.
Magic code
"PE" ("PL" for Phar Lap)
Architecture
various, including Intel 80386
Operating systems
  • 1993-09-27: Windows NT 3.1
  • 1995-08-24: Windows 95 (4.0)
  • 1998-03: BeOS Release 3 for Intel 80386
  • ?: Phar Lap TNT DOS-Extender
  • ?: HX-DOS extender
Influences
various, including Intel 80386

Contents

  1. Contents
  2. Overall layout
  3. MS-DOS stub
  4. Signature
  5. COFF File Header
  6. Optional header
    1. Optional header standard fields
    2. Optional header Windows-specific fields
    3. Optional header data directories
  7. Section header
  8. Section data
    1. .debug section
    2. .drectve section
    3. Export (.edata) section
      1. Export address table
      2. Export name pointer table
      3. Export ordinal table
      4. Export name table
    4. Import (.idata) section
      1. Import directory table
      2. Import lookup table
      3. Hint/name table
      4. Import address table
    5. .pdata section
    6. Base relocation table (.reloc) section
      1. Base relocation block
    7. .tls section
    8. Load configuration section
    9. .rsrc section
      1. Resource directory table
      2. Resource directory strings
      3. Resource data description
      4. Resource data
    10. .cormeta section
    11. .sxdata section
  9. COFF relocations
  10. COFF line numbers
  11. COFF symbol table
  12. Auxiliary symbols
  13. COMDAT sections
  14. CLR token definition
  15. COFF string table
  16. Attribute certificate table
  17. Delay-load import tables
  18. References

Overall layout

The PE format is probably the most widespread format for personal computer. It is based on the COFF file format, and several fields are similar to it. Similarly to other Microsoft formats, it starts with an MS-DOS stub that typically displays a message that this application can only be run in Windows, and then exits.

MS-DOS stub
Signature
COFF File Header
Optional header standard fields
Optional header Windows-specific fields
Optional header data directories
Section headers
Section data
COFF symbol table
COFF relocations

MS-DOS stub

A portable executable file starts with an MZ stub program, with the following additional or modified field.

x18 i16le Should be x0040
x24 i16le OEM Identifier
x26 i16le OEM Info
x3C i32le Offset to Signature from file start in bytes

Signature

Only part of an image.[5] This signature identifies the application as PE. A COFF image follows it.

x00 i32le 'PE\0\0'
Phar Lap uses 'PL\0\0' to distinguish from Windows applications

COFF File Header

x00 i16le Machine (COFF magic)
0x0000 unknown[1][3][5]
0x014C Intel 386[1][2][3][4][5]
0x8664 AMD64[3][5]
0x01C0 ARM[2][3] little endian[5]
0x01C2 ARM Thumb[3][5]
0x01C4 ARM Thumb-2 little endian[5]
0xAA64 ARM64 little endian[5]
0xA641 ARM64EC[6]
0x0200 Intel Itanium[2][3][5]
0x5032 RISC-V 32-bit[5]
0x5064 RISC-V 64-bit[5]
0x5128 RISC-V 128-bit[5]
0x0268 Motorola 68000[2]
0x014D Intel i860[4]
0x014D Intel 486[1]
0x014E Intel Pentium[1]
0x0162 MIPS Mark I: R2000[1], R3000[1][2][4]
0x0163 MIPS Mark 2: R6000[1]
0x0166 MIPS Mark 3: R4000[2][4], MIPS[3] little endian[5]
0x0168 MIPS R10000[2]
0x0266 MISP16[2][3][5]
0x0366 MIPS with FPU[2][3][5]
0x0466 MIPS16 with FPU[2][3][5]
0x0169 MIPS WCE v2[3] little endian[5]
0x0183 DEC Alpha AXP[4]
0x0184 DEC Alpha AXP[2]
0x0284 DEC Alpha AXP 64-bit[2]
0x01D3 Matsushita AM33[3][5]
0x0EBC EFI byte code[3][5]
0x9041 Mitsubishi M32R[3][5]
0x01F0 PowerPC[3][2] little endian[5]
0x01F1 PowerPC with floating point[3][5]
0x0601 PowerPC based Macintosh (stored in little endian) [checked with MSVC cross compiler]
0x01A2 Hitachi SH3[3][5]
0x01A3 Hitachi SH3 DSP[3][5]
0x01A6 Hitachi SH4[3][5]
0x01A8 Hitachi SH5[3][5]
0x0500 Hitachi SH big endian[6]
0x0550 Hitachi SH little endian[6]
0x0290 PA-RISC[6]
0x6232 LoongArch 32-bit[5]
0x6264 LoongArch 64-bit[5]
x02 i16le Number of Sections (COFF)
x04 i32le Time Date Stamp, seconds since 1970-01-01 midnight (COFF)
x08 i32le Offset to symbol table (COFF)
Should be 0 in PE image
x0C i32le Number of symbols in symbol table (COFF)
Should be 0 in PE image
x10 i16le Size of optional header (COFF)
x12 i16le Characteristics (COFF flags)
Bit 0 No relocations (COFF)
Bit 1 No unresolved symbols, executable (COFF)
Bit 2 No line number information, deprecated (COFF)
Bit 3 No local symbols, deprecated (COFF)
Bit 4 Aggressively trim working set (obsolete since Windows 2000)[5]
Bit 5 > 2GB support
Bit 6 Reserved
Bit 7 Little endian (deprecated)
Bit 8 Little endian, 32-bit (COFF)
Bit 9 No debugging information
Bit 10 Removable run from swap, fully load and run from swap if on removable media
Bit 11 Net run from swap, fully load and run from swap if on network
Bit 12 System file
Bit 13 DLL
Bit 14 Uniprocessor machine
Bit 15 Big endian (deprecated)

Optional header

The following parts only appear inside load images.

Optional header standard fields

x00 i16le Magic
0x0107 ROM image[5]
0x010B PE32, 32-bit
0x020B PE32+, 64-bit
x02 i8 Major version
x03 i8 Minor version
x04 i32le Size of code (COFF: text)
x08 i32le Size of data (COFF)
x0C i32le Size of bss (COFF)
x10 i32le Entry point relative to image base (COFF)
x14 i32le Address of code relative to image base (COFF)
x18 i32le (Not PE+) Address of data relative to image base (COFF)

Optional header Windows-specific fields

x1Cx18 i32lei64le Image base address, added to almost all address fields, must be multiple of 64Ki
0x00010000 Default for Windows CE executables
0x00400000 Default for Windows NT/95 executables and higher
0x10000000 Default for DLLs
x20 i32le Section alignment in bytes
Default: page size
x24 i32le File alignment of raw data sections in file, should be power of 2 between 512 and 64Ki
x28 i16le OS major version
x2A i16le OS minor version
x2C i16le Image major version
x2E i16le Image minor version
x30 i16le Subsystem major version
x32 i16le Subsystem minor version
x34 i32le Win32 version; must be 0
x38 i32le Size of complete image in bytes (multiple of section alignment)
x3C i32le Size of headers, including DOS stub and section headers (multiple of file alignment)
x40 i32le Checksum
x44 i16le Subsystem
0x0000 Unknown
0x0001 Device driver, native Windows process
0x0002 Windows GUI
0x0003 Windows character mode
0x0005 OS/2 character mode[1][4][5]
0x0007 POSIX character mode
0x0008 Native Win9x driver[5]
0x0009 Windows CE[3][5]
0x000A EFI application[3][5]
0x000B EFI driver with boot services[3][5]
0x000C EFI driver with runtime services[3][5]
0x000D EFI ROM image[3][5]
0x000E Xbox[3][5]
0x0010 Windows boot application[5]
x46 i16le DLL characteristics
0x0001 Call on process startup[1][4]
0x0002 Call on process[1] termination ([4] claims thread)
0x0004 Call on thread startup[1][4]
0x0008 Call on thread[1] termination ([4] claims process)
0x0020 Can handle high entropy 64-bit virtual address space[5]
0x0040 Can be relocated at load time[3]
0x0080 Code integrity check enforced[3]
0x0100 NX compatible image[3]
0x0200 Isolation aware, do not isolate[3]
0x0400 Does not use structured exception handling[3]
0x0800 Image must not be bound[3]
0x1000 Must execute in AppContainer[5], Reserved[3]
0x2000 WDM driver[3]
0x4000 Supports Control Flow Guard[5]
0x8000 Terminal server aware[3]
x48 i32lei64le Size of stack to reserve
x4Cx50 i32lei64le Size of stack to commit
x50x58 i32lei64le Size of heap to reserve
x54x60 i32lei64le Size of heap to commit
x58x68 i32le Loader flags, 0
x5Cx6C i32le Number of data directory entries

Optional header data directories

Stored as 4-byte relative virtual address and 4-byte size

x00 i32le[2] Export table (Export (.edata) section)
x08 i32le[2] Import table (Import (.idata) section)
x10 i32le[2] Resource table (.rsrc section)
x18 i32le[2] Exception table
x20 i32le[2] Certificate table; stored as file pointer and size
x28 i32le[2] Base relocation table (Base relocation table (.reloc) section)
x30 i32le[2] Debug data
x38 i32le[2] Architecture/Description string, must be 0
x44 i32le Global pointer
x44 i32le =0
x48 i32le[2] Thread local storage table
x50 i32le[2] Load configuration table[3][5]
x58 i32le[2] Bound table import[3][5]
x60 i32le[2] Import address table[3][5]
x68 i32le[2] Delay import descriptor[3][5]
x70 i32le[2] CLR runtime header[3][5]
x78 i32le[2] Reserved, 0[3][5]

Section header

A sequence of structures encoding the sections.

x00 c[8] Section name, padded with nulls (COFF)
A '/' followed by a decimal number gives an offset into the string table (not for executables)
x08 i32le Total size of section
x0C i32le Virtual address (COFF)
x10 i32le Size of data in image (COFF)
x14 i32le Offset to section data from PE start (COFF)
x18 i32le Offset to relocation data, 0 for executables (COFF)
x1C i32le Offset to line number entries (deprecated) (COFF)
x20 i16le Number of relocations, 0 for executables (COFF)
x22 i16le Number of line numbers (deprecated)
x24 i32le Flags
Bit 3 TYPE_NO_PAD - Must not be padded (obsolete)
Bit 5 CNT_CODE - Executable (COFF)
Bit 6 CNT_INITILIAZED_DATA - Initialized data (COFF)
Bit 7 CNT_UNINITIALIZED_DATA - Uninitialized data (COFF)
Bit 8 LNK_OTHER - reserved
Bit 9 LNK_COMMENT - Comments
Bit 11 LNK_REMOVE - Not part of final image (object only)
Bit 12 LNK_COMDAT - COMDAT[5]
Bit 15 GPREL - Data in section is referenced through the global pointer[5]
Bit 16 MEM_PURGEABLE - reserved[5] (typo in documentation, shows bit 17)
Bit 17 MEM_16BIT - reserved[5]
Bit 18 MEM_LOCKED - reserved[5]
Bit 19 MEM_PRELOAD - reserved[5]
Bits 20:23 Alignment: 2 ** (value - 1)
Bit 24 LNK_NRELOC_OVFL - Contains extended relocations
Bit 25 MEM_DISCARDABLE - Discardable
Bit 26 MEM_NOT_CACHED - Non-cachable
Bit 27 MEM_NOT_PAGED - Non-pageable
Bit 28 MEM_SHARED - Shareable
Bit 29 MEM_EXECUTE - Executable
Bit 30 MEM_READ - Readable
Bit 41 MEM_WRITE - Writable

Section data

RVA is an abbreviation of relative virtual address. It is relative to the image base.

.debug section

TODO

.drectve section

TODO

Export (.edata) section

x00 i32le Flags, reserved
x04 i32le Date time stamp
x08 i16le Major version
x0A i16le Minor version
x0C i32le RVA of ASCII string of name of DLL
x10 i32le Starting ordinal number, typically 1
x14 i32le Number of Export address table entries
x18 i32le Number of entries in the Export name pointer table as well as the ordinal table
x1C i32le RVA of Export address table
x20 i32le RVA of Export name pointer table
x24 i32le RVA of Export ordinal table

Export address table

A sequence of 32-bit RVA for the exported values. It is either the exported address, or a forwarder: a null-terminated ASCII string within the export table directory referencing another DLL entry, consisting of the DLL name, a '.' and either the name of the export, or '#' and the decimal value of the ordinal.

An export can be accessed by ordinal by providing the index into this table, relative to the starting ordinal number.

Export name pointer table

A sequence of 32-bit RVA into the Export name table. The entries should be ordered lexically. A symbol imported by name will match this entry, and the associated ordinal entry in the export ordinal table provides the ordinal value for an entry in the Export address table.

Export ordinal table

A sequence of 16-bit ordinal values, referencing the Export address table, where each entry corresponds to the corresponding entry in the Export name pointer table.

Export name table

A series of null-terminated ASCII strings, referenced by Export name pointer table.

Import (.idata) section

Import directory table

A sequence of entries for each imported DLL. It is closed by an entry of all zeros.

x00 i32le RVA of Import lookup table (also called Characteristic)
x04 i32le Datetime stamp
x08 i32le Index of first forwarder reference
x0C i32le RVA of ASCII string of the DLL name
x10 i32le RVA of Import address table

Import lookup table

A sequence of 32-bit or 64-bit entries. If the most significant bit (bit 31 or bit 63) is set, it provides a 16-bit ordinal import. Otherwise the low 31 bits provide the RVA of an entry in the Hint/name table. The table is closed by a 0 value.

Hint/name table

x00 i16le Index into Export name pointer table of the imported DLL. If it fails, lookup uses the name instead
x02 c[*] Null-terminated ASCII string of the imported name. An extra null byte is added to align to 2 bytes

Import address table

Identical in format and content to the Import lookup table, but the values get replaced by the actual addresses when loaded into memory.

.pdata section

TODO

Base relocation table (.reloc) section

Each 4 KiB page has an associated relocation block that starts on a 4-byte boundary, containing the addresses that should be relocated by the base address.

Base relocation block

x00 i32le RVA of the page
x04 i32le Size of block in bytes, including these two fields
x08 i16le[*]
Bits 0:11 Offset from page start to the
Bits 12:15 Type of base relocation
0 Skipped
1 High 16 bits
2 Low 16 bits
3 32 bits
4 High 16 bits, followed by low 16 bits
5 MIPS jump instruction
ARM 32-bit MOVW/MOVT instruction pair
RISC-V high 20 bits
6 reserved
7 ARM Thumb 32-bit MOVW/MOVT instruction pair
RISC-V low 12-bit I-type format
8 RISC-V low 12-bit S-type format
LoongArch 32-bit consecutive 2 instructions
LoongArch 64-bit 4 consecutive instructions
9 MIPS16 jump instruction
10 64-bit

.tls section

TODO

Load configuration section

TODO

.rsrc section

Resources are stored in a multi-level hierarchy. Windows uses 3 levels: type, name, language.

Resource directory table

x00 i32le Flags, reserved
x04 i32le Datetime stamp
x08 i32le Major version
x0A i32le Minor version
x0C i16le Number of entries identified by strings
x10 i32le Number of entries identified by numbers

This is then followed by the entries. First are the entries identified by strings, then the entries identified by numbers follow. All entries are stored lexicographically, then numerically.

x00 i32le Offsets in the resource data directory to strings
Or 32-bit numbers
x04 i32le If the high bit is clear, the address of a resource data
If the high bit is set, the address of another resource directory

Resource directory strings

A sequence of Unicode strings used in Resource directory table.

x00 i16le Length of the string
x02 c16[*] UTF-16 string

Resource data description

Each resource has one entry.

x00 i32le RVA of data
x04 i32le The size of the resource in bytes
x08 i32le Codepage
x0C i32le Reserved

Resource data

.cormeta section

TODO

.sxdata section

TODO

COFF relocations

Only present in object files.

x00 i32le Virtual address, relative to the image base (COFF)
x04 i32le Symbol name
A 0-based index into the symbol table (COFF)
x08 i16le Type (COFF)

Relocation types for AMD64:

x08 i16le Type (COFF)
x0001 64-bit address
x0002 32-bit address
x0003 32-bit RVA address
x0004 32-bit address relative from following byte
x0005-x0009 32-bit address relative from byte at distance 1-5
x000A 16-bit section index
x000B 32-bit offset from its section
x000C CLR token
x000D 7-bit offset from its section
x000E 32-bit signed span-dependent value
x000F pair following span-dependent value
x0010 32-bit signed span-dependent value applied

Relocation types for Intel 386:

x08 i16le Type (COFF)
x0006 32-bit address (COFF)
x0007 32-bit RVA address
x000A 16-bit section index
x000B 32-bit offset from its section
x000C CLR token
x000D 7-bit offset from its section
x0014 32-bit relative displacement (COFF)

TODO: other systems

COFF line numbers

These are deprecated.

x00 i32le Symbol table index (if line number is 0) or virtual address
x04 i16le 1-based line number
0 for symbol table index

COFF symbol table

x00 c[8] Symbol name, zero-padded (first 4 bytes should not be all zero)
x00 i32le If zero, the symbol is inlined
x04 i32le Offset to name in symbol table (only if first 4 bytes are zero)
x08 i32le Value of symbol
x0C i16le Section number, 1-based
0x0000 External/undefined symbol
0xFFFF Absolute symbol
0xFFFE Debugging symbol
x0E i16le Symbol type: base type (Microsoft tools set this to x00 or x20)
x0000 No symbol
x0001 void
x0002 char, int8
x0003 short int, int16
x0004 int
x0005 long int, int32
x0006 float
x0007 double
x0008 struct ...
x0009 union ...
x000A enum ...
x000B Member in enumeration
x000C unsigned char, uint8
x000D unsigned short int, uint16
x000E unsigned int
x000F unsigned long int, uint32
x0010 Pointer
x0020 Function
x0030 Array
x10 i8 Storage class, only certain values are used
x00 No entry
x01 Automatic
x02 External/public (used)
x03 Static/private (used)
x04 External definition (TODO: swapped from COFF?)
x05 Register (TODO: swapped from COFF?)
x06 Label
x07 Undefined label
x08 Member of structure
x09 Function argument
x0A Structure tag
x0B Member of union
x0C Union tag
x0D Type definition
x0E Undefined static
x0F Enumeration tag
x10 Member of enumeration
x11 Register parameter
x12 Bitfield
x64 Beginning/end of block (.bb, .eb)
x65 Beginning/end of function (.bf, .ef) (used)
x66 End of structure
x67 File name (used)
x68 Section defintion
x69 Weak external
x6B CLR token symbol
xFF Physical end of function
x11 i8 Number of auxiliary entries, each entry occupying a symbol record

Auxiliary symbols

TODO

COMDAT sections

Object only.

TODO

CLR token definition

Object only.

TODO

COFF string table

Object only.

TODO

Attribute certificate table

Image only.

TODO

Delay-load import tables

Image only.

TODO

References


MP/MQ executable

File extensions
.exp, .exe with MZ stub, .rex with relocations
Magic code
"MP", "MQ" with relocations
Architecture
Intel 80386
Operating systems
  • 1986-08: Phar Lap 386|DOS-Extender
  • ?: FM Towns OS (via Phar Lap 386|DOS-Extender)
Influences
Intel 80386

Contents

  1. Contents
  2. Overall layout
  3. Executable stub and loader
  4. Header
  5. Relocations
  6. References

Overall layout

This format comes in two modes: load modules '.exp' and relocatable load modules '.rex'. An '.exp' load module consists of a header and the following image data. A '.rex' module is similar but it is followed by relocations.

The '.exp' or '.rex' file can also be combined with an MS-DOS stub into an '.exe' file that loads the image following the MZ structure. The Win386 does the same but it combines a '.rex' module with a Windows based loader (one that also comes with its own MS-DOS stub).

Executable stub and loader
Header (including Relocations for MQ)
Image

Executable stub and loader

When embedded inside a DOS .exe file, an additional entry in the header is used to store the start of the load module.

x3C i32le Offset to Header from file start in bytes

For executables using the Win386 Windows extender, that field is already used for the 'NE' header, which will load the executable into memory from Windows. Instead, the previous field is used:

x38 i32le Offset to Header from file start in bytes
x3C i32le Offset to the NE header for the Win386 extender

Header

x00 c[2] 'MP' for a regular module or 'MQ' for a relocatable module
x02 i16le Number of bytes in the last 512 byte page, or 0 if the entire page is used
x04 i16le Number of 512 byte pages in load module, rounded up
x06 i16le Number of relocations, should be 0 for an 'MP' file
x08 i16le Size of this header in 16 bytes paragraphs
x0A i16le Required minimum additional memory in 4KiB pages
x0C i16le Required maximum additional memory in 4KiB pages, xFFFF means all memory[1]
x0E i32le Initial value of ESP (stack)
x12 i16le Checksum, the sum of all 16-bit words in the file should be zero. Alternatively, it is the negation of the modular sum of all 16-bit words except this one[1]
x14 i32le Initial value of EIP (entry)
x18 i16le Offset of first relocation from '.exp' module, should be x1E[3]
x1A i16le Overlay number, should be 0[1][3]
x1C i16le =x0001[1][2]

Relocations

A sequence of i32le offsets from the image start that should be relocated. They contain addresses the base of the image should be added to.

x00 i32le
Bits 0:30 Address of value to be relocated
Bit 31
0 32-bit value
1 16-bit value[1]

References


BW executable

File extensions
.exp, .exe with MZ stub
Magic code
"BW"
Architecture
Intel 80286
Operating systems
1987-07: Rational Systems DOS/16M DOS extender
Influences
Intel 80286

Contents

  1. Contents
  2. Overall layout
  3. Executable stub and loader
  4. Module Header
    1. DOS-style 'BW' header
    2. Additional fields in header
    3. GDT image
      1. Additional fields, inside GDT image
      2. Old run-time selectors
      3. GDT data
  5. Relocation data
    1. RSI-1
    2. RSI-2
  6. References

Overall layout

An '.exp' load module consists of a header and the following segment data. It can appear on its own, or multiple modules can be spliced together, with an MZ stub attached.

Information is organized around the concept of a global descriptor table (GDT), as used on the Intel 80286 CPU. Every part of the program is accessed in one of several segments. The physical address, size and access permissions for these segments are stored in a system structure called the GDT. Segments are addressed as 16-bit values, incremented by a value of 8, as an index into the GDT. The BW file format exposes this architecture to a high degree.

The actual module header structure can be further subdivided into multiple parts.

Executable stub and loader
DOS-style 'BW' header
Additional fields in header
Additional fields, inside GDT image
GDT data
Segment data
Relocation data
DOS-style 'BW' header for .exp file 2

Relocations can come in two formats: RSI-1 or RSI-2.

Executable stub and loader

When embedded inside a DOS .exe file, an additional entry in the header is used to store the start of the load module.

x3C i32le Offset to Module Header from file start in bytes

Module Header

The module header consists of a block of header fields, followed by a GDT image. The block of header fields starts with a set of fields similar to those in the MZ header, followed by a few more specific to the DOS/16M extender. The GDT image also contains several header fields, however addressing GDT entries starts at that address, so they are separated out.

DOS-style 'BW' header

x00 c[2] 'BW', signature that identifies it as a DOS/16M load module
x02 i16le Number of bytes in the last 512 byte page, or 0 if the entire page is used
x04 i16le Number of 512 byte pages in load module, rounded down[2]
x06 i16le[2] Reserved
x0A i16le Required minimum additional memory in KiB
x0C i16le Required maximum additional memory in KiB (implies private allocation)
x0E i16le Initial SS (stack segment)
x10 i16le Initial SP (stack)
x12 i16le For RSI-2, the selector for the first relocation (huge relocation list)
x14 i16le Initial IP (entry)
x16 i16le Initial CS (segment of entry)
x18 i16le Size of the GDT (global descriptor table) at runtime in bytes - 1
x1A i16le Version of the tool that created the file
MAKEPM: major version * 100 + minor version
GLU[1]: major version * 1000 + minor version (Watcom pretends to be GLU version 2.0)
GLU[2]: (major version + 10) * 100 + minor version

Additional fields in header

x1C i32le Position of next spliced .exp entry from start of file
Also end pointer to current load module
x20 i32le Offset to start of CodeView[2] debug info (TODO: not sure where it is stored inside the file)
x24 i16le Last used selector value in GDT image
0 means the last used value can be derived from the size of the GDT image
(TODO: Watcom drops the last entry in the table)
x26 i16le Private memory allocation in KiB[1]
x28 i16le Allocation increment (ExtReserve) in KiB[1]
x2A c[6] Reserved

GDT image

The first few GDT entries are overwritten by some additional header fields.

Additional fields, inside GDT image

Selector #0 (x00)

x30 i16le Runtime options[1], switch control[2]
Bit 0 Force A20 line to 0 in 80386 real mode[2]
Bit 1 Do not test for VCPI at startup[1]
Bit 2 Do not defer BIOS INT 16h function 1[2]
Do not inhibit keyboard polling[1]
Bit 3 Allow overloading[1]
Bit 4 OPT_INT10 - ?[1]
Bit 5 Initialize newly allocated memory to x00
Bit 6 Initialize newly allocated memory to xFF
Bit 7 Rotate selector assignment[1], do not reuse selectors immediately after cancelling[2]
Bit 12 Relocation table is present, must be set to make relocatable[1]
x32 i16le Selector of transparent stack (obsolete[2])
x34 i16le Module flags
Bit 0 ef_auto - Automatic selectors, module is relocatable
Bit 1 ef_package - Module is an .exp package
Bit 2 ef_nobigfoot - Do not place stack in low DPMI memory[1]
Bit 13 ef_sharedata - Data is global, not per-instance[1]
Bit 14 ef_shareable - Component may be shared[1]
Bit 15 ef_dos4g - Module requires DOS/4G[1]
x36 i16le Size of program in 16 byte paragraphs (obsolete[2])

Selector #1 (x08)

x38 i16le Size of GDT in file, in bytes
x3A i16le First used selector, first selector actually containing data
0 means x80 (selector #16)
The first selector is always stored at offset xB0[3]
x3C i8 Default memory strategy
0x00 MPreferExt - Prefer extended memory
No strategy specified
0x01 MPreferLow - Prefer conventional memory
0x02 MForceExt - Requires extended memory
0x03 MForceLow - Requires conventional memory
0x04 MTransparent - Requires conventional memory, allocate selectors for transparent addressing[2]
0x05 MTransStack - Transparent, aligned for use as stack[2]
x3D i8 Reserved, x92 (usually)
x3E i16le Size of transfer buffer in bytes, 0 means 8 KiB

Selectors #2-#7 (x10-x38)

x40 i32le Load module length (according to Watcom, not reflected in actual files)
x44 c[0x2C] -

Selectors #8-#15 (x40-x78)

x70 c[0x20] Original .EXP file name

Old run-time selectors

At run-time, the first few selectors were originally used by DOS/16M to refer to various system structures.[2]

x00 i16le Null selector (CPU enforced)
x08 i16le Selector to access GDT (or LDT)
x10 i16le Selector to access IDT
x18 i16le Kernel code
x20 i16le Kernel data
x28 i16le MS-DOS program segment prefix
x30 i16le MS-DOS environment
x38 i16le Physical memory address 0
x40 i16le BIOS data
x48 i16le Reserved
x50 i16le GDT auxiliary information segment
x58 i16le Reserved
x60 i16le Scratch descriptor for debugging
x68 i16le Reserved
x70 i16le Kernel code in extended memory
x78 i16le Reserved
x80 i16le First user-mode selector

GDT data

The actual GDT data typically starts at selector #16 (offset xB0). It is a sequence of structures similar to entries in an Intel 80286 GDT.

x00 i16le Size of segment as stored in file - 1
0 means empty
Watcom generates 16 byte paragraph aligned values
x02 i24le Address of segment in 16-byte paragraphs[3], optional field, typically 0
x05 i8 Access bits
Bit 1 For code segments, set if readable
For data segments, set if writable (always readable)
Bit 3
0 Data segment
1 Code segment
Bit 4 1
Bits 5:6 Descriptor privilege level (0 for system/highest privilege, 3 for user mode/lowest)
Bit 7 1
x06 i16le
Bits 0:12 Required memory size in 16 byte paragraphs, maximum of x10000 allowed
Bit 13 If set, segment is empty, no file data or memory allocated
Bit 15 If set, marks a transparent stack

Relocation data

Relocation data is stored in segments, following the image segments. No image data comes after the relocations.

Each relocation specifies a selector and offset that must be relocated. The data to be relocated contains a selector that will be modified according to what the actual loaded selector values are.

RSI-1

The last two segments contain the relocations. The first of these two segments contains the selector values, the second one the offset values. Each relocation position is specified by the corresponding selector and offset values at the same position in the two segments.

The list is terminated when the segment data terminates, or when both the selector and offset values are 0.

Note that this gives a limit of 32768 relocations.

RSI-2

The last several segments contain the relocations. Relocations are provided as a sequence of variable length structures of the following form:

x00 i16le Selector values of addresses needed to be relocated
Bit 1 Set if this is the last relocation required
x02 i16le Number of offsets corresponding to this selector value
x04 i16le[*] Sequence of offsets that need relocation within this segment

References


XP executable

File extensions
.exp, .exe with MZ stub
Magic code
"XP" for Intel 80286, unknown for Intel 80386
Architecture
Intel 80286, Intel 80386
Operating systems
1988: Ergo OS/286, probably Ergo OS/386 as well
Influences
Intel 80286, Intel 80386

Contents

  1. Contents
  2. Overall layout
  3. Header
  4. Segment Table
  5. Needing more information
  6. References

Overall layout

Much of the format is deduced through reverse engineering.

The file consists of a header, a segment table, followed by the binary image.

Header
Segment Table, part of the header
Binary image
Relocations?

Header

x00 c[4] 'XP\1\0'
x04 i32le Offset to segment table base, typically x68
x08 i32le Number of entries in segment table
x0C i32le Offset to image, typically directly following header
x10 i32le Image size in bytes
x14 i32le Offset to fixups (probably)
x18 i32le Number of fixup entries (format unknown)
x1C i32le Minimum extent (unknown)
x20 i32le Maximum extent (unknown)
x24 i32le =0
x28 i32le GS (16-bit register stored in a 32-bit field)
x2C i32le FS
x30 i32le DS
x34 i32le SS
x38 i32le CS
x3C i32le ES
x40 i32le EDI
x44 i32le ESI
x48 i32le EBP
x4C i32le ESP
x50 i32le EBX
x54 i32le EDX
x58 i32le ECX
x5C i32le EAX
x60 i32le EFLAGS
x64 i32le EIP

Segment Table

The segment table typically follows the header. Each entry has a structure very similar to an Intel 80386 segment descriptor inside an LDT.

x00 i16le Limit or size of segment - 1, least significant 2 bytes
x02 i24le Base, relative to image base + x100, least significant 3 bytes
x05 i8 Attributes (seems to only recognize segment descriptors)
Bit 0 =0
Bit 1 =1
Bit 2 =0
Bit 3
0 Data segment
1 Code segment
Bit 4 =1
Bit 5-6 DPL, typically 3
Bit 7 =1
x06 i8 Attributes
Bits 0-3: limit, most significant 1 byte
Bits 4: selector is alias (must not be set together with window)
Bits 5: selector is window (must not be set together with alias)
Bits 6: 32-bit (as for 386)
Bits 7: limit is given in pages instead of bytes (as for 386)
x07 i8 Base, most significant 1 byte

The EXPRESS command seemingly generates pairs of data and an optional code segment. The first segment is supposed to correspond to the PSP.

Needing more information

The format of the fixups is currently not known. The meaning of extents is not understood. There may be additional unknown flags or entries. The runtime layout is not known. It is also not known if OS/386 uses the same file format, however based on the structure of the file, whether an executable is 16-bit or 32-bit can be determined from the segment table.

References

  • [1] DMPEXP.EXE (OS/286)

P2/P3 executable

File extensions
.exp, .exe with MZ stub
Magic code
"P2" for Intel 80286, P3 for Intel 80386
Architecture
Intel 80286, Intel 80386
Operating systems
  • ?: Phar Lap 386|DOS-Extender
  • 1991: FM Towns OS (via Phar Lap 386|DOS-Extender)
Influences
Intel 80286, Intel 80386

Contents

  1. Contents
  2. Overall layout
    1. Flat model
    2. Multi-segmented model
  3. Header
  4. Segment Information Table
  5. Relocation Table
  6. Run-time Parameter Block
  7. Symbol Table
    1. Symbol Table Header
    2. Segment Symbol Table
    3. Public Symbol Table
  8. Intel Task State Segment
    1. 16-bit Task State Segment
    2. 32-bit Task State Segment
  9. Descriptor Tables
    1. Intel Global Descriptor Table
    2. Intel Interrupt Descriptor Table
    3. Intel Local Descriptor Table
  10. Borland Debug Information
  11. References

Overall layout

This format comes in two models: flat model and multi-segmented model.

The '.exp' file can also be combined with an MS-DOS stub into an '.exe' file that loads the image following the MZ structure.

Flat model

The program consists of a header, followed by the run-time parameter block, an optional symbol table and the program image. (TODO: not sure about the position of the symbol table)

Header
Run-time Parameter Block
Symbol Table
Program image
Borland Debug Information (optional)

Multi-segmented model

The program consists of a header, followed by the segment information table, relocations, run-time parameter block, an optional symbol table and the program image.[3] (TODO: not sure about the position of the symbol table)

The program image consists of multiple segment images. It also contains some low level Intel 80286/80386 specific entries such as the task state segment and descriptor tables.

Header
Segment Information Table
Relocation Table
Run-time Parameter Block
Symbol Table
Intel Task State Segment in program image
Intel Global Descriptor Table in program image
Intel Interrupt Descriptor Table in program image
Intel Local Descriptor Table in program image
Code and data segments in program image
Borland Debug Information (optional)

A 16-bit (P2) file could typically be segmented, with relocations, a runtime parameter block and an LDT, but no segment information table, TSS, GDT or IDT. The Watcom compiler can also generate 32-bit (P3) segmented files, complete with a segment-information table, TSS, GDT, an 8-byte long IDT and an LDT, with code/data segments being stored in the LDT, while the TSS/GDT/IDT/LDT accessible via selectors in GDT.

Header

x00 c[2] 'P3' for 80386
'P2' for 80286[2]
x02 i16le
0001 Flat model
0002 Multi-segmented model[2][3]
x04 i16le Size of Header in bytes, should be x0180
x06 i32le Size of entire '.exp' file, including all header information
x0A i16le Checksum, the sum of all 16-bit words in the file should be zero. Alternatively, it is the negation of the modular sum of all 16-bit words except this one[1]
x0C i32le Offset to Run-time Parameter Block from start of '.exp' file, should be x0180 for flat model progarms
x10 i32le Size of Run-time Parameter Block
x14 i32le (Multi-segmented) Offset to Relocation Table from start of '.exp' file[2][3], should be x00000000 for flat model programs[1]
x18 i32le (Multi-segmented) Size of Relocation Table[2][3], should be x0000 for flat model programs[1]
x1C i32le (Multi-segmented) Offset to Segment Information Table from start of '.exp' file[2][3], should be x00000000 for flat model programs[1]
x20 i32le (Multi-segmented) Size of Segment Information Table[2][3], should be x0000 for flat model programs[1]
x24 i16le (Multi-segmented) Size of Relocation Table entry[2][3], should be x000C[3], should be x0000 for flat model programs[1]
x26 i32le Offset to program image from start of '.exp' file
x2A i32le Size of program image in file, containing the code and data
x2E i32le Offset to Symbol Table, x00000000 if no symbols are present
x32 i32le Size of Symbol Table, x00000000 if no symbols are present
x36 i32le (Multi-segmented) Offset of Intel Global Descriptor Table within program image, should be x00000000 for flat model programs[1]
x3A i32le (Multi-segmented) Size of Intel Global Descriptor Table, should be x00000000 for flat model programs[1]
x3E i32le (Multi-segmented) Offset of Intel Local Descriptor Table within program image, should be x00000000 for flat model programs[1]
x42 i32le (Multi-segmented) Size of Intel Local Descriptor Table, should be x00000000 for flat model programs[1]
x46 i32le (Multi-segmented) Offset of Intel Interrupt Descriptor Table within program image, should be x00000000 for flat model programs[1]
x4A i32le (Multi-segmented) Size of Intel Interrupt Descriptor Table, should be x00000000 for flat model programs[1]
x4E i32le (Multi-segmented) Offset of Intel Task State Segment within program image, should be x00000000 for flat model programs[1]
x52 i32le (Multi-segmented) Size of Intel Task State Segment, should be x00000000 for flat model programs[1], x0000002C or more for 80286[4], x00000068 or more for 80386[5]
x56 i32le (Flat[2]) Minimum number of bytes to allocate after the program image
x5A i32le (Flat[2]) Maximum number of bytes to allocate after the program image
x5E i32le (Flat[2]) Base offset at which the executable is linked
Used to trap null references[1]
x62 i32le Initial ESP (stack)
x66 i16le (Multi-segmented) Initial SS (segment of stack)[2][3]
x68 i32le Initial EIP (entry)
x6C i16le (Multi-segmented) Initial CS (segment of entry)[2][3]
x6E i16le (Multi-segmented) Initial LDT value[2][3]
x70 i16le (Multi-segmented) Initial TSS value[2][3]
x72 i16le Flags
Bit 0 Load image is compressed (packed)
Bit 1 32-bit checksum is present[2]
Bits 2:4 Relocation table type[2]
x74 i32le Load image in memory when uncompressed, same as image size of uncompressed files
x78 i32le Optional 32-bit checksum[2]
x7C i32le Size of initial stack in bytes
x80 c[0x100] Reserved

Segment Information Table

Only for multi-segmented programs.[2][3] For every segment in the data, there should be a corresponding entry in the segment information table. The descriptor tables and task state segments normally do not require an entry.

x00 i16le Selector number
Bits 0:1 Privilege level
Bit 2
0 Addresses a GDT entry
1 Addresses an LDT entry
x02 i16le Flags
x04 i32le Base offset within program image
x08 i32le Extra bytes to be allocated for the segment

Relocation Table

Only for multi-segmented programs.[2][3] Addresses of 16-bit selector values in the image that need to be relocated.

For a 16-bit file ('P2'), each entry in the relocation table consists of a 4-byte entry:[6]

x00 i16le Offset to value to be relocated
x02 i16le Selector of segment of value to be relocated

For a 32-bit file ('P3'), each entry in the relocation table consists of a 6-byte entry:[3]

x00 i32le Offset to value to be relocated
x04 i16le Selector of segment of value to be relocated

Run-time Parameter Block

This should begin at offset x0180 for flat-model programs. The format is usually the 'DX' format.

x00 c[2] 'DX' for extended '.exp' files, it can be changed[1]
x02 i16le MINREAL, minimum number of 16-byte paragraphs of real mode memory to leave free
x04 i16le MAXREAL, maximum number of 16-byte paragraphs of real mode memory to leave free
x06 i16le MINIBUF, minimum number of 1KiB blocks for data buffer for DOS system calls
x08 i16le MAXIBUF, maximum number of 1KiB blocks for data buffer for DOS system calls
x0A i16le NISTACK, number of interrupt stacks, controls the maximum number of nested switches between real mode and protected mode
x0C i16le ISTSIZE, size in 1KiB blocks of each interrupt stack buffer
x0E i32le REALBREAK, end of real mode code and data
x12 i16le CALLBUFS, size of call buffer in 1KiB to be used for passing data between real mode and protected mode
x14 i16le Flags
Bit 0 File is virtual memory manager[2], reserved for Phar Lap[1]
Bit 1 File is debugger[2], reserved for Phar Lap[1]
Bits 2:15 Reserved[1]
x16 i16le Unprivileged flag[1]
0x0000 PRIVILEGED, run program at privilege level 0[1][2]
0x0001 UNPRIVILEGED, run program at privilege level 1, 2 or 3[1][2]
x18 c[0x66] Reserved

Symbol Table

The PUBSYM symbol table has the following layout:[1]

Symbol Table Header
Segment Symbol Table
Public Symbol Table

Symbol Table Header

x00 c[4] 'SYM1'
x04 i16le Size of Symbol Table Header in bytes, should be x0E
x06 i32le Size of Segment Symbol Table in bytes
x0A i32le Size of Public Symbol Table in bytes

Segment Symbol Table

Each entry starts with a variable length field containing its name.

x00 i8 Length of name
x01 c[*] String containing name

The name is then followed by a fixed 12-byte structure.

x00 i32le Offset to segment within program image
x04 i32le Size of segment
x08 i16le Selector (real mode) or paragraph (protected mode) of segment
x0A i16le Segment flags
Bit 0 Absolute segment (only in real mode)

Public Symbol Table

Each entry starts with a variable length field containing its name.

x00 i8 Length of name
x01 c[*] String containing name

The name is then followed by a fixed 12-byte structure.

x00 i32le Offset to symbol within segment
Constant value for absolute symbols
x04 i16le 1-based index of selector of symbol in Segment Symbol Table

Intel Task State Segment

Only for multi-segmented programs.[2][3] This is part of the program image and reflects an Intel 80286/80386 Task State Segment (TSS).

The Intel 80286/80386 architecture contains a structure that permits hardware assisted task switching. It contains entries for each register, stack segment and offset values for switching between different levels of privilege and some other administrative information. There are separate 16-bit and 32-bit versions (and later, 64-bit version) introduced for the 80286 and 80386, respectively.

16-bit Task State Segment

This is the 16-bit version[4], presumably used for 'P2' files. (TODO)

x00 i16le Link
x02 i16le SP (stack pointer) for ring 0 (highest privilege)
x04 i16le SS (stack segment) for ring 0 (highest privilege)
x06 i16le SP (stack pointer) for ring 1
x08 i16le SS (stack segment) for ring 1
x0A i16le SP (stack pointer) for ring 2
x0C i16le SS (stack segment) for ring 2
x0E i16le IP, point of execution at task switching
x10 i16le FLAGS, state of CPU flags
x12 i16le AX
x14 i16le CX
x16 i16le DX
x18 i16le BX
x1A i16le SP
x1C i16le BP
x1E i16le SI
x20 i16le DI
x22 i16le ES
x24 i16le CS (code segment), segment of executing task at task switching
x26 i16le SS (stack segment), segment of stack at task switching
x28 i16le DS
x2A i16le LDTR

32-bit Task State Segment

This is the 32-bit version[5], used for 'P3' files.[3]

x00 i16le Link
x02 i16le =0
x04 i32le ESP (stack pointer) for ring 0 (highest privilege)
x08 i16le SS (stack segment) for ring 0 (highest privilege)
x0A i16le =0
x0C i32le ESP (stack pointer) for ring 1
x10 i16le SS (stack segment) for ring 1
x12 i16le =0
x14 i32le ESP (stack pointer) for ring 2
x18 i16le SS (stack segment) for ring 2
x1A i16le =0
x1C i32le CR3 (control register 3), address of paging structure
x20 i32le EIP, point of execution at task switching
x24 i32le EFLAGS, state of CPU flags
x28 i32le EAX
x2C i32le ECX
x30 i32le EDX
x34 i32le EBX
x38 i32le ESP
x3C i32le EBP
x40 i32le ESI
x44 i32le EDI
x48 i16le ES
x4A i16le =0
x4C i16le CS (code segment), segment of executing task at task switching
x4E i16le =0
x50 i16le SS (stack segment), segment of stack at task switching
x52 i16le =0
x54 i16le DS
x56 i16le =0
x58 i16le FS
x5A i16le =0
x5C i16le GS
x5E i16le =0
x60 i16le LDTR
x62 i16le =0
x64 i16le
Bit 0 Debug trap bit, causes the CPU to raise an exception on task switch
x66 i16le I/O permission map offset from TSS start

Descriptor Tables

The Intel architecture defines a wide range of descriptor types. The following gives a general overview of the structure.

x00 i16le Limit or offset value
x02 i16le Base address or selector value
x04 i8 Byte 2 of base address or supplementary information
x05 i8 Access flags
Bits 0:3 Descriptor type
Bit 4
0 System descriptor
1 Code or data segment descriptor
Bits 5:6 Descriptor privilege level (0 for highest privilege, 3 for lowest privilege)
Bit 7 Present bit (must be 1 for properly accessing descriptor)
x06 i8 (80386 or later) Attribute bits or byte 2 of offset value
x07 i8 (80386 or later) Byte 3 of base address or offset value

A typical segment descriptor has the following layout:

x00 i16le Low 16 bits of limit, last byte in segment, or 0 for an empty segment
x02 i24le Low 24 bits of starting address of segment, OpenWatcom sets this to 0[3]
x05 i8 Access flags
Bit 0 Accessed bit
Bit 1 Data segments: writable
Code segments: readable
Bit 2 Data segments: expand-down, limit is the lower limit of the segment
Code segments: conforming, transfers to this segment will preserve the current privilege level
Bit 3
0 Data segment
1 Code segment
Bit 4 =1
Bits 5:6 Descriptor privilege level (0 for highest privilege, 3 for lowest privilege)
Bit 7 Present bit (must be 1 for properly accessing descriptor)
x06 i8 (80386 or later) Attribute bits
Bits 0:3 Bits 16 to 23 of limit
Bit 4 Bit available for user
Bit 5 Reserved (64-bit flag for 64-bit code segments, not used by Phar Lap)
Bit 6 32-bit segment
Bit 7 High granularity flag: limit value is shifted by 12 bits
x07 i8 (80386 or later) High 8 bits of starting address of segment, OpenWatcom sets this to 0[3]

The descriptor of an LDT or TSS:

x00 i16le Low 16 bits of limit, last byte in segment
x02 i24le Low 24 bits of starting address of segment, OpenWatcom sets this to 0[3]
x05 i8 Access flags
Bits 0:3
0x01 16-bit available TSS (invalid in 64-bit mode)
0x02 LDT
0x03 16-bit busy TSS (invalid in 64-bit mode)
0x09 32-bit available TSS (also 64-bit)
0x0B 32-bit busy TSS (also 64-bit)
Bit 4 =1
Bits 5:6 Descriptor privilege level (0 for highest privilege, 3 for lowest privilege)
Bit 7 Present bit (must be 1 for properly accessing descriptor)
x06 i8 (80386 or later) Attribute bits
Bits 0:3 Bits 16 to 23 of limit
Bit 4 Bit available for user
Bit 5 Reserved
Bit 6 Reserved
Bit 7 High granularity flag: limit value is shifted by 12 bits
x07 i8 (80386 or later) High 8 bits of starting address of segment, OpenWatcom sets this to 0[3]

The descriptor of a call, interrupt or trap gate:

x00 i16le Low 16 bits of offset
x02 i16le Selector for gate
x04 i8 Usually reserved
For a call gate, the low 5 bits provide the parameter count, number of 16-bit/32-bit words that need to be transferred between privilege levels (invalid in 64-bit mode)
(in 64-bit mode, interrupt and trap gates use the lower 3 bits to reference an interrupt stack table)
x05 i8 Access flags
Bits 0:3
0x04 16-bit call gate (invalid in 64-bit mode)
0x06 16-bit trap gate (invalid in 64-bit mode)
0x07 16-bit interrupt gate (invalid in 64-bit mode)
0x0C 32-bit call gate (also 64-bit)
0x0E 32-bit trap gate (also 64-bit)
0x0F 32-bit interrupt gate (also 64-bit)
Bit 4 =0
Bits 5:6 Descriptor privilege level (0 for highest privilege, 3 for lowest privilege)
Bit 7 Present bit (must be 1 for properly accessing descriptor)
x06 i16le (80386 or later) High 16 bits of offset

The descriptor of a task gate (invalid in 64-bit mode):

x00 i16le Reserved
x02 i16le Selector for TSS
x04 i8 Reserved
x05 i8 Access flags
Bits 0:3 =x05
Bit 4 =0
Bits 5:6 Descriptor privilege level (0 for highest privilege, 3 for lowest privilege)
Bit 7 Present bit (must be 1 for properly accessing descriptor)
x06 i16le Reserved

Intel Global Descriptor Table

Only for multi-segmented programs.[2][3] This is part of the program image and reflects an Intel 80286/80386 Global Descriptor Table (GDT). A global descriptor table provides the description of segments and gates that are supposed to be system wide. A GDT may contain all types of descriptors except interrupt and trap gates. Segment selectors address the GDT if bit 2 is 0.

OpenWatcom stores a dummy selector, as required by the architecture, then a 32-bit TSS, followed by 16-bit data segments to access the TSS, GDT, IDT, then an LDT and a 16-bit data segment to access the LDT.[3]

Intel Interrupt Descriptor Table

Only for multi-segmented programs.[2][3] This is part of the program image and reflects an Intel 80286/80386 Interrupt Descriptor Table (IDT). The Intel architecture defines 256 interrupt values, and in protected mode the IDT can hold a descriptor for each of these. Only task, interrupt and trap gates are permitted.

OpenWatcom stores only a dummy selector.[3]

Intel Local Descriptor Table

Only for multi-segmented programs.[2][3] This is part of the program image and reflects an Intel 80286/80386 Local Descriptor Table (LDT). Similarly to a global descriptor table, it contains descriptions of segments and gates. The Intel architecture makes it convenient to switch local descriptor tables, so it is usually used for task specific information. An LDT may contain only segment descriptors, as well as call and task gates. Segment selectors address the LDT if bit 2 is 1.

OpenWatcom stores a dummy selector, then an entry for each segment in the program image.[3]

Borland Debug Information

This optional section appears after the program image.[2]

TODO

References


Macintosh resource

File extensions
Magic code
Architecture
binary, Motorola 68000
Operating systems
1984-01-24: System 1 for Macintosh 128K (Mac OS)
Influences
binary, Motorola 68000

Contents

  1. Contents
  2. Overall layout
  3. Resource header
  4. Resource data
  5. Resource map
    1. Resource type list
    2. Reference list
    3. Resource name list
  6. 'CODE' resources
    1. Runtime view
      1. Jump table entries
        1. Near model jump table
        2. Far model jump table
        3. CFM-68K jump table
      2. Format of near 'CODE' segments
      3. Format of far 'CODE' segments
      4. Format of CFM-68K 'CODE' segments
  7. References

Overall layout

Classic Macintosh executables are stored together with other resources, as 'CODE' resources. The first part will be an overview of the resource file format in general.

Resource header
Reserved area
Resource data
Resource map (header)
Resource type list
Reference list
Resource name list

Resource header

x00 i32be Offset of Resource data from start of resource header, should be x0100
x04 i32be Offset of Resource map from start of resource header
x08 i32be Length of Resource data
x0C i32be Length of Resource map

Resource data

A sequence of resources, each encoded as follows.

x00 i32be Length of resource data, following this longword
x04 c[*] Actual resource data

Resource map

x00 c[0x10] Reserved for copy of resource header
x10 c[4] Reserved for handle to next resource map
x14 c[2] Reserved for file reference number
x16 i16be Reserved fork attributes
x18 i16be Offset of Resource type list from beginning of resource map
x1A i16be Offset of Resource name list from beginning of resource map
x1C i16be Number of types in Resource type list - 1
x1E c[*] Resource type list
... c[*] Reference list
... c[*] Resource name list

Resource type list

Each type has the following format.

x00 c[4] Resource type
x04 i16be Number of resources of this type - 1
x06 i16be Offset of Reference list entry from beginning of Resource type list

Reference list

Each resource type has a sequence of corresponding reference list entries.

x00 i16be Resource ID
x02 i16be Offset of resource name from beginning of Resource name list
xFFFF otherwise
x04 i8 Resource attributes
x05 i24be Offset of resource data from beginning of Resource data
x08 i32be Reserved for handle to resource

Resource name list

Each resource name has the following format.

x00 i8 Length of resource name
x01 c[*] Resource name

'CODE' resources

Runtime view

Every Classic Macintosh application consists of code segments, a stack and an area of memory addressed via the A5 register, referred to as the A5 world. The A5 world contains global variables as well as the jump table that permits code transfers between different code segments.

Code segments and the jump table are loaded from the 'CODE' resources. The jump table is stored as the 'CODE' resource with resource ID 0.

Jump table entries

The jump table stored in the 'CODE'0 resource has the following layout.

x00 i32be Above A5 size
x04 i32be Below A5 size, including global variables and QuickDraw global variables
x08 i32be Jump table size, 8 times the number of entries
x0C i32be Jump table offset, relative to the A5 register, should be x20

This is then followed by a sequence of (unloaded) jump table entries. There are two types of jump table entries: near model jump table entries (offset fits 16 bits) and far model jump table entries (offset requires 32 bits). Jump table entries (near and far) are grouped according to their segment.

A jump table entry is accessed via the instruction jsr offset(a5) for some offset.

Near model jump table

A near model jump table consists of a sequence of near model jump table entries. The format of an unloaded jump table entry is as follows:

x00 i16be Routine offset from beginning of segment
x02 i32be Instruction to load segment number onto stack
mov #number, -(sp)
x02 i16be x3F3C
x04 i16be Segment number
x06 i16be _LoadSeg trap number
xA9F0

The format of a loaded jump table entry, only appearing after the image is loaded in memory, is as follows.

x00 i16be Segment number
x02 i16be[3] Instruction to jump to routine
x02 i16be x4ED9
x04 i32be Absolute offset
Far model jump table

A far model jump table being with a sequence of near model jump table entries, followed by a flag and a sequence of far model jump table entries. It would typically start with a single near model jump table entry, addressing a bootstrap code that patches the _LoadSeg command.

Far model jump table entries are separated by a flag entry of the following format:

x00 i16be x0000
x02 i16be Version number, xFFFF
x04 i32be x00000000

This is then followed by (unloaded) far model jump table entries:

x00 i16be Segment number
x02 i16be _LoadSeg trap number
xA9F0
x04 i32be Segment offset
CFM-68K jump table

A CFM-68K application is very similar to a far model jump table but with a different flag entry:

x00 i16be x0000
x02 i16be Version number, xFFFD
x04 i32be x00000000

Note: it is unclear if the 'CODE'0 resource only contains a single near jump table entry and no flag.

Format of near 'CODE' segments

All other 'CODE' resources are loadable segments, and their resource ID is the number of the segment. Near model segments have a 4 byte header referencing the jump table data:

x00 i16be Offset to first jump table entry from the start of the jump table
x02 i16be Number of jump table entries

Format of far 'CODE' segments

Far model segments have a different header format:

x00 i16be Version number, xFFFF
x02 i16be Reserved, x0000
x04 i32be A5 offset of near entries
x08 i32be A5 number of near entries
x0C i32be A5 offset of far entries
x10 i32be A5 number of far entries
x14 i32be Offset of A5-relative relocation information
x18 i32be Value of A5, to be added to addresses
x1C i32be Offset of PC-relative relocation information
x20 i32be Segment load address
x24 i32be Reserved, x00000000

This header is then followed by the segment image, then the A5-relative relocation information, then the PC-relative relocation information.

Relocation information is stored as a compressed list of offsets between 32-bit words that need relocation.

x01-x7F Shifted by 1 for values between x02 and xFE
x8080-xFFFF Low 15 bits shifted by 1 for values between x0100 and xFFFE
x00 x80008000-xFFFFFFFF Low 31 bits shifted by 1 for values between x00010000 and xFFFFFFFE
x00 x00 End of relocation information

Format of CFM-68K 'CODE' segments

CFM-68K model segments have a format similar to that of far segments:

x00 i16be Version number, xFFFD
x02 i16be Reserved, x0000
x04 i32be A5 offset of jump table entries
x08 i32be A5 number of jump table entries
x0C i32be A5 offset of transition vectors
x10 i32be A5 number of transition vectors
x14 i32be Reserved, x00000000
x18 i32be Reserved, x00000000
x1C i32be Reserved, x00000000
x20 i32be Reserved, x00000000
x24 i32be Reserved, x00000000

This header is then followed by the segment image.

References


AppleSingle/AppleDouble container format

File extensions
.adf for AppleDouble stored on MS-DOS, but usually a prefix with % (UNIX), R. (ProDOS), ._ (Mac OS X/macOS)
Magic code
x00x05x16x00 for AppleSingle, x00x05x16x07 for AppleDouble
Architecture
binary, Motorola 68000
Operating systems
1988-02: A/UX
Influences
binary, Motorola 68000

Contents

  1. Contents
  2. Overall layout
  3. Header
  4. Data fork
  5. Resource fork
  6. Real name
  7. Comment
  8. Icon, B&W
  9. Icon, color
  10. File Info
    1. Macintosh
    2. A/UX File Info
    3. MS-DOS File Info
    4. ProDOS File Info
  11. File Dates Info
  12. Finder information
  13. Macintosh File Info
  14. ProDOS File Info
  15. MS-DOS File Info
  16. AFP short name
  17. AFP File Info
  18. AFP Directory ID
  19. References

Overall layout

Header

x00 i32be Magic number
0x00051600 AppleSingle
0x00051607 AppleDouble
x04 i32be Version number
0x00010000 Version 1
0x00020000 Version 2
x08 c[16] (Version 1) Home file system
(Version 2) reserved, all zeroes
"Macintosh       " Macintosh, A/UX
"ProDOS          " ProDOS
"MS-DOS          " MS-DOS
"Unix            " UNIX
"VAX VMS         " VMS
x0C i16be Number of entries

Each entry has the following format:

x00 i32be Entry ID
1 Data fork
2 Resource fork
3 Real name, in its home file system
4 Comment
5 Icon, B&W
6 Icon, color
7 (Version 1 only) File Info
8 (Version 2 only) File Dates Info
9 Finder information
10 (Version 2 only) Macintosh File Info
11 (Version 2 only) ProDOS File Info
12 (Version 2 only) MS-DOS File Info
13 (Version 2 only) AFP short name
14 (Version 2 only) AFP File Info
13 (Version 2 only) AFP Directory ID
0x80000000-0xFFFFFFFF user IDs
x04 i32be Offset
x08 i32be Size of entry

Data fork

Contains an arbitrary length sequence of bytes as stored for the file.

Resource fork

Contains the resource fork of a Macintosh or ProDOS file. Its structure is described elsewhere.

Real name

Contains a string of the file name in its home filesystem.

Comment

Standard Macintosh comment, stored as an ASCII string of at most 200 characters.

Icon, B&W

Macintosh black and white icon. Expected to be the copy of an 'ICON' or 'ICN#' resource. The ASIconBW structure is as follows:

x00 i32be[32] 32 rows of 32 1-bit pixels packed in longwords[3]

Icon, color

Macintosh color icon. Most likely a copy of an 'ICN#', 'ics#', 'icl4', 'ics4', 'icl8' or 'ics8' resource.

TODO

File Info

Version 1 only. The exact layout depends on the home file system.

Macintosh

x00 i32be Creation date (moved to File Dates Info in Version 2)
x04 i32be Modification date (moved to File Dates Info in Version 2)
x08 i32be Last backup date (moved to File Dates Info in Version 2)
x0C i32be Attributes (moved to Macintosh File Info in Version 2)
Bit 0 Locked
Bit 1 Protected

A/UX File Info

x00 i32be Creation date (moved to File Dates Info in Version 2)
x04 i32be Last use date & time (moved to File Dates Info in Version 2)
x08 i32be Last modification date & time (moved to File Dates Info in Version 2)

MS-DOS File Info

x00 i32be Modification date (moved to File Dates Info in Version 2)
x00 i16be MS-DOS attributes (moved to MS-DOS File Info in Version 2)

ProDOS File Info

x00 i32be Creation date & time (moved to File Dates Info in Version 2)
x04 i32be Modification date & time (moved to File Dates Info in Version 2)
x08 i16be Access (moved to ProDOS File Info in Version 2)
x0A i16be File Type (moved to ProDOS File Info in Version 2)
x04 i32be Auxiliary ("A/UX" in [1], likely typo) type (moved to ProDOS File Info in Version 2)

File Dates Info

Version 2 only, all systems. The structure is called ASFileDates.[3]

All entries are stored as a signed number, counting the seconds since 2000-01-01 GMT, midnight. Unknown entries are set to x80000000.[3]

x00 s32be Creation date
x04 s32be Modification date
x08 s32be Backup date
x0C s32be Access date

Finder information

The first part is the FInfo structure.

x00 c[4] fdType - File type[3]
x04 c[4] fdCreator - File's creator[3]
x08 i16be fdFlags - Finder flag bits[3]
Bit 0 (HFS only) File is on desktop[3]
Bits 1:3 Color coding[3]
Bits 4:5 Reserved[3]
Bit 6 Application available to multiple users[3]
Bit 7 File contains no INIT resources[3]
Bit 8 Finder has loaded bundle resources[3]
Bit 9 Reserved[3]
Bit 10 File contains custom icon[3]
Bit 11 File is a stationary pad[3]
Bit 12 File cannot be renamed by Finder[3]
Bit 13 File has a bundle[3]
Bit 14 File's icon is invisible[3]
Bit 15 (System 7) File is an alias[3]
x0A Point fdLocation - File's location in finder[3]
x00 i16be v - Vertical coordinate (Y)
x02 i16be h - Horizontal coordinate (X)
x0E i16be fdFldr - File's folder[3]

This is followed by the FXInfo structure.

x10 i16be fdIconID - Icon ID number[3]
x12 i16be[3] fdUnused - Reserved[3]
x18 s8 fdScript - Script flag and code[3]
x19 s8 fdXFlags - Reserved[3]
x1A i16be fdComment - Comment ID number[3]
x1C i32be fdPutAway - Home directory ID[3]

Macintosh File Info

x00 i32be Flags
Bit 0 Locked
Bit 1 Protected

ProDOS File Info

x00 i16be Access
x02 i16be File Type
x04 i32be Auxiliary Type

MS-DOS File Info

x00 i16be MS-DOS attributes
Bit 0 Read-only[3]
Bit 1 Hidden[3]
Bit 2 System file[3]
Bit 3 Volume label[3]
Bit 4 Subdirectory[3]
Bit 5 New or modified (archive bit)[3]

AFP short name

The short name, as stored on the AppleTalk Filing Protocol. Arbitrary length string, usually ASCII printable, starting with '!'.[3]

AFP File Info

x00 i32be Flags
Bit 0 Invisible
Bit 1 Multi User
Bit 2 System
Bit 3 Backup Needed

AFP Directory ID

x00 i32be File's directory ID on AFP server

References


MacBinary format

File extensions
.bin or .macbin or .mbin
Magic code
Architecture
binary, Motorola 68000
Operating systems
?: Mac OS
Influences
binary, Motorola 68000

Contents

  1. Contents
  2. Overall layout
  3. Header
    1. CRC calculation
  4. References

Overall layout

The MacBinary is an alternative to the AppleSingle format to transfer Macintosh files to other systems, combining the resource and data forks into a single file.

Header
Data Fork, aligned on 128 bytes
Resource Fork, aligned on 128 bytes
Get Info comment, aligned on 128 bytes

Header

x00 i8 x00 (Version 1: version number[1])
Suggested for file check for MacBinary
x01 i8 Length of filename (1-63)
x02 c[0x3F] Filename
x41 c[4] (FInfo) File type
x45 c[4] (FInfo) File creator
x49 i8 (FInfo) Finder flags
Bit 0 Inited[1][3]
Bit 1 Changed[1], reserved[3]
Bit 2 Busy[1], hasCustomIcon[3]
Bit 3 Bozo[1], isStationary[3]
Bit 4 System[1], nameLocked[3]
Bit 5 Bundle[1], hasBundle[3]
Bit 6 Invisible[1][3]
Bit 7 Locked[1], isAlias[3]
x4A i8 0
Suggested for file check for MacBinary
x4B i16be (FInfo) y position in window
x4D i16be (FInfo) x position in window
x4F i16be (FInfo) window/folder ID
x51 i8 Protected flag bit (low order bit)
x52 i8 0 (Version 3: change for incompatible update to MacBinary I)
Suggested for file check for MacBinary I
x53 i32be Data Fork length
x57 i32be Resource Fork length
x5B i32be File creation date
x5F i32be File modification date
x63 i16be (Version 1 extension) Get Info comment length
x65 i8 (Version 2, FInfo) Finder flags (remaining bits)
Bit 0 isOnDesk[3]
Bits 1:3 color[3]
Bit 4 reserved[3]
Bit 5 requiresSwitchLaunch[3]
Bit 6 isShared[3]
Bit 7 hasNoInits[3]
x66 i32be (Version 3) "mBIN"
Suggested for file check for check for MacBinary III
x6A i8 (Version 3, FXInfo) Script of file [fdScript]
x6B i8 (Version 3, FXInfo) Extended Finder flags [fdXFlags]
x6C c[8] reserved
x74 i32be (Version 2) Unpacked file size or 0
x78 i16be (Version 2) Length of secondary header, must be 0
x7A i8 (Version 2) Version number
x11 Version 2
x12 Version 3
x7B i8 (Version 2) Minimum required version number, x11
x7C i16be (Version 2) CRC of previous 124 bytes
Suggested for file check for check for MacBinary II
x7E i16be reserved

CRC calculation

CRC calculation for the field at offset x7C is done using the CRC16-CCITT algorithm.

Start with x1021.

For each byte, xor the byte shifted by 8.

Do the CRC loop: rotate 8 times, and each time there is a carry, xor x1021 to the result of that rotation.

References


Object Module Format for Apple computers

File extensions
Magic code
Architecture
MOS 6502, WDC 65C816
Operating systems
  • ?: ORCA/M 4.0 (version 0)
  • around 1986: ORCA/M 4.1 (version 1, 8/16-bit)
  • 1986: ProDOS 16, GS/OS
Influences
MOS 6502, WDC 65C816

Contents

  1. Contents
  2. Overall layout
  3. Segment header
  4. Segment record
    1. Records used in all modules
    2. Records used in load modules only
      1. Super-compressed records
    3. Records used in run-time library dictionaries only
    4. Records used in object files only
  5. Expressions
  6. Jump-table segment
    1. Unloaded state
    2. Loaded state
  7. Initialization segment
  8. References

Overall layout

An file in the Object Module Format can be an object (type xB1), library (type xB2) or a load file (types xB3-xBE). The general structure of an OMF file is a sequence of segment headers and segment records.

Segment header 1
Segment record sequence 1
Segment header 2
Segment record sequence 2
...

Library files contain a library dictionary segment.

Load files can contain code, data, direct-page/stack, initialization, jump-table and pathname segments. Each segment contains binary data (LCONST record followed by zerod out DS), followed by a relocation directory (sequence of RELOC, cRELOC, INTERSEG, cINTERSEG, SUPER records).

Run-time library files have type xB4, shell applications have type xB5.

Segment header

Every segment has a segment header. The format and size of the segment has to be determined using this structure. The value at offset x0F provides the version of the segment (each segment in a file can have a different version). The value at x00 will then provide the length of the segment. According to [3], the way that field is interpreted depends on whether it is an executable/object or a library.

x00 i32le (Version 1[1]) BLKCNT - Number of 512 byte blocks in segment, including header
(Version 2[2] and static libraries[3]) BYTECNT - Number of bytes in segment, including header
Offset to next segment data, no alignment required
x04 i32le RESSPC - Number of additional zero bytes to append to segment data (can be replaced via a DS record)
x08 i32le LENGTH - Number of bytes in segment when loaded into memory, including zero bytes of RESSPC
x0C i8 (Version 1[1]) KIND
(Version 2[2]) Reserved
Bits 0:4 Type (version 1)
0x00 Code Segment
0x01 Data Segment
0x02 Jump Table Segment
0x04 Pathname Segment
0x08 Library Dictionary Segment
0x10 Initialization Segment
0x11 Absolute Bank Segment
0x12 Direct Page/Stack Segment
Bit 5 Position independent (version 1)
Bit 6 Private (version 1)
Bit 7
0 Static (version 1)
1 Dynamic (version 1)
x0D i8 LABLEN - Length of all label fields
A value of 0 means a variable length field, the first byte of which specifies the number of characters following
x0E i8 NUMLEN - Length of number fields, must be 4 for Apple IIGS
x0F i8 VERSION - OMF version, currently 1 (version 1.0) and 2 (version 2.0 or 2.1) are valid
x10 i32le BANKSIZE - Maximum bank size of segment, must be power of 2 and ≤ x10000 for Apple IIGS, and a value of 0 permits crossing bank boundaries
x12 i16le (Version 1[1]) Reserved
(Version 2[2]) KIND
Bits 0:4 Type (version 2)
0x00 Code Segment
0x01 Data Segment
0x02 Jump Table Segment
0x04 Pathname Segment
0x08 Library Dictionary Segment
0x10 Initialization Segment
0x12 Direct Page/Stack Segment
Bit 8 Bank-relative (version 2)
Bit 9 Skip segment (version 2)
Bit 10 Reload segment (version 2)
Bit 11 Absolute-bank segment (version 2)
Bit 12 Do not load in special memory (version 2)
Bit 13 Position independent (version 2)
Bit 14 Private (version 2)
Bit 15
0 Static (version 2)
1 Dynamic (version 2)
x14 i16le Reserved
x18 i32le ORG - Absolute address of segment, or 0 if relocatable
x1C i32le ALIGN - Alignment, must be power of 2 and ≤ x10000 for Apple IIGS
Apple IIGS only supports page alignment (x100) and bank alignment (x10000)
x20 i8 NUMSEX, must be 0
0 Little endian
1 Big endian
x21 i8 (Version 1[1]) LCBANK - Bank number to load into, if ORG specifies an address in the Language Card area (banks x00, x01, xE0, xE1)
(Version 2[3]) REVISION - OMF revision number, set to 1 for version 2.1 ([2] claims it is reserved)
x22 i16le (not Version 0[3])SEGNUM - Segment number, must be equal to the index of the segment within the file, starting from 1
x24 i32le (not Version 0[3])ENTRY - Entry point of the segment
x28 i16le (not Version 0[3])DISPNAME - Offset to LOADNAME, typically x2C [2], or x30 for 2.1 [3]
x2A i16le (not Version 0[3])DISPDATA - Offset to the segment data, typically x3A + LABLEN
x2C i32le (optional, Version 2.1[3]) tempOrg[2]

This is then followed by the LOADNAME field, at offset DISPNAME (not Version 0[3]):

x00 c[0xA] LOADNAME, always length 10 - Name of the segment according to linker
x0A c[?] SEGNAME - Name of the segment

Note: [2] calls the field at x0A blockCount which is probably a bug[3].

Segment record

The segment body starts at DISPDATA (stored in Segment header), and it is a sequence of records. The first byte defines the record type. The number fields length NUMLEN and byte ordering NUMSEX, the offsets are indicated with assuming a value of 4, as dictated by Apple IIGS. The label fields have length LABLEN.

Records used in all modules

x00 i8 x00 - END - end of segment

x00 i8 xF1 - DS - inserts a sequence of zero bytes at the current location counter
x01 number Number of zeros to insert

x00 i8 xF2 - LCONST - load absolute data
x01 i32 Number of bytes of data
x05 c[*] Data to be loaded

x00 i8 xFB - General - (Version 2) reserved for Apple Computer, Inc.
xFC-xFF - Experimental - (Version 2)
x01 i32 Number of bytes
x05 c[*] Data

Records used in load modules only

x00 i8 xE2 - RELOC - patches an address within a segment
x01 i8 Number of bytes to relocate
x02 i8 Shift amount to address before patching value; positive values shift to the left, negative values to the right
x03 number Offset to location to patch
x07 number Offset from 0 that should be written

x00 i8 xF5 - cRELOC - compressed RELOC, patches an address within a segment
x01 i8 Number of bytes to relocate
x02 i8 Shift amount to address before patching value; positive values shift to the left, negative values to the right
x03 i16 Offset to location to patch
x05 i16 Offset from 0 that should be written

x00 i8 xE3 - INTERSEG - patches an address between segments
x01 i8 Number of bytes to relocate
x02 i8 Shift amount to address before patching value; positive values shift to the left, negative values to the right
x03 number Offset to location to patch
x07 i16 File number, if a program has only 1 load file, the value is 1
for dynamic segments, this references a file with a jump table segment
x09 i16 Segment number, starting from 1
for dynamic segments, this references a jump table segment
x0B number Offset from 0 that should be written
for dynamic segments, this references a call to the System Loader for that reference

x00 i8 xF6 - cINTERSEG - compressed INTERSEG, patches an address between segments, with file number 1
x01 i8 Number of bytes to relocate
x02 i8 Shift amount to address before patching value; positive values shift to the left, negative values to the right
x03 i16 Offset to location to patch
x05 i8 Segment number, starting from 1
for dynamic segments, this references a jump table segment
x06 i16 Offset from 0 that should be written
for dynamic segments, this references a call to the System Loader for that reference

x00 i8 xF7 - SUPER - (Version 2) A super-compressed relocation-dictionary record
x01 i32 Number of bytes in the rest of the record
x05 i8 Record type
x06 c[*] Lists 16-bit offsets in a sequence of blocks, each block corresonding to that page
x00 i8 x00-x7F - Patch 1-128 offsets, the low bytes given in the following bytes
x81-xFF - Skip 1-128 pages, no following bytes
x01 i8[*] Low bytes of the offsets to patch at, within the same page

Super-compressed records

For super-compressed records, only the addresses of the patches are provided. The way it will be patched depends on the type of the record and the value stored at the address at the time of patching.

Type i8 x00 - SUPER RELOC2, super-compressed RELOC, patches an address within a segment, relocate 2 bytes, bit-shift count of zero
Value i16 Offset from 0 that should be written

Type i8 x01 - SUPER RELOC3, super-compressed RELOC, patches an address within a segment, relocate 3 bytes, bit-shift count of zero
Value i16 Offset from 0 that should be written

Type i8 x02-x0D - SUPER INTERSEG1-SUPER INTERSEG12 - super-compressed INTERSEG, patches an address between segments, with file number 1-12, relocate 3 bytes, bit-shift count of zero
Value i16 Offset from 0 that should be written
for dynamic segments, this references a call to the System Loader for that reference
Value+2 i8 Segment number, starting from 1
for dynamic segments, this references a jump table segment

Type i8 x0E-x19 - SUPER INTERSEG13-SUPER INTERSEG24 - super-compressed INTERSEG, patches an address between segments, with file number 1, segment number 1-12, relocate 2 bytes, bit-shift count of zero
Value i16 Offset from 0 that should be written
for dynamic segments, this references a call to the System Loader for that reference

Type i8 x1A-x25 - SUPER INTERSEG25-SUPER INTERSEG36 - super-compressed INTERSEG, patches an address between segments, with file number 1, segment number 1-12, relocate 2 bytes, bit-shift count of -16 (xF0)
Value i16 Offset from 0 that should be written
for dynamic segments, this references a call to the System Loader for that reference

Records used in run-time library dictionaries only

x00 i8 xF4 - ENTRY - used in the run-time library entry dictionary
x01 i16 Segment number
x03 number Relative location within the load segment of the label
x07 label Label

Records used in object files only

x00 i8 x01-xDF - CONST - load absolute data
x01 c[*] Data to be loaded

x00 i8 xE0 - ALIGN - insert zero bytes to align to boundary
x01 i32 Alignment, must be a power of 2 that is at most ALIGN

x00 i8 xE1 - ORG - moves present location counter
if negative, subsequent writes will overwrite the previous data
x01 number Amount of bytes to move

x00 i8 xE4 - USING - loads the local labels from a data segment for usage
x01 label Segment name

x00 i8 xE5 - STRONG - requires that a segment must be linked, even if it is not referenced
x01 label Segment name

x00 i8 xE6 - GLOBAL - defines a global label at the current position
xEF - LOCAL - defines a local label at the current position
x01 label Label name, of length LABLEN
... i16 Number of bytes generated by the line, or xFFFF if it is greater or equal to xFFFF
... i8 Operation type
'A' Address-type DC statement
'B' Boolean-type DC statement
'C' Character-type DC statement
'D' Double-precision floating-point-type DC statement
'F' Floating-point-type DC statement
'G' EQU or GEQU statement
'H' Hexadecimal-type DC statement
'I' Integer-type DC statement
'K' Reference-address-type DC statement
'L' Soft-reference-type DC statement
'M' Instruction
'N' Assembler directive
'O' ORG statement
'P' ALIGN statement
'S' DS statement
'X' Arithmetic symbolic parameter
'Y' Boolean symbolic parameter
'Z' Character symbolic parameter
... i8 Private flag, designates the code or data segment as private if x01

x00 i8 xE7 - GEQU - defines a global label with expression
xF0 - EQU - defines a local label with expression
x01 label Label name, of length LABLEN
... i16 Number of bytes generated by the line, or xFFFF if it is greater or equal to xFFFF
... i8 Operation type (same as GLOBAL)
... i8 Private flag, designates the code or data segment as private if x01
... expr Expression

x00 i8 xE8 - MEM - reserves a memory range
x01 number Start address
x05 number End address

x00 i8 xEB - EXPR - evaluates an expression and stores its truncated value
xEC - ZEXPR - evaluates an expression and stores its value, making sure the truncated bytes are 0
xED - BEXPR - evaluates an expression and stores its value, making sure the truncated bytes match those of the location counter
xF3 - LEXPR - like EXPR, but if the expression evaluates to a label with fixed, constant offset in a different dynamic code segment, a jump-table segment entry is generated
x01 i8 Size of value in bytes
x02 expr Expression

x00 i8 xEE - RELEXPR - generates a relative branch offset from a location
x01 i8 Size of value in bytes
x02 number Offset of origin of branch
x06 expr Expression

Expressions

TODO (only relevant to object files)

Jump-table segment

The jump-table begins with 8 zero bytes. Afterwards, each jump-table entry is 14 bytes long.

Unloaded state

This is the format stored in files.

x00 i16le User ID, initially 0, filled in after loading
x02 i16le Load-file number, a value of 0 terminates the list
x04 i16le Load-segment number
x06 i32le Load-segment offset
x0A c[4] A long subroutine jump to the load function using JSL, the actual address is filled in after loading

Loaded state

This format is only used for the image in memory.

x00 i16le User ID
x02 i16le Load-file number
x04 i16le Load-segment number
x06 i32le Load-segment offset
x0A c[4] A long jump to the reference using JML

Initialization segment

When encountering an initialization segment, the System Loader transfers control to it. It must then return to the System Loader via a long return RTL instruction. It must also not change the stack pointer, use the current direct page, or reference segments that have not been loaded yet. When an application is restarted, initialization segments are also rerun.

References


Preferred Executable Format (PEF)

File extensions
Magic code
"Joy!"
Architecture
Motorola 68000, PowerPC
Operating systems
  • 1994-03-14: System 7.1.2 for Power Macintosh 6100
  • 1996-01: BeOS Developer Release 6 on PowerPC (replacing ELF)
Influences
Motorola 68000, PowerPC

Hunk executable

File extensions
Magic code
x00x00x03xF3
Architecture
Motorola 68000, PowerPC for WarpUp (1997)
Operating systems
  • 1978: TRIPOS?
  • 1985-07-23: AmigaOS 1.0
  • 1997: WarpOS
  • 2004-04: AmigaOS 4.0 (alongside ELF)
Influences
Motorola 68000, PowerPC for WarpUp (1997)

Contents

  1. Contents
  2. Further work
  3. References

Further work

This format requires documentation.

References


Adam Seychell's DOS32 executable

File extensions
.exe
Magic code
"Adam", "DLL "
Architecture
Intel 80386
Operating systems
  • 1994: Adam Seychell's DOS32 extender
  • ?: WDOSX
  • ?: DX64
Influences
Intel 80386

Contents

  1. Contents
  2. Overall layout
  3. Executable Header
    1. Executable Header for the version 3.5 beta
  4. Relocations
  5. References

Overall layout

Optional MZ stub (DJGPP only)
Executable Header
Executable image
Relocations

Executable Header

x00 c[4] Signature
"Adam" - executable
"DLL " - dynamic linking library
x04 i16le Version number of linker (DLINK), in packed BCD format
x06 i16le Version number of DOS32 required, in packed BCD format
x08 i32le Size of DOS32 executable, without stub
x0C i32le Start of executable image from header start
x10 i32le Size of executable image, start of relocations
x14 i32le Memory required, including executable image
x18 i32le Initial EIP (entry)
x1C i32le Initial ESP (stack)
x20 i32le Number of relocations
x24 i32le Flags
Bit 0 Compressed image
Bit 1 Display DOS32 logo on start
x28 i32le Size of relocations[2], apparently not used

Executable Header for the version 3.5 beta

According to Michael Tippach's research[2], version 3.5 uses a different header format.

x00 c[4] Signature
"Adam" - executable
"DLL " - dynamic linking library
x04 i16le Version number of linker (DLINK), in packed BCD format
x06 i16le Version number of DOS32 required, in packed BCD format
x08 i32le Size of DOS32 executable, without stub
x0C i32le Size of executable image
x10 i32le Start of executable image from header start
x14 i32le Initial EIP (entry)
x18 i32le Memory required, including executable image
x1C i32le Initial ESP (stack)
x20 i32le Start of relocations
x24 i8 Logo color
x25 i8 Logo delay
x26 i8 Flags
Bit 0 Compressed image
Bit 1 Display DOS32 logo on start
Bit 2 Unregistered
x27 i8 =0
x28 i32le =0

Relocations

Each relocation is stored as a 32-bit offset from the executable image start, and addresses a 16-bit word that is the selector of the data segment.

References