fix(326): reloc-driven shared-memory address rebasing (sound --memory shared)#340
Conversation
…table Records the evidence-based #326 decision before the code, per rivet-leads-code. ADR-6 (design-question, resolved): address relocation for the shared-memory fusion mode. Spike (/tmp/spike326, gale-shaped fixtures reproducing both gale datapoints) settled the input contract: - path-D (relocatable: consume linking+reloc.*) CHOSEN — survives `wasm-tools component new` byte-for-byte; meld 0.39.0 already PRESERVES the metadata (just doesn't consume it). - path-E (PIC/dylink) REJECTED — `component new` refuses a core importing memory/__memory_base globals ("module is only allowed to import functions"). - path-F (hard-error non-relocatable shared inputs) retained as fallback. SR-48 (proposed, release v0.40.0, derives-from SYS-6, mitigates LS-M-11): consume linking+reloc.CODE/DATA, translate each site via the rewriter offset_map (the #331 AddressRemap seam), add memory_base to R_WASM_MEMORY_ADDR_SLEB/LEB/I32 operands, strip consumed relocs; hard-error when metadata is absent. Supersedes the unsound "inject addr+memory_base at every load/store" idea in SR-37 history. `rivet validate` PASS. Refs #326, #334, gale#168, ADR-4, ADR-6, SR-37, SR-48, LS-M-11. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hand-parses `linking` v2 + `reloc.CODE`/`reloc.DATA` custom sections into
structured RelocInfo (wasmparser 0.246 dropped reloc/linking readers, so meld
must parse them itself). Pure, side-effect-free reader — NOT yet wired into the
fusion path (increment 2), so no Tier-5 file is touched.
Wire format reverse-engineered from the /tmp/spike326 fixture and confirmed
against wasm-tools ground truth: body = target_section:varu32, count:varu32,
then entries {type:u8, offset:varu32, index:varu32, addend:varint32}; the addend
is emitted for the memory-address/offset family even when 0 (encoded zero, not
absent).
8/8 unit tests green: parses the spike reloc.CODE (4 entries: MemoryAddrSleb
62/3/32, 88/3/0; MemoryAddrLeb 132/4/0, 144/4/0), confirms the metadata SURVIVES
`wasm-tools component new` into the embedded core, hand-built-bytes round-trip
(no /tmp dependency), and has_reloc_metadata=false for the baseline component.
Refs #326, SR-48, ADR-6.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gale#168 resolved) gale#168 (avrabe): -C link-arg=--emit-relocs keeps reloc.CODE/DATA in the FINAL linked module — a self-contained core component new accepts, carrying linking v2 + reloc.*, importing no memory/__memory_base globals. Strictly better than the spike's --emit=obj -> wasm-ld -r (which under-links -> component new rejects the dangling __indirect_function_table import). Verified through wac plug: composite carries one reloc.CODE+linking per inner core, unstripped to meld. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Tier-5) Consume linking+reloc.CODE/DATA to rebase a component's absolute addresses into its shared-memory window, making `fuse --memory shared` SOUND for relocatable inputs (ADR-6 path-D, SR-48). Fixes the meld#326 corruption for --emit-relocs inputs; verified at runtime. Core (rewriter.rs, merger.rs, segments.rs, reloc.rs): - Per module, translate each R_WASM_MEMORY_ADDR_* reloc site through the rewriter offset_map (the #331 AddressRemap seam) and add the module's memory_base to the i32.const/i64.const address literal (reloc.CODE) or the 4-byte LE data pointer (reloc.DATA); strip consumed relocs. - memarg rebasing switched from BLANKET (add base to every load/store offset) to reloc-DRIVEN (only flagged memargs), which also fixes a latent over-rebasing of genuine struct-field offsets. - path-F gate (error.rs MissingRelocMetadata): a no-reloc, non-zero-base module with direct memory access hard-errors instead of silently colliding. Verified (isolated target): 457 lib + 4 integration tests green, incl. test_326_reloc_const_rebasing_end_to_end (address rebased at runtime), test_326_shared_rebase_without_relocs_hard_errors (path-F), and the existing test_address_rebasing_end_to_end (bulk-only dynamic rebasing) still green. clippy + fmt clean. Mythos discover pass (Tier-5): core rebasing arithmetic verified sound (coordinate alignment across all functions, rebase-exactly-once, LEB/overflow, reloc-type filtering). Three gate/scope findings, resolved: - Finding A (value-as-pointer gate miss): reverted the naive broadening (it regresses the legitimate bulk-only case) -> documented KNOWN LIMITATION + filed #339 (needs data-flow-aware gate); does NOT affect --emit-relocs inputs. - Finding B (memory64 8-byte data pointers unhandled): reject via has_unhandled_data_addr_relocs (+ unit test) rather than mis-rebase. - Finding C: corrected MissingRelocMetadata message (--emit-relocs on final link; a `wasm-ld -r` object is addends-only, not sufficient). Refs #326, #339, ADR-6, SR-48, LS-M-11. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mythos delta-pass requiredThis PR modifies one or more Tier-5 source files (per Before merge, run the Mythos discover protocol on the
Why this gate exists: LS-A-10 The gate check on this PR will pass once the label is |
Mythos discover pass (manual, Tier-5) — doneRan an adversarial discover pass over the reloc-consumer diff (the automated per-file pass will likely time out on merger.rs/rewriter.rs). Focus areas and verdict: Core rebasing arithmetic — VERIFIED SOUND:
Three gate/scope findings — resolved:
Findings B/C fixed in this PR; A filed as #339 with rationale. |
LS-N verification gate✅ 59/59 approved LS entries verified
Approved Failed LS entries(none) Missing regression tests(none) Updated automatically by |
Mythos delta-pass (auto)❌ 2 finding(s) across 5 Tier-5 file(s)
Auto-run via |
…sing (#342) Cut v0.40.0 (0.39.0 → 0.40.0). Scope: #326 reloc-consumer (merged #340) — the address-rebasing keystone that makes single-address-space MCU fusion sound. SR-48 proposed → verified: runtime oracle test_326_reloc_const_rebasing_end_to_end (address rebased to base+addr via wasmtime), path-F control test_326_shared_rebase_without_relocs_hard_errors, reloc.rs parser/Finding-B tests; 457 lib + 4 integration green; Mythos discover pass done. Known limitation #339 (Mythos Finding A, no-reloc value-as-pointer) documented. `rivet release status v0.40.0` → Cuttable (SR-48 verified). `rivet validate` PASS. CHANGELOG [0.40.0] with falsification + known-limitations. Refs #326, #339, ADR-6, SR-48, LS-M-11. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Makes
meld fuse --memory sharedsound for relocatable inputs by consuming their relocation metadata to rebase absolute addresses into each module's shared-memory window — fixing the meld#326 silent memory corruption (gale's gust:os buffer +static mutdatapoints).What it does
linking+reloc.*, produced by-C link-arg=--emit-relocs). PIC is architecturally excluded (wasm-tools component newrefuses core modules importing memory/__memory_baseglobals). Settled by a spike (see fuse --memory auto/shared silently corrupts memory across components: load/store dynamic addresses are not rebased (no memory.grow; distinct from #172/#299) #326 comment); gale-side producer resolved (gale#168, one flag).reloc.rshand-parseslinkingv2 +reloc.CODE/reloc.DATA(wasmparser 0.246 dropped these readers). Verified the metadata survivescomponent newbyte-for-byte.R_WASM_MEMORY_ADDR_*site through the rewriteroffset_map(the fuse --dwarf remap emits out-of-section .debug_line rows for multi-DWARF inputs (verify-clean, silent); documented drop+adapter path not taken #331 AddressRemap seam), add the module'smemory_baseto thei32.const/i64.constliteral (code) or 4-byte LE pointer (data), strip consumed relocs. memarg rebasing switched blanket→reloc-driven (also fixes latent over-rebasing of struct-field offsets). No-reloc + non-zero-base + direct memory access → hard-error (path-F), never silent corruption.Verification (isolated target)
test_326_reloc_const_rebasing_end_to_end(address rebased at runtime via wasmtime),test_326_shared_rebase_without_relocs_hard_errors(path-F), and the pre-existingtest_address_rebasing_end_to_end(bulk-only dynamic rebasing) still green. clippy + fmt clean.Mythos discover pass (Tier-5)
Core rebasing arithmetic verified sound (coordinate alignment across all functions, rebase-exactly-once, LEB/overflow, reloc-type filtering). Three gate/scope findings, all resolved:
--emit-relocsinputs (their consts are rebased viareloc.CODE).has_unhandled_data_addr_relocs(+ unit test) rather than mis-rebase.MissingRelocMetadatamessage (--emit-relocson final link; awasm-ld -robject is addends-only).Falsification
If reloc rebasing regressed,
test_326_reloc_const_rebasing_end_to_end(asserts the address literal equalsbase + addrat runtime) fails. If path-F regressed,test_326_shared_rebase_without_relocs_hard_errorsfails. If the bulk path regressed,test_address_rebasing_end_to_endfails.Refs #326, #334, #339, gale#168, ADR-6, SR-48, LS-M-11, SYS-6.
🤖 Generated with Claude Code