- Influences
- DEC PDP-11, DEC VAX, Motorola 68000, Intel 386 and others (Interdata 7/32, IBM 370, MIPS, SPARC)
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
- Contents
- Header
- 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
- Contents
- Overall layout
- File header
- ECOFF file header
- XCOFF64 file header
- Optional header
- 3B20 optional header
- NS32000 fields
- Concurrent DOS additional fields
- GNU_AOUT header fields
- Additional optional header fields for MIPS
- ECOFF optional header
- XCOFF32 additional fields
- XCOFF64 format
- Section header
- ECOFF section header
- XCOFF64 section header
- Relocation information
- Concurrent DOS 68K relocation information
- Line numbers
- Symbol table
- String table
- Further work
- References
Overall layout
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
- Contents
- Header
- Header extension
- Segment table
- Further work
- 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
- Contents
- Further work
- 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
- Contents
- Notes on the format
- Overall layout
- ELF header
- Program header
- Section header
- Symbol table
- OS/2 resource file format
- Resource collection array entry
- Resource collection
- OS/2 operating system information (.osinfo)
- OS/2 import table (.imports)
- OS/2 export table (.exports)
- BeOS Developer Release 4 resources
- Segment contents
- Dynamic linking
- Further work
- 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
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 | i32 | i64 |
e_entry, virtual address of entry point |
x1C | x20 | i32 | i64 |
e_phoff, offset to Program header in bytes from file start |
x20 | x28 | i32 | i64 |
e_shoff, offset to Section header in bytes from file start |
x24 | x30 | i32 |
e_flags, processor specific flags |
x28 | x32 | 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 |
x2A | x34 | 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 |
x2C | x36 | i16 |
e_phnum, number of entries in Program header |
x2E | x38 | 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 |
x30 | x3A | 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 |
x32 | x3C | 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] |
|
x04 | x08 | i32 | i64 |
p_offset, offset to data from start of file |
x08 | x10 | i32 | i64 |
p_vaddr, virtual address to load at |
x0C | x18 | i32 | i64 |
p_paddr, physical address to load at, unused for System V executables and shared objects |
x10 | x20 | i32 | i64 |
p_filesz, number of bytes in the file image |
x14 | x28 | i32 | i64 |
p_memsz, number of bytes in the memory image |
x18 | | i32 | |
p_flags, see above |
x1C | x30 | i32 | i64 |
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 | i32 | i64 |
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] |
|
x0C | x10 | i32 | i64 |
sh_addr, address at which section should appear, or 0 |
x10 | x18 | i32 | i64 |
sh_offset, offset to section data from start of file; a section of type SHT_NOBITS will contain a conceptual offset |
x14 | x20 | i32 | i64 |
sh_size, size of section in bytes; unless sh_type is SHT_NOBITS, this many bytes appear in the file |
x18 | x28 | i32 |
sh_link |
x1C | x2C | i32 |
sh_info |
x20 | x30 | i32 | i64 |
sh_addralign, alignment constraint, 0 or 1 mean no alignment, otherwise it must be a power of 2 |
x24 | x38 | i32 | i64 |
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 |
x0C | x04 | 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] |
|
|
x0D | x05 | i8 |
st_other
Bits 0:1 |
st_visibility
x00 |
STV_DEFAULT |
x01 |
STV_INTERNAL |
x02 |
STV_HIDDEN |
x03 |
STV_PROTECTED |
|
|
x0E | x06 | 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
- Contents
- Program Information
- 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
- Contents
- Overall layout
- Binary record
- Transfer address record
- Terminating record
- 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]
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
- Contents
- Overall layout
- Executable Header
- Relocation information
- References
Overall layout
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
- Contents
- Overall layout
- Executable Header
- RSX record
- References
Overall layout
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
- Contents
- Overall layout
- Executable Header
- SRTL identifier
- Shared run-time library group
- FASTLOAD group
- Relocation data
- RSX index
- CP/M-86 runtime layout
- 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
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)
|
x51 | c[9] |
(FlexOS only): File is in fast load format
|
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:
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
- Contents
- Overall layout
- Header
- CP/M-68K and Concurrent DOS 68K header for contiguous executables
- CP/M-68K non-contiguous executables
- Header for early versions of GEMDOS
- Atari TOS header
- Human68k .Z header
- Symbol Table
- Relocation Table
- CP/M-68K relocations
- Crunched relocations
- GEMDOS/Atari TOS relocations
- Human68k relocations
- 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
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
- Contents
- Overall layout
- Executable Header
- Segment Information Array
- Relocation Data
- Symbol Table
- References
Overall layout
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
- Contents
- Overall layout
- Executable Header
- Relocation Table
- Symbol Table
- References
Overall layout
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
- Contents
- Overall layout
- EXE Header
- Relocation Table
- Program Information
- References
Overall layout
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
- Contents
- Overall layout
- Segmented EXE Format
- Segmented EXE Header
- Segment Table
- Resource Table
- Windows resource table
- OS/2 resource table
- Resident Name Table
- Module Reference Table
- Imported Name Table
- Entry Table
- Normal entries
- Constant
- Moveable entries
- Non-Resident Name Table
- Segment Data
- Relocations
- Internal reference to a fixed segment
- Internal reference to a movable segment
- Import by ordinal
- Import by name
- OSFIXUP
- References
Overall layout
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.
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 |
|
Bit 4 |
|
Bit 5 |
|
Bit 6 |
|
Bit 7 |
|
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.
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
|
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
Import by 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, FJARQQ — wait; DS: esc turns into int x3C; byte x18-x1F by adding xFE32 and x4000 respectively |
0x0002 |
FISRQQ, FJSRQQ — wait; SS: esc turns into int x3C; byte x58-x5F by adding x0632 and x8000 respectively |
0x0003 |
FICRQQ, FJCRQQ — wait; CS: esc turns into int x3C; byte x98-x9F by adding x0E32 and xC000 respectively |
0x0004 |
FIERQQ — wait; ES: esc turns into int x3C by adding x1632 |
0x0005 |
FIDRQQ — wait; esc turns into int x34-x3B by adding x5C32 |
0x0006 |
FIWRQQ — nop; wait turns into int x3D by adding xA23D |
— |
FIFRQQ, FJFRQQ — wait; FS: esc[4] |
— |
FIGRQQ, FJGRQQ — wait; 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
- Contents
- Overall layout
- Old-style EXE header and executable
- Linear Executable Module Header
- Loader Section
- Object Table
- Object Page Table
- Object Iterated Page Table
- Resource Table
- Resident Name Table
- Entry Table
- Unused entry
- 16-bit entry
- 286 call gate entry
- 32-bit entry
- Forwarder entry
- Module Format Directives Table (optional)
- Resident Directives Data Table (optional)
- Per-Page Checksum
- Fixup Section (resident)
- Fixup Page Table
- Fixup Record Table
- Internal reference
- Imported reference by ordinal
- Imported reference by name
- Internal reference via entry table
- Internal chaining fixups
- Import Module Name Table
- Import Procedure Name Table
- Data Section
- Iterated data pages
- Non-Resident Name Table
- Non-Resident Directives Data
- Debug Section
- References
Overall layout
Old-style EXE header and executable
A linear executable file starts with an MZ stub program, with the following additional or modified field.
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
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 |
|
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 |
|
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:
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:
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:
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:
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
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
|
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
|
Bit 5 |
Additive value width
|
Bit 6 |
Object number/module ordinal number width
|
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 |
x03 | x< | 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
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
- Contents
- Overall layout
- MS-DOS stub
- Signature
- COFF File Header
- Optional header
- Optional header standard fields
- Optional header Windows-specific fields
- Optional header data directories
- Section header
- Section data
- .debug section
- .drectve section
- Export (.edata) section
- Export address table
- Export name pointer table
- Export ordinal table
- Export name table
- Import (.idata) section
- Import directory table
- Import lookup table
- Hint/name table
- Import address table
- .pdata section
- Base relocation table (.reloc) section
- Base relocation block
- .tls section
- Load configuration section
- .rsrc section
- Resource directory table
- Resource directory strings
- Resource data description
- Resource data
- .cormeta section
- .sxdata section
- COFF relocations
- COFF line numbers
- COFF symbol table
- Auxiliary symbols
- COMDAT sections
- CLR token definition
- COFF string table
- Attribute certificate table
- Delay-load import tables
- 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
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
x1C | x18 | i32le | i64le |
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 | i32le | i64le |
Size of stack to reserve |
x4C | x50 | i32le | i64le |
Size of stack to commit |
x50 | x58 | i32le | i64le |
Size of heap to reserve |
x54 | x60 | i32le | i64le |
Size of heap to commit |
x58 | x68 | i32le |
Loader flags, 0 |
x5C | x6C | 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
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
- Contents
- Overall layout
- Executable stub and loader
- Header
- Relocations
- 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
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
- Contents
- Overall layout
- Executable stub and loader
- Module Header
- DOS-style 'BW' header
- Additional fields in header
- GDT image
- Additional fields, inside GDT image
- Old run-time selectors
- GDT data
- Relocation data
- RSI-1
- RSI-2
- 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.
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.
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
- Contents
- Overall layout
- Header
- Segment Table
- Needing more information
- 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
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
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
- Contents
- Overall layout
- Flat model
- Multi-segmented model
- Header
- Segment Information Table
- Relocation Table
- Run-time Parameter Block
- Symbol Table
- Symbol Table Header
- Segment Symbol Table
- Public Symbol Table
- Intel Task State Segment
- 16-bit Task State Segment
- 32-bit Task State Segment
- Descriptor Tables
- Intel Global Descriptor Table
- Intel Interrupt Descriptor Table
- Intel Local Descriptor Table
- Borland Debug Information
- 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)
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.
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
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
- Contents
- Overall layout
- Resource header
- Resource data
- Resource map
- Resource type list
- Reference list
- Resource name list
- 'CODE' resources
- Runtime view
- Jump table entries
- Near model jump table
- Far model jump table
- CFM-68K jump table
- Format of near 'CODE' segments
- Format of far 'CODE' segments
- Format of CFM-68K 'CODE' segments
- 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
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
Resource type list
Each type has the following format.
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
- Contents
- Overall layout
- Header
- Data fork
- Resource fork
- Real name
- Comment
- Icon, B&W
- Icon, color
- File Info
- Macintosh
- A/UX File Info
- MS-DOS File Info
- ProDOS File Info
- File Dates Info
- Finder information
- Macintosh File Info
- ProDOS File Info
- MS-DOS File Info
- AFP short name
- AFP File Info
- AFP Directory ID
- 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
|
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
A/UX File Info
MS-DOS File Info
ProDOS File Info
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
- Contents
- Overall layout
- Header
- CRC calculation
- 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
|
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
- Contents
- Overall layout
- Segment header
- Segment record
- Records used in all modules
- Records used in load modules only
- Super-compressed records
- Records used in run-time library dictionaries only
- Records used in object files only
- Expressions
- Jump-table segment
- Unloaded state
- Loaded state
- Initialization segment
- 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.
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
- Contents
- Further work
- 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
- Contents
- Overall layout
- Executable Header
- Executable Header for the version 3.5 beta
- Relocations
- References
Overall layout
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