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.
4.8 KiB
AmigaOS Library Structure
The Library Node
Every AmigaOS library (and device, resource) begins with a struct Library at its base address:
/* exec/libraries.h */
struct Library {
struct Node lib_Node; /* +$00: linked list node */
UBYTE lib_Flags; /* +$0E: LIBF_ flags */
UBYTE lib_pad; /* +$0F: (reserved) */
UWORD lib_NegSize; /* +$10: bytes of function table (negative area) */
UWORD lib_PosSize; /* +$12: bytes of struct Library + private data */
UWORD lib_Version; /* +$14: major version */
UWORD lib_Revision; /* +$16: minor revision */
APTR lib_IdString; /* +$18: pointer to ID string */
ULONG lib_Sum; /* +$1C: checksum of the function table */
UWORD lib_OpenCnt; /* +$20: number of current openers */
};
lib_NegSize is the total byte size of the JMP table (the negative-address area preceding the struct). It equals num_functions × 6 bytes per JMP instruction.
JMP Table (Negative Offset Area)
The function table is constructed below the library base address. Each entry is a 6-byte JMP instruction:
Library base - 6: 4E F9 xx xx xx xx JMP AbsAddress (Open)
Library base - 12: 4E F9 xx xx xx xx JMP AbsAddress (Close)
Library base - 18: 4E F9 xx xx xx xx JMP AbsAddress (Expunge)
Library base - 24: 4E F9 xx xx xx xx JMP AbsAddress (Reserved)
Library base - 30: 4E F9 xx xx xx xx JMP AbsAddress (first user function)
Library base - 36: ...
Standard Functions (Fixed LVOs for All Libraries)
| LVO (offset) | Function |
|---|---|
| -6 | Open |
| -12 | Close |
| -18 | Expunge |
| -24 | Reserved (must return 0) |
These four are mandatory for every library. User functions start at LVO -30.
JMP Encoding
4E F9 AAAA AAAA = JMP.L absolute_address
To call function at LVO -30:
MOVEA.L LibBase, A6
JSR -30(A6) ; call through JMP table
The JSR -30(A6) does not jump directly to the function — it jumps to the JMP slot, which then jumps to the real function. This indirection is essential for SetFunction() patching.
MakeLibrary() — Constructing the Table
exec.library MakeLibrary() builds a library:
struct Library *MakeLibrary(
APTR funcArray, /* array of function pointers (APTR) or LONG offsets */
APTR structInit, /* structure initialiser table (or NULL) */
ULONG (*initFunc)(), /* init function (or NULL) */
ULONG dataSize, /* size of library data area */
BPTR segList /* segment list of the library code */
);
funcArray is a NULL-terminated list of function addresses. MakeLibrary allocates the combined negative+positive area and fills in the JMP table.
Library Initialisation
At MakeNode() / MakeLibrary() time:
AllocMem(lib_NegSize + lib_PosSize, MEMF_PUBLIC | MEMF_CLEAR)- Fill JMP table at negative offsets
- Initialise
struct Libraryfields at positive offsets - Set
lib_Sumto the checksum of the JMP table
At AddLibrary():
- Library is added to
SysBase->LibList - Future
OpenLibrary()calls find it by name viaFindName()
OpenLibrary() Path
struct Library *base = OpenLibrary("mylib.library", MIN_VERSION);
Internally:
execsearchesSysBase->LibListfor a node withln_Name == "mylib.library"- If found and version sufficient: calls
LVO_Open(offset -6) on the library - If not found: attempts to load
LIBS:mylib.libraryfrom disk viaLoadSeg()+InitResident() - Returns library base pointer, or NULL on failure
ROM Libraries (Kickstart)
Some libraries are resident — embedded directly in the Kickstart ROM:
exec.library— always in ROM; base at$4in exec exception vectorgraphics.library,intuition.library,dos.library— loaded from ROM on boot
ROM-resident libraries are listed in the Resident module list. During boot, exec calls InitResident() for each module marked as auto-init.
Library Flags
/* lib_Flags bits: */
#define LIBF_SUMMING (1<<0) /* currently computing checksum */
#define LIBF_CHANGED (1<<1) /* function table was patched (SetFunction) */
#define LIBF_SUMUSED (1<<2) /* checksum is valid */
#define LIBF_DELEXP (1<<3) /* delayed expunge requested */
LIBF_CHANGED is set by SetFunction() to signal that the checksum is no longer valid — tools like ShowConfig use this to detect patched libraries.
References
- NDK39:
exec/libraries.h,exec/nodes.h - ADCD 2.1 Autodocs: exec — OpenLibrary, MakeLibrary, AddLibrary, SetFunction
- Amiga ROM Kernel Reference Manual: Libraries — library architecture chapter
- http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node0002.html