#328 Relocation ledger (ADR 0025 D2/D3): imm64 absolute-site inventory for ASLR + the eventual data core
openPart of #318 (ADR 0033 Axis B, per the 2026-07-15 amendment). The durable next step after the raw-arena core was deferred behind the compacting GC.
Goal
Record every ABSOLUTE (imm64/u64) address site in a saved image so it can be delta-relocated when the image loads at a non-fixed base (PIE/ASLR, ADR 0025 D3), and so the eventual compact data core reuses the same ledger.
Scope finding (shrinks ADR 0025 worst case)
funcl CALL + FUNCTION-VALUE relocations are ALREADY rel32 / PC-relative (ag-patches-apply, ag-fn-value-patches-apply: "load-address-independent"). They need NO relocation when the code base moves. The ledger is ONLY the absolute sites:
- imm64 refs in code to quote-pool + keyword/symbol pool RECORD vaddrs (arena)
- cross-region pointers (heap<->code)
- heap-slot raw lowtag-2 code pointers (fn cells, closure entries)
- fn-table vaddrs
- arena pool records (heap + code slots)
- fixed-runtime raw vaddr slots, root-range starts
The B3 HEAP bitmap is NOT this — the object path is already heap-position- independent (rebuilds at fresh addresses). This ledger is code/cross-region only.
Approach (funcl is the linker — ADR 0025)
Record each absolute site AT EMIT TIME into a persistent ag-image-reloc-ledger (the compiler already tracks the same sites transiently as ag-quote-patches / ag-keyword-pool-vaddrs / ag-baked-relocs before consuming them). Serialize the ledger into a RELOC-CODE image section. On load, apply += delta per site (no-op at delta 0). COLD never relocates (self-host); ledger is warm/image-only.
Increments (ADR 0025: build ledger at delta 0, verify at non-zero delta)
- Ledger accumulator + RELOC-CODE section + delta-0 apply skeleton (additive).
- Wire the first absolute class (quote-pool imm64 sites); serialize + apply.
- Extend to keyword/symbol pool record vaddrs, fn-table vaddrs, heap-slot code pointers, cross-region.
- Forced non-zero-delta verifier: map CODE-MMAP at a different base, apply the ledger, boot + full suite. Proves completeness (ADR 0025 delta-0-hides-bits trap). Residual old-base scan.
- PIE: stop MAP_FIXED-ing CODE-MMAP; map at kernel base + relocate (ADR 0025 D3).
Code anchors
- src/cold/stage1.lisp:1111 ag-patches-apply (rel32 — NOT in ledger)
- src/cold/stage1.lisp:1235 ag-fn-value-patches-apply (rel32 — NOT in ledger)
- src/cold/compiler.lisp:751 ag-baked-relocs; :998 abs record vaddr capture
- src/cold/compiler.lisp quote-pool emit + ag-quote-patches (the abs imm64s)
- src/warm/image.lisp RELOC section (+image-section-reloc+ = 8; reused/extended)
- docs/decisions/0025-security-posture-and-relocation-bitmap-image.md (D2/D3)
Re-scoped after codex verification — NOT a standalone ledger
Codex confirmed: within-code refs (call/function-value/quote-pool) are already rel32/PC-relative, so a general code-relocation LEDGER is redundant with Axis A for the object path. A standalone ledger is justified ONLY for the deferred ADR 0025 D2 raw-dump/self-relocating PIE bytes.
The work splits three ways:
Keeping #328 open to track (2) + (3). The general-ledger framing is dropped.