This page describes the 32-bit a.out of the BSDs, as given by FreeBSD’s
a.out(5) manual page and its <sys/imgact_aout.h> header.
The older 16-bit PDP-11 form is on the
Seventh Edition page; relocations and symbols are on
relocations and symbols. a.out has no
signature beyond its magic number and no version field.
Layout
A file has up to seven parts, in this order. Only the header is required.
| Part | Size | Offset (macro) |
|---|---|---|
| exec header | 32 bytes | 0 |
| text segment | a_text | N_TXTOFF |
| data segment | a_data | N_DATOFF |
| text relocations | a_trsize | N_RELOFF |
| data relocations | a_drsize | N_RELOFF + a_trsize |
| symbol table | a_syms | N_SYMOFF |
| string table | its first 4 bytes | N_STROFF |
The exec header
Eight unsigned 32-bit fields. The byte order depends on the machine (see
a_midmag).
| Offset | Size | Field | Meaning |
|---|---|---|---|
0x00 | 4 | a_midmag | Flags, machine ID and magic number: flags << 26 | mid << 16 | magic. |
0x04 | 4 | a_text | Size of the text segment in bytes. |
0x08 | 4 | a_data | Size of the initialised data segment in bytes. |
0x0C | 4 | a_bss | Bytes of zero-filled memory after the data; it sets the initial break (brk(2)). |
0x10 | 4 | a_syms | Size of the symbol table in bytes. |
0x14 | 4 | a_entry | Address where execution starts after loading. |
0x18 | 4 | a_trsize | Size of the text relocation table in bytes. |
0x1C | 4 | a_drsize | Size of the data relocation table in bytes. |
a_midmag
| Bits | Field | Read with |
|---|---|---|
| 0–15 | magic number | N_GETMAGIC |
| 16–25 | machine ID | N_GETMID |
| 26–31 | flags | N_GETFLAG |
FreeBSD stores the word little-endian and also has _NET versions of the
macros that read it big-endian (network order); a ZMAGIC number in network order is
recognised and read that way. The manual notes that not every architecture uses
a_midmag, so the machine cannot always be told from the header.
Magic numbers
| Name | Octal | Hex | Meaning |
|---|---|---|---|
OMAGIC | 0407 | 0x107 | “Old impure format”: text and data follow the header with no gaps and are both loaded into writable memory. |
NMAGIC | 0410 | 0x108 | Read-only text: text and data are contiguous in the file, text is read-only, and data is loaded at the next page boundary. |
ZMAGIC | 0413 | 0x10B | Demand-load format: header, text and data are each padded to whole pages, and pages are loaded as they are needed. Text pages are read-only, data pages writable. |
QMAGIC | 0314 | 0xCC | “Compact” demand-load format: the header is part of the first text page (the text starts at file offset 0). |
N_BADMAG is true when the magic number, in either byte order, is none of
these four.
Machine IDs
| Value | Name | Machine |
|---|---|---|
0 | MID_ZERO | unknown, implementation-dependent |
1 | MID_SUN010 | Sun 68010/68020 |
2 | MID_SUN020 | Sun 68020 only |
134 | MID_I386 | i386 BSD |
138 | MID_SPARC | SPARC |
143 | MID_ARM6 | ARM6 |
200 | MID_HP200 | HP 200 (68010) BSD |
300 | MID_HP300 | HP 300 (68020 + 68881) BSD |
0x20B | MID_HPUX800 | HP 800, HP-UX |
0x20C | MID_HPUX | HP 200/300, HP-UX |
Other BSDs define further IDs; this list is FreeBSD’s.
Flags
| Value | Name | Meaning |
|---|---|---|
0x10 | EX_PIC | Contains position-independent code (set by as -k, kept by ld). |
0x20 | EX_DYNAMIC | Contains run-time link-edit information: needs the run-time linker. |
0x30 | EX_DPMASK | Mask for both. Both set: a position-independent executable such as a shared library, loaded by the run-time linker. |
Offsets and addresses
FreeBSD’s macros, where PG is the linker page size
(__LDPGSZ, which depends on the machine) and ALIGN(x)
rounds x up to a multiple of PG for ZMAGIC and QMAGIC files
and leaves it alone otherwise:
| Macro | Value |
|---|---|
N_TXTOFF | PG for ZMAGIC; 0 for QMAGIC (and network-order ZMAGIC); 32, the header size, otherwise |
N_DATOFF | ALIGN(N_TXTOFF + a_text) |
N_RELOFF | ALIGN(N_DATOFF + a_data) |
N_SYMOFF | N_RELOFF + a_trsize + a_drsize |
N_STROFF | N_SYMOFF + a_syms |
N_TXTADDR | For OMAGIC, NMAGIC and ZMAGIC: 0 if a_entry < a_text, otherwise a_entry & ~PG; for others, PG. (The header’s own comment: “This can not be done right.”) |
N_DATADDR | ALIGN(N_TXTADDR + a_text) |
Example
The first word of a dynamically linked i386 ZMAGIC program, built from the macros above:
flags 0x20 (EX_DYNAMIC) << 26 0x80000000
mid 134 (MID_I386) << 16 0x00860000
magic ZMAGIC 0x0000010B
a_midmag 0x8086010B stored little-endian: 0B 01 86 80
Sources
- a.out(5) – FreeBSD manual page: layout,
struct exec, magic numbers and loading conventions, flags, macros - sys/imgact_aout.h – FreeBSD source: field types, bit layout of
a_midmag, magic, machine ID and flag values, offset and address macros