amiga-bootcamp/06_exec_os/library_vectors.md
Ilia Sharin fca930d0db docs(amiga): make cross-references clickable markdown links
Convert bare .md path references in 29 files to proper [name](relative/path)
markdown links for GitHub navigation.
2026-04-23 12:24:21 -04:00

3.6 KiB
Raw Blame History

← Home · Exec Kernel

Library Vectors — JMP Table, LVOs, MakeFunctions, SetFunction

Overview

Every AmigaOS library exposes its functions via a JMP table at negative offsets from the library base. This document covers the structure of the table, how LVOs are assigned, and how to create or patch one programmatically.


JMP Table Structure

Address              Content         Description
lib_base - N×6:     4EF9 XXXXXXXX   JMP <absolute address>  ← function N
...
lib_base - 24:      4EF9 XXXXXXXX   JMP Reserved
lib_base - 18:      4EF9 XXXXXXXX   JMP Expunge
lib_base - 12:      4EF9 XXXXXXXX   JMP Close
lib_base -  6:      4EF9 XXXXXXXX   JMP Open
lib_base +  0:      struct Library  ← pointer returned by OpenLibrary

Each slot is exactly 6 bytes: opcode $4EF9 (JMP abs.l) + 4-byte target address.


LVO Formula

LVO = 6 × slot_index

where slot_index counts from 1 (Open) upward:
  Open     = slot 1 → LVO = 6
  Close    = slot 2 → LVO = 12
  Expunge  = slot 3 → LVO = 18
  Reserved = slot 4 → LVO = 24
  First user fn = slot 5 → LVO = 30
  Second user fn = slot 6 → LVO = 36
  ...

The .fd file ##bias value is the positive LVO: bias 30 → LVO 30.


MakeFunctions — Building a JMP Table

exec.library MakeFunctions() fills in the JMP table from a function pointer array:

ULONG MakeFunctions(APTR targetLib, APTR funcArray, APTR funcDispBase);

Typical usage in library InitLib:

; funcArray: table of function pointers, terminated by -1
_LibFuncTable:
    dc.l  _LibOpen
    dc.l  _LibClose
    dc.l  _LibExpunge
    dc.l  _LibNull        ; Reserved — returns NULL
    dc.l  _MyFunc1
    dc.l  _MyFunc2
    dc.l  -1              ; terminator

LibInit:
    LEA   _LibFuncTable(PC), A0
    MOVEA.L  A6, A1       ; library base (passed in A6 by exec)
    MOVEQ    #0, D0       ; funcDispBase = 0 (absolute addresses)
    MOVEA.L  4.W, A6
    JSR      (-420,A6)    ; MakeFunctions(A1, A0, D0)

MakeFunctions writes JMP <ptr> for each entry, filling the table downward from lib_base 6.


SetFunction — Patching a Single Slot

APTR SetFunction(struct Library *library, LONG funcOffset, APTR newFunction);
  • funcOffset is the negative LVO (e.g., 30 for the first user function)
  • Returns the old function pointer
/* Hook dos.library Write() */
old_write = SetFunction((struct Library *)DOSBase, -48, my_write_hook);

See setfunction_patching.md for trampoline patterns.


Checksum Maintenance

After MakeFunctions or SetFunction, exec updates lib_Sum via SumLibrary:

SumLibrary((struct Library *)myLib);

If LIBF_SUMUSED is set, exec verifies the checksum at CloseLibrary time. Patching the JMP table without calling SumLibrary will trigger a checksum failure (alert box or guru).


Viewing Vectors in IDA Pro

  1. Navigate to lib_base 6 (first standard vector)
  2. Each 6-byte group: opcode 4EF9 + 4-byte address
  3. Press C to disassemble if not auto-detected
  4. The 4-byte value is the actual function address — press G (Go to) to navigate
  5. Name each function with the .fd file as reference

References

  • NDK39: exec/execbase.h, exec/libraries.h
  • ADCD 2.1: MakeFunctions, MakeLibrary, SetFunction, SumLibrary
  • library_jmp_table.md — reconstruction workflow
  • lvo_table.md — complete LVO reference tables