Hunk Object and Link-Library Format¶
An object file is the intermediate output of a compiler or assembler: one per translation unit, with unresolved external references left intact. A link library is a collection of object files used by a linker to resolve those references; functions from a link library are copied into the final executable at link time (unlike AmigaOS run-time libraries, which stay on disk and are shared via OpenLibrary()).
Both use a subset of the executable Hunk format with extensions:
HUNK_UNITto delimit translation units.HUNK_RELOC16/HUNK_RELOC8for short PC-relative relocations (object files only).HUNK_DRELOC32/16/8for base-register-relative relocations into__MERGEDsegments.HUNK_EXTfor external symbol definitions and references.HUNK_LIB/HUNK_INDEXfor indexed link libraries.
Object files have no
HUNK_HEADER. Memory attributes are encoded in the top two bits of each hunk type instead. The bit combinations00/01/10correspond toMEMF_ANY/MEMF_CHIP/MEMF_FAST. The combination11is undocumented; the manual recommends using it as an extension hook for an explicit memory type in the next long-word, mirroringHUNK_HEADER's layout.
Object file layout¶
[ HUNK_UNIT ] — translation-unit header (name in long-words)
[ HUNK_NAME ] optional
2 bits mt — memory type
30 bits h — hunk type
[HUNK_CODE | HUNK_DATA | HUNK_BSS] — segment body, depending on `h`
do {
[HUNK_RELOC32 | RELOC16 | RELOC8
| RELOC32SHORT | RELRELOC32
| DRELOC32 | DRELOC16 | DRELOC8
| EXT | SYMBOL | DEBUG]
…until HUNK_END
}
repeat until EOF
HUNK_UNIT — translation-unit identifier¶
struct {
LONG hn_longs; /* length of name, in long-words */
LONG hn_name[hn]; /* the name, zero-padded to long-word boundary */
};
The name is typically the source file name; most linkers ignore it. Required as the first hunk of every object file. Not present in libraries or executables.
HUNK_NAME — segment naming¶
In object and library files, segment names drive the merging logic of the linker. Two segments with identical names (across object files and library members) are merged into one segment in the final executable. Special names:
| Name | Effect |
|---|---|
__MERGED |
Segment addressed via a base register (small-data model). Compiler uses one address register (usually a4) loaded to the segment base, with 32K offset to allow ±32K addressing. |
_NOMERGE |
Never merged with anything, regardless of small/large model. |
NTRYHUNK |
Becomes the first segment of the final executable — required for the overlay manager, which must run first. |
text |
Conventional name for code+constant data. |
data |
Conventional name for non-constant data in the large data model. |
udata |
Conventional name for BSS in the large data model. |
chip |
Conventional name for MEMF_CHIP data. |
The memory type is not implied by the name — mt in the hunk type header remains the source of truth.
HUNK_RELOC16 / HUNK_RELOC8¶
Both follow the same format as HUNK_RELRELOC32 (32-bit offsets, but pointing at 16- or 8-bit elements). They are used for short PC-relative branches in object files; the loader itself does not handle them, only the linker does. For the linker to resolve them, the referencing and target segments must be merged (identical HUNK_NAME).
If the merged segment still exceeds the displacement range, linkers may emit an automatic link vector (ALV) — a small intermediate stub that performs an absolute jump. ALVs work for code jumps but not for PC-relative data accesses. Avoid 16- or 8-bit references to data across translation units.
HUNK_DRELOC32 / HUNK_DRELOC16 / HUNK_DRELOC8¶
Same wire format as HUNK_RELOC32. Operands are 32-, 16-, or 8-bit displacements relative to a base register (typically a4) at the segment base of __MERGED. Used when the small-data model moves static data through a base register.
The 68K's 16-bit base-relative addressing mode limits __MERGED to 64K total. Linkers handle the 32K boundary by adjusting the base register 32K into the segment and applying a -32K offset to all r0 entries.
HUNK_EXT — external symbol definitions and references¶
This hunk is what makes an object file unresolved. It carries both definitions (symbols this unit provides) and references (symbols this unit needs from elsewhere).
struct {
BYTE st; /* symbol type, see table below */
UBYTE sl; /* length of name in long-words (24 bits!) */
LONG sn[sl]; /* name, zero-padded to long-word boundary */
/* For definitions (st < 0x80): one LONG sv (symbol value) */
/* For common references (st == 0x82 or 0x89): one LONG sc (size of common block in bytes) */
/* For other references: one LONG sn (number of references), then so[] (offsets into segment) */
} [];
The array terminates when an entry has sl == 0.
Symbol types¶
Bit 7 of st selects definitions (clear) or references (set):
st |
Class | Meaning |
|---|---|---|
EXT_SYMB 0x00 |
Definition | sv + ma[i] is the address of the symbol. (HUNK_SYMBOL-style debug info only.) |
EXT_DEF 0x01 |
Definition | sv + ma[i] is the address; references become HUNK_RELOC32 to segment i. |
EXT_ABS 0x02 |
Definition | sv is the absolute value, substituted into references verbatim. |
EXT_RES 0x03 |
Definition | Obsolete (dynamic-library runtime binding). |
EXT_REF32 0x81 |
Reference | 32-bit, resolved by EXT_DEF or EXT_ABS. |
EXT_COMMON 0x82 |
Reference | Like EXT_REF32, but if no definition is found the linker allocates BSS space for the largest referenced size. (FORTRAN common blocks; SAS/C header-include guard pattern.) |
EXT_REF16 0x83 |
Reference | 16-bit PC-relative; target segment must be merged. |
EXT_REF8 0x84 |
Reference | 8-bit PC-relative; same segment. |
EXT_DREF32/16/8 0x85–0x87 |
Reference | Base-register-relative references to __MERGED. |
EXT_RELREF32 0x88 |
Reference | 32-bit PC-relative; generates a HUNK_RELRELOC32. |
EXT_RELCOMMON 0x89 |
Reference | Like EXT_COMMON, but emits a HUNK_RELRELOC32. |
EXT_ABSREF16/8 0x8a/0x8b |
Reference | 16/8-bit absolute value. |
Link libraries¶
Link libraries come in two forms:
Non-indexed (old style)¶
A simple concatenation of object files. Join is sufficient to produce one. Slow: the linker must scan the whole file to find a single symbol.
Indexed¶
[ HUNK_LIB ] payload of compiled object units
[ HUNK_INDEX ] compressed symbol/hunk index
… (repeat)
The pair is bounded by <2^16 long-words of payload. Larger libraries use multiple HUNK_LIB / HUNK_INDEX pairs.
HUNK_LIB¶
Carries the actual code/data hunks. Differences from a plain object file:
- No
HUNK_UNIT(the unit name lives inHUNK_INDEX). - No
HUNK_NAME(the segment name lives inHUNK_INDEX). - No
EXT_DEF,EXT_ABS, or other definitions (the symbol table lives inHUNK_INDEX). References —st ≥ 0x80— are retained.
Memory type mt is encoded the same way as in object files (top two bits of the hunk type).
HUNK_INDEX¶
struct {
/* String table */
UWORD sl; /* byte length of string table (must be even) */
UBYTE strings[sl]; /* NUL-terminated C strings, the first being "" */
/* Per-unit entries, until end-of-hunk sentinel */
UWORD uo; /* byte offset of unit name into string table */
UWORD ho; /* long-word offset of first hunk of unit within HUNK_LIB */
UWORD hc; /* number of segments in unit */
for (each segment) {
UWORD hn; /* byte offset of hunk name */
UWORD hl; /* abbreviated hunk size, in long-words */
UBYTE mt:2; /* memory type */
UWORD h:14; /* abbreviated hunk type */
UWORD xc; /* number of references */
for (each reference) {
UWORD xn; /* byte offset of reference name */
}
UWORD dc; /* number of definitions */
for (each definition) {
UWORD dn; /* byte offset of defined name */
WORD sv; /* low 16 bits of symbol value */
UBYTE au; /* bits 23..16 of EXT_ABS value */
bit 0; /* always 0 (definition marker) */
bit as; /* sign bit + bits 30..24 of EXT_ABS value */
UBYTE st:6;/* low 6 bits of EXT type (always definition: bit 7 = 0) */
}
}
};
Limitations of the indexed format:
- Address symbols are restricted to 16 bits within a hunk (64K max) — fine for service functions, restrictive for low-level code.
EXT_ABSsymbol values fit in 32 bits (-2^24 + 1to2^24 - 1) — enough for Amiga custom-chip register addresses.EXT_COMMONandEXT_RELCOMMONcannot be represented.- Reference types (the
stbyte) are not in the index; they remain in the correspondingHUNK_EXTofHUNK_LIB.
The string table is the deduplicated union of all unit names, segment names, reference names, and definition names. The first entry must be the empty string (offset 0), enabling unnamed hunks.
See Also¶
- AmigaDOS Hunk Binary Format
- AmigaOS Hunk Overlays
- Hunk Version and Stack Cookies
- SAS/C Compiler Reference
Sources: Thomas Richter, "ROM Kernel Reference Manual: AmigaDOS" (First Edition, 2024), Chapter 11.6–11.7 — Object File Format and Link Library File Format; Ralph Babel, "The Amiga Guru Book" (1993), Chapter 22.
Raw: raw/rkm/rkm-dos-book.md; raw/rkm/guru-book.md
Updated: 2026-10-02