Repository navigation
RQ-59-A64PANIC (#1013): aarch64 ELF builder refuses cleanly (exit 1 + reason naming the declined symbol) instead of panicking - #1045
Merged
Conversation
…ust refuse cleanly, not panic Asserts the full refusal contract, not merely 'does not crash': exit code exactly 1 (not Rust's panic 101), no panic markers on stderr, and a machine-readable reason naming the declined symbol (func_0) and the #851 unrelocated-placeholder class. Negative control: the same decline with no dangling relocation stays a routine exit-0 skip. Currently FAILS on the exit-code assertion (measured: exit 101, panic at crates/synth-backend-aarch64/src/elf.rs:189) — the fix lands next. Sibling behaviour measured while writing this (a finding vs #1013's table): arm and riscv both exit 0 on the identical module — ARM compiles the 95-target br_table outright; RISC-V declines func_0 and emits the object with synth_func_0 as an UNDEFINED symbol, relocations retained (loud at link time, #871). Full undefined-external parity for aarch64 is #1017/v0.60 scope; this lane only fixes the refusal mechanism. Refs #1013 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…ncommitted changes
Committed by the hub coordinator so the work survives. NOT REVIEWED and NOT
COMPLETE: the lane stopped mid-task and had not committed in 15 hours. This is
a restore point, not a claim that anything is verified.
Touches crates/synth-backend-aarch64/src/{backend,elf}.rs,
crates/synth-cli/src/main.rs and the lane's own
crates/synth-cli/tests/a64_dangling_reloc_decline_1013.rs (99 insertions).
Refs #1013.
…ng correction Status proposed -> implemented. The entry's parity table said ARM and RISC-V exit 1 cleanly on the identical module; measured (symtab-verified), neither does: ARM compiles the wide br_table outright (func_0 placed, exit 0), RISC-V declines func_0 but emits the object with synth_func_0 as SHN_UNDEF and the relocation retained (loud at link time, exit 0). aarch64 cannot express undefined externals yet (#1017-adjacent v0.60 scope), so the landed fix matches aarch64's OWN known-good refusal shape — the #851 data-segment decline: clean exit 1, reason naming the dangling symbol and class, no partial object. Recorded in the description so the requirement stops asserting the unmeasured table. rivet validate: 50 pre-existing errors before AND after this edit (the #1012 class); this commit adds none. Refs #1013 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RQ-59-A64PANIC (#1013): aarch64 ELF builder refuses cleanly (exit 1 + reason) instead of panicking on a dangling reloc against a declined function
Resumed lane. The previous run stalled with uncommitted work; the coordinator salvaged it onto this branch (
salvage(#1013)commit, explicitly marked UNREVIEWED). This run reviewed the salvage on merit, re-verified red-first from a rebuilt binary, kept it, and completed the lane (rivet status flip + measured-sibling correction + class survey).Red-first transcript (re-verified this run, freshly built binaries)
BEFORE (sources at
708ae34b= pre-fix, test's own generated 20-targetbr_tablefixture — the minimized galehttparseshape):AFTER (this branch):
The DECISION is unchanged — an unrelocated
bl #0/adrp #0placeholder never ships. Only the MECHANISM changed:panic!→Err(BackendError::CompilationFailed(...)), propagated through both CLI call sites (build_aarch64_elf,build_multi_func_aarch64_elf) to the anyhow exit-1 path.The test (
crates/synth-cli/tests/a64_dangling_reloc_decline_1013.rs) asserts the full refusal contract, not "does not crash": premise anchor (the VCR-A64-CF-001 decline actually happened), exit code exactly 1 (101 = still panicking, 0 = dangling reloc shipped), nopanicked at/RUST_BACKTRACEon stderr, reason string namingfunc_0and the #851 class, and no partial object left behind. Plus a negative control: the same decline with NO dangling reloc stays a routine exit-0 skip with the object emitted.Reference behaviour — measured, and a correction to #1013's table
#1013 says ARM and RISC-V exit 1 cleanly on the identical module. Measured (symtab-verified with pyelftools), neither does:
--target cortex-m4): COMPILES the widebr_tableoutright — exit 0,func_0placed in.text.-b riscv): declinesfunc_0but emits the object withsynth_func_0as an SHN_UNDEF symbol and the relocation retained — loud at link time (riscv backend: 'external call without relocation table' blocks every seam-importing function (--relocatable) #871), exit 0.aarch64's ELF builder cannot express undefined externals yet (that is #1017-adjacent v0.60 capability work, explicitly out of scope). So the fix matches aarch64's own known-good refusal shape — the #851 active-data-segment decline in
backend.rs(BackendError::CompilationFailed, reason naming the class, clean exit 1) — exactly the house style #1041 credits aarch64 for. No new policy invented; the rivet entry's description got a MEASURED CORRECTION paragraph recording this.Panic-site class survey (aarch64 crate, non-test code)
Grepped
panic!/unreachable!/unwrap()/expect(/direct indexing acrosscrates/synth-backend-aarch64/src/:elf.rsdangling-symbol lookup (formerlyunwrap_or_else(panic!)at line 189) — nowErr.elf.rs:195— reloc-KIND wildcard (RelocKindother than the four AArch64 kinds reaching the aarch64 builder would be a cross-backend plumbing bug); defensive-panic convention.selector.rs:2846—patch_branchunreachable!on a non-placeholder word the selector itself emitted.backend.rs,encoder.rs,substrate.rs,lib.rs: zero non-test panic sites.substrate.table) feeds the SAME builder loop, so a table relocation against a declined function is covered by the sameErr, not a sibling panic.Salvage verdict
KEPT, with completion. The salvaged fix + test were judged correct: mechanism matches the house refusal style, test asserts the full contract, builder signature change is
Ok-wrapping only on the success path (emitted bytes untouched — frozen anchors did not move; full workspace suite green). Added this run: red/green re-verification from rebuilt binaries, sibling measurement, class survey, rivetRQ-59-A64PANICstatusproposed→implementedwith the measured-sibling correction.Gates
cargo fmt --all— no diffcargo clippy --workspace --all-targets -- -D warnings— greencargo test --workspace— TRUE exit 0 (see below)python3 scripts/claim_check.py claims.yaml— 50/50 claims holdpython3 scripts/model_coverage_audit.py --check— okrivet validate— 50 pre-existing errors before AND after the rivet edit (the rivet externals are declared against a volume that does not exist — the federated half of the trace graph is never validated #1012 class); this PR adds noneEXPECTED_DECLINES(fix(#973): ARM select on an i64-comparison returns the then-arm — and an ARM leg for the corpus CI never compiled #992 /arm_corpus_sweep_973.py): unaffected — it is the ARM-target (cortex-m4f) sweep and this change alters only the aarch64 refusal mechanism; no fixture entry moves.🤖 Generated with Claude Code
https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L