amiga-bootcamp/03_loader_and_exec_format/hunk_relocation.md
Ilia Sharin 21751c0025 docs(amiga): complete AmigaOS 3.1/3.2 developer reference — 172 files across 17 sections
Comprehensive technical documentation covering:
- Hardware: OCS/ECS/AGA custom chip registers, Copper & Blitter deep dives
- Boot sequence: cold boot through startup-sequence
- Binary format: HUNK executable spec, relocation, debug info
- Linking & ABI: .fd files, LVO tables, register calling conventions
- Exec kernel: tasks, interrupts, memory, signals, semaphores
- AmigaDOS: file I/O, FFS/OFS layout, CLI/Shell scripting
- Graphics: planar bitmaps, Copper programming, HAM/EHB modes
- Intuition: screens, windows, IDCMP, BOOPSI
- Devices: trackdisk, SCSI, serial, timer, audio, keyboard
- Libraries: utility, expansion, IFFParse, locale, ARexx
- Networking: bsdsocket API, SANA-II, TCP/IP stack comparison
- Toolchain: GCC, vasm/vlink, SAS/C, NDK, debugging
- Reverse engineering: IDA/Ghidra setup, compiler fingerprints, case studies
- CPU & MMU: 68040/060 emulation libs, PMMU, cache management
- Driver development: SANA-II, Picasso96/RTG, AHI audio

All files include breadcrumb navigation. No local paths or proprietary content.
2026-04-23 12:17:35 -04:00

4.6 KiB

← Home · Loader & HUNK Format

HUNK Relocation Mechanics

Overview

Relocation is the process of patching absolute addresses in a loaded executable to reflect its actual memory location. Since AmigaOS allocates memory dynamically, a program cannot know its load address at compile time — all inter-hunk references must be fixed up at runtime.


Why Relocation Is Necessary

An Amiga executable contains references like:

LEA  DataTable(PC), A0   ; PC-relative — no relocation needed
MOVE.L #DataTable, A0    ; Absolute — MUST be relocated

The linker places DataTable at some hunk-relative offset (e.g., offset 0 in the data hunk). The absolute address is only known at load time. The relocation table tells the loader which longwords in the code contain these absolute values.


HUNK_RELOC32 Format

HUNK_RELOC32 ($000003EC)

[Repeat until terminator:]
  <num_offsets>       Number of longword addresses to patch for this target hunk
  <target_hunk>       Index of the hunk whose base address is added
  <offset_0>          Byte offset within the current hunk to patch
  <offset_1>
  ...

<0>                   num_offsets = 0 terminates the reloc list
HUNK_END ($000003F2)

Patching Algorithm

For each entry in HUNK_RELOC32 of hunk H:

foreach (target_hunk, offsets[]):
    base = segment_base_address[target_hunk]
    foreach offset in offsets:
        *(ULONG *)(H_base + offset) += base

The value at H_base + offset already contains the hunk-relative address written by the linker. Adding the actual base produces the final absolute address.

Example

Code hunk references data hunk at two sites:

Before load (raw file values):
  code[0x18] = $00000000   ; linker placed "data offset 0" here
  code[0x2C] = $00000010   ; linker placed "data offset 0x10" here

HUNK_RELOC32:
  num_offsets = 2
  target_hunk = 1           ; data hunk
  offsets = [0x18, 0x2C]

After load (data hunk loaded at $20000):
  code[0x18] = $00000000 + $20000 = $00020000
  code[0x2C] = $00000010 + $20000 = $00020010

HUNK_RELOC16 and HUNK_RELOC8

Same format as HUNK_RELOC32 but patch 16-bit or 8-bit values:

  • HUNK_RELOC16 ($3ED): patches UWORD at offset
  • HUNK_RELOC8 ($3EE): patches UBYTE at offset

These are rare in practice — the 68000 requires even-aligned word accesses and only supports 16-bit displacement in most addressing modes.


HUNK_DREL32 — Short Relocation (32-bit)

HUNK_DREL32 ($3F7) is an alternative relocation format used by some linkers (e.g., BLink) for smaller reloc tables:

HUNK_DREL32

[Repeat:]
  <num_offsets>  (WORD, not LONGWORD)
  <target_hunk>  (WORD)
  <offset_0>     (WORD)
  ...

<0>              terminator

By using 16-bit values, this format is more compact for programs with many relocations and small hunk sizes (<64 KB). AmigaOS InternalLoadSeg supports both formats.


PC-Relative References (No Relocation Needed)

The 68020+ supports PC-relative addressing with 32-bit displacements:

LEA  symbol(PC), A0    ; PC-relative load effective address
MOVE.L  data(PC), D0   ; PC-relative data read

PC-relative references do not require relocation — the offset is relative to the instruction, so it is valid regardless of where the code is loaded. GCC for 68k generates PC-relative code by default (-fpic), significantly reducing the size of relocation tables.

SAS/C generates absolute references by default and relies heavily on HUNK_RELOC32.


Relocation at Runtime — Segment Chain

The loader tracks loaded segments as a BPTR chain (singly-linked list). The segment list head is returned by LoadSeg():

Segment 0 (code):
  BPTR → Segment 1
  [code data]

Segment 1 (data):
  BPTR → 0 (NULL)
  [data]

Each segment begins with a 4-byte BPTR to the next segment. Hunk index n corresponds to segment n in this chain.


Viewing Relocations with Tools

IDA Pro

After loading a HUNK file with the Amiga plugin, IDA resolves relocations automatically. The fixup table is visible in View → Open Subviews → Fixups.

hexdump + manual

Locate HUNK_RELOC32 ($3EC) in raw hex:

xxd mybinary | grep "0003 ec"

Then read num_offsets and target_hunk longwords that follow.

hunkinfo (custom tool)

hunkinfo mybinary    # shows all hunks, sizes, reloc counts

References