After the text and data of a BSD a.out file come the text and data relocation
tables, the symbol table and the string table, at the offsets given on the
header page. Sizes below assume a 32-bit
machine, where int and long are 4 bytes.
Relocation entries
Each entry (struct relocation_info, 8 bytes) is an address word and a
word of bit fields, in this order:
| Field | Bits | Meaning |
|---|---|---|
r_address | 32 (an int) | Byte offset of the pointer to fix, from the start of the text segment (text relocations) or the data segment (data relocations). The value already there is added to the new value. |
r_symbolnum | 24 | If r_extern is set, the ordinal number of a symbol (not a byte offset). Otherwise an n_type value naming the segment the pointer refers to. |
r_pcrel | 1 | The pointer is PC-relative. |
r_length | 2 | log₂ of the pointer size: 0 one byte, 1 two bytes, 2 four bytes. |
r_extern | 1 | The relocation uses a symbol’s address. Clear: a local relocation that follows the segments’ load addresses. |
r_baserel | 1 | Relocate to an offset in the Global Offset Table, which holds the symbol’s address at run time. |
r_jmptable | 1 | Relocate to an offset in the Procedure Linkage Table. |
r_relative | 1 | Relative to the image’s load address at run time; only in shared objects. |
r_copy | 1 | The run-time linker copies the symbol’s contents from a shared object to r_address. |
The bit fields add up to 32 bits. Their bit positions inside the word follow the C compiler’s bit-field order for the machine, which the manual page does not state.
Symbol entries
The symbol table is an array of struct nlist (12 bytes on disk):
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 4 | n_strx | Byte offset of the name in the string table. (In memory, nlist(3) replaces it with a pointer, n_name.) |
4 | 1 | n_type | Type and external bit, below. |
5 | 1 | n_other | Low 4 bits: AUX_OBJECT (1, data object) or AUX_FUNC (2, function), used by ld for dynamic executables. |
6 | 2 | n_desc | For debuggers; passed through by the linker unchanged. |
8 | 4 | n_value | The value: an address for text, data and BSS symbols. |
n_type
| Value | Name | Meaning |
|---|---|---|
0x01 | N_EXT | External (global) bit, ORed in: the symbol can be referred to from other files. |
0x1E | N_TYPE | Mask for the type bits the linker uses. |
0xE0 | N_STAB | Mask for debugger symbols; any of these bits set makes it a stab. |
0x00 | N_UNDF | Undefined: the linker must find a definition. If none is found and n_value is non-zero, it is a common symbol and the linker allocates that many BSS bytes (the largest size wins). |
0x02 | N_ABS | Absolute; not changed by the linker. |
0x04 | N_TEXT | Text address; updated when files are merged. |
0x06 | N_DATA | Data address; updated when files are merged. |
0x08 | N_BSS | BSS address; has no file offset. |
0x0A | N_INDR | Alias definition. |
0x0C | N_SIZE | Pseudo-type giving a symbol’s size. |
0x12 | N_COMM | Common reference. |
0x14 | N_SETA | Absolute set element (GNU extension). |
0x16 | N_SETT | Text set element (GNU). |
0x18 | N_SETD | Data set element (GNU). |
0x1A | N_SETB | BSS set element (GNU). |
0x1C | N_SETV | Pointer to a set vector in the data area (GNU). |
0x1E | N_FN / N_WARN | With N_EXT set (0x1F): a file name marker placed before a file’s symbols, for debuggers. Without it: a warning message. |
Stab types
Debugging entries have a value in the N_STAB bits; the whole
n_type byte then gives the kind of entry:
| Value | Name | Meaning | Value | Name | Meaning |
|---|---|---|---|---|---|
0x20 | N_GSYM | global symbol | 0x82 | N_BINCL | include file beginning |
0x22 | N_FNAME | F77 function name | 0x84 | N_SOL | included source file name |
0x24 | N_FUN | procedure name | 0xA0 | N_PSYM | parameter variable |
0x26 | N_STSYM | data segment variable | 0xA2 | N_EINCL | include file end |
0x28 | N_LCSYM | BSS segment variable | 0xA4 | N_ENTRY | alternate entry point |
0x2A | N_MAIN | main function name | 0xC0 | N_LBRAC | left bracket (scope start) |
0x30 | N_PC | global Pascal symbol | 0xC2 | N_EXCL | deleted include file |
0x40 | N_RSYM | register variable | 0xE0 | N_RBRAC | right bracket (scope end) |
0x44 | N_SLINE | text segment line number | 0xE2 | N_BCOMM | begin common |
0x46 | N_DSLINE | data segment line number | 0xE4 | N_ECOMM | end common |
0x48 | N_BSLINE | BSS segment line number | 0xE8 | N_ECOML | end common (local name) |
0x60 | N_SSYM | structure or union element | 0xFE | N_LENG | length of preceding entry |
0x64 | N_SO | main source file name | |||
0x80 | N_LSYM | stack variable |
What n_desc and n_value hold for each stab is defined by
stab(5) and the debuggers; it is not covered here.
String table
Starts with an unsigned 32-bit length of the whole table, counting the length field itself, followed by the symbol names, each ending in a zero byte. The first name therefore starts at offset 4.
Sources
- a.out(5) – FreeBSD manual page:
relocation_info,nlist,n_typemeanings, string table - sys/sys/nlist_aout.h – FreeBSD source:
n_typeandAUX_values - include/stab.h – FreeBSD source: stab type values