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.
5.6 KiB
RE Methodology — AmigaOS HUNK Binaries
Phase 1: Initial Triage
1.1 Identify the File Type
xxd target.library | head -4
| First 4 bytes | Type |
|---|---|
00 00 03 F3 |
Executable (HUNK_HEADER) |
00 00 03 E7 |
Object file (HUNK_UNIT) |
70 FF 60 FA |
Resident tag (RomTag) |
1.2 Dump HUNK Structure
hunkinfo target.library
Expected output:
Hunk 0: CODE size=$1234 offset=$00012000
Hunk 1: DATA size=$0200 offset=$00013240
Hunk 2: BSS size=$0400
Symbols: 45
Relocs: 127
1.3 Verify Library Header
For a .library file, hunk 0 should start with a RomTag (resident module tag):
$4AFC ; RT_MATCHWORD (hex: MOVEQ #0, D0 in context)
Real RomTag starts at word $4AFC:
_romtag:
DC.W RTC_MATCHWORD ; $4AFC
DC.L _romtag ; RT_MATCHTAG (self-pointer)
DC.L _endskip ; RT_ENDSKIP
DC.B RTF_AUTOINIT ; RT_FLAGS
DC.B VERSION ; RT_VERSION
DC.B NT_LIBRARY ; RT_TYPE
DC.B PRIORITY ; RT_PRI
DC.L _libname ; RT_NAME
DC.L _idstring ; RT_IDSTRING
DC.L _inittable ; RT_INIT (or function)
Phase 2: Load in IDA Pro
2.1 Load the File
File → New → select the binary → select "Amiga HUNK" format (or m68k raw if plugin not available).
If using the HUNK plugin:
- Hunks are mapped to segments:
CODE0,DATA0,BSS0, etc. - HUNK_SYMBOL entries become IDA names automatically
- HUNK_RELOC32 become IDA fixups
2.2 Set Processor
Options → General → Processor type = Motorola 680x0
For A1200/A4000 targets, enable 68020 or 68040 instruction sets.
2.3 Apply Library Type Information
Load the AmigaOS TIL (Type Information Library) if available:
File → Load file → FLIRT signature file— use Amiga-specific FLIRT sigs- Or manually:
View → Open Subviews → Type Libraries→ loadamigaos.til
Phase 3: Locate the Library Base
For a .library file, the library base is created by MakeLibrary() at runtime. In the static binary, look for:
; InitTable for the library:
DC.L _libsize ; LIB_POSSIZE (struct size)
DC.L _funcTable ; function array pointer
DC.L _dataTable ; data init table (or NULL)
DC.L _initCode ; init function
The function table is an array of absolute function pointers terminated by -1:
_funcTable:
DC.L _Open
DC.L _Close
DC.L _Expunge
DC.L _Reserved
DC.L _MyFunc1
DC.L _MyFunc2
...
DC.L -1 ; terminator
This is the easiest way to find all library functions from the static binary.
Phase 4: Identify Calling Conventions
4.1 Find Library Calls
Search for the pattern JSR -N(A6) or JSR -N(A5) (some code uses A5):
In IDA, search for instruction text: jsr -
Each hit is a library call. The register A6 (or A5) holds the library base at that point.
4.2 Trace Library Base
Trace backwards from the JSR to find where A6 was loaded:
MOVEA.L _DOSBase, A6 ; most common: global variable
JSR -48(A6) ; Write
MOVEA.L D0, A6 ; from return value of OpenLibrary
JSR -30(A6) ; Open
MOVEA.L 4.W, A6 ; SysBase directly
JSR -198(A6) ; AllocMem
4.3 Resolve the LVO
# IDA Python: resolve a JSR -N(A6) to a function name
def resolve_lvo(ea):
insn = idc.print_insn_mnem(ea)
if insn not in ('jsr', 'JSR'):
return
op = idc.print_operand(ea, 0)
# op looks like "-48(A6)" or "-552(a6)"
import re
m = re.match(r'(-?\d+)\(A6\)', op, re.IGNORECASE)
if m:
lvo = int(m.group(1))
# Look up in your LVO table
name = LVO_TABLE.get(lvo, f"unknown_lvo_{-lvo}")
idc.set_cmt(ea, f"→ {name} LVO={lvo}", 0)
Phase 5: Annotate and Name
5.1 Apply Library Function Names
Using the LVO tables from lvo_table.md, annotate each JSR:
# IDA script: annotate all JSR -N(A6) calls in exec context
import idautils, idc, idaapi
EXEC_LVOS = {
-198: "AllocMem",
-210: "FreeMem",
-282: "AddTask",
-552: "OpenLibrary",
# ... (full table from lvo_table.md)
}
for ea in idautils.CodeRefsTo(idc.get_name_ea_simple("_SysBase"), 0):
# For each reference to SysBase load, find subsequent JSR
pass # implement full trace
5.2 Name Functions
After resolving all library calls in a function, it becomes clear what the function does. Apply a meaningful name:
IDA: Press N on a function → rename to descriptive identifier
5.3 Define Structures
Apply AmigaOS structure types:
View → Open Subviews → Local Types→ import from AmigaOS headers- Or manually define:
ExecBase,DosLibrary,MsgPort, etc.
Phase 6: Patch Analysis
Look for evidence of SetFunction patching:
- JMP table entries pointing outside the library code segment
LIBF_CHANGEDbit set inlib_Flags- Functions that immediately JSR to a stored old-function address
Look for timer/protection mechanisms:
- Calls to
dos.library CurrentTime()ortimer.device - CIA timer reads (
$BFDE00area) - Comparison of tick counts with a threshold
References
- ida_setup.md — IDA configuration details
- compiler_fingerprints.md — compiler identification
- lvo_table.md — complete LVO tables
- NDK39: all
.fdandinclude/files