amiga-bootcamp/04_linking_and_libraries/link_libraries.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

5.3 KiB

← Home · Linking & Libraries

AmigaLib Static Linking

Overview

AmigaOS programs are linked against a set of static libraries that provide startup code, C runtime stubs, and glue for OS entry points. The linker resolves all external symbols at link time and produces a self-contained HUNK-format executable.


Key Static Libraries (NDK39 / SAS/C)

Library Purpose
amiga.lib OS stub functions — OpenLibrary, AllocMem, etc. for non-inline linking
sc.lib / c.lib SAS/C runtime: printf, malloc, strlen, standard I/O
auto.lib Auto-open libraries (DOSBase, SysBase acquisition)
debug.lib kprintf, dprintf serial debugging stubs
m.lib Math library (software floating point)
scm68020.lib SAS/C math for 68020 (co-processor stubs)

For GCC:

Library Purpose
libnix C runtime for m68k-amigaos-gcc — replaces sc.lib
libamiga OS glue for GCC (NDK-based)
libm Soft-float math
libgcc GCC internal helpers (division, etc.)

Startup Object: c.o / _start

Every AmigaOS C program begins execution at the first word of segment 0 — not at main(). The startup object c.o (SAS/C) or crt0.o (GCC/libnix) is always linked first and provides:

;; SAS/C c.o skeleton (simplified)
_start:
    MOVE.L  4.W, A6              ; SysBase from absolute location $4
    MOVE.L  A0, _CommandStr      ; raw CLI argument string (from dos.library)
    MOVE.L  A1, _WBenchMsg       ; WBStartup message (if WB launch, else NULL)
    JSR     __main               ; C runtime init → eventually calls main()
    ; D0 = exit code from main()
    MOVE.L  D0, _rc              ; save return code
    JSR     __exit               ; C runtime cleanup
    RTS                          ; return to dos.library

What __main Does

  1. Opens DOSBase via OpenLibrary("dos.library", 0) using SysBase in A6
  2. Sets up stdin/stdout/stderr file handles (wraps dos.library I/O)
  3. Allocates C heap (if any static malloc/new usage)
  4. Initializes errno, _timezone, __ProgramName
  5. Calls any registered __constructor functions (C++ static init)
  6. Calls main(argc, argv) — argument string is parsed from _CommandStr
  7. Calls exit(return_code) → runs atexit() handlers → CloseLibrary(DOSBase)

WBStartup Glue

When launched from Workbench (double-click), A0 = NULL, A1 = WBStartup msg ptr. The startup code must:

/* standard WB detection in __main / startup */
if (_WBenchMsg) {
    /* We are a WB launch. argc=0, argv=NULL passed to main() */
    /* Must not return until cleanup */
}

On exit from a WB-launched program:

Forbid();                          /* prevent task switching during cleanup */
ReplyMsg((struct Message *)_WBenchMsg);  /* unblock Workbench */
/* now safe to RTS / remove task */

This pattern is critical: failing to ReplyMsg a WB launch will hang Workbench.


SAS/C startup checks for a stack size cookie in the executable:

/* In your source — sets minimum stack to 8 KB */
LONG __stack = 8192;

The linker includes this symbol at a known offset; the OS shell reads it and allocates at least that much stack before launching. IDA Pro will often highlight _stack as a data symbol.


CTRL-C Checking

SAS/C runtime polls for CTRL-C via CheckSignal(SIGBREAKF_CTRL_C) inside printf, fgets, and other stdio functions. Programs that do long computation loops should call:

if (SetSignal(0, 0) & SIGBREAKF_CTRL_C)
    cleanup_and_exit();

Or use SAS/C's __chkabort() hook.


slink FROM lib/c.o myobj.o LIB lib/sc.lib lib/amiga.lib TO myprogram

Order matters:

  1. lib/c.omust be first (entry point at start of segment 0)
  2. Object files (myobj.o, ...)
  3. sc.lib — C runtime (resolves printf, etc.)
  4. amiga.lib — OS stubs (resolves any non-inlined OS calls)
m68k-amigaos-gcc -o myprogram myobj.o -lamiga -lnix -lgcc \
    -Wl,-Map,myprogram.map

Linker script places crt0.o automatically via -lnix startup group.


Library Archive Format

Static libraries (.lib) are HUNK_LIB archives — sequences of embedded HUNK_UNIT object files with a HUNK_INDEX for fast symbol lookup:

HUNK_LIB
  [HUNK_UNIT: AllocMem.o]
    HUNK_CODE
    HUNK_EXT   (export: _AllocMem)
    HUNK_END
  [HUNK_UNIT: FreeMem.o]
    ...
HUNK_INDEX
  [symbol table: _AllocMem → unit 0, _FreeMem → unit 1, ...]

The linker only pulls in units whose exported symbols are referenced — unused code from libraries is not linked into the executable (link-time dead-stripping).


Segment Layout in Final Executable

With a typical 3-object, 2-lib link:

Segment 0 (code):  c.o startup + all CODE sections merged
Segment 1 (data):  all DATA sections merged
Segment 2 (BSS):   all BSS sections (zero-filled)

Most linkers merge same-type sections by default. slink supports explicit placement control via CHIP / FAST keywords.


References

  • NDK39: lib/amiga.lib, auto.lib, debug.lib, c.o
  • SAS/C 6.x Programmer's Reference Manual — linking chapter
  • libnix source: https://github.com/bebbo/libnix
  • Amiga ROM Kernel Reference Manual: Libraries — process startup appendix