fix(elf): .ARM.attributes + thumb auto-detect disasm (#637); internal func_N STB_LOCAL, symtab locals-first + real sh_info (#656) - #693
Merged
Conversation
… func_N goes STB_LOCAL, symtab locals-first + real sh_info (#656) #637 — synth disasm decoded synth's own Cortex-M Thumb-2 output as A32 garbage, and synth objects carried no ISA marker for other tools either: - The ELF builder gains `arm_attributes_section()` (SHT_ARM_ATTRIBUTES, 'A' + "aeabi" + Tag_File): Tag_CPU_arch / Tag_CPU_arch_profile / Tag_ARM_ISA_use / Tag_THUMB_ISA_use derived from the selected target (cortex-m3 = v7/M/Thumb-2, thumbv7em = v7E-M, thumbv8.1m = v8.1-M, cortex-r5 = v7/R/A32). Emitted on the relocatable-object path and both Cortex-M image paths, appended last so every section index is stable. Standard toolchains now auto-select the Thumb decoder — plain `objdump -d` (no --triple) already reads synth objects correctly. - `synth disasm` auto-detects the ISA instead of defaulting to A32: .ARM.attributes Tag_THUMB_ISA_use when present, else the STT_FUNC thumb bit (odd st_value), else e_entry bit 0. #656 — internal (non-exported) functions and the `func_{wasm_index}` call aliases were STB_GLOBAL, so co-linking two independently-dissolved objects failed with `multiple definition of 'func_N'`: - Non-exported functions and every func_N alias are now STB_LOCAL; exported names stay STB_GLOBAL. `arm-none-eabi-ld -r a.o b.o` links clean, each object keeps its own local helpers, exports resolve cross-object. - That drags in the ELF ordering rule that blocked local symbols since the DWARF work (#430): ElfBuilder now stable-sorts locals before globals at build time, sets `.symtab` sh_info to the first-non-local index (was hardcoded 1), and rewrites every relocation's symbol index through the permutation (.rel.text and the .rel.debug_* tables), so the #167/#173 R_ARM_THM_CALL machinery stays consistent. With zero locals the permutation is the identity — pre-#656 objects are byte-identical. Oracles: new elf_tooling_637_656.rs (bindings + sh_info + reloc reindex + co-link via arm-none-eabi-ld/ld.lld when present + attributes bytes + disasm thumb mnemonics on the #682 masked-shift shape), new elf_builder unit tests (locals-first sort, reloc remap, identity freeze, attributes blob). Frozen .text anchors 10/10 (symtab/attributes only — .text untouched); control_step (13/13) and flight_seam (0x07FDF307) symtab-based differentials re-run green on the new layout. Closes #637 Closes #656 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Fixes two ELF tooling/linkability issues in one lane: #637 and #656 (+ the #430 sh_info lineage).
#637 —
synth disasmdecoded synth's own Thumb-2 output as A32 garbageTwo independent levers, both landed:
.ARM.attributesemission (elf_builder::arm_attributes_section, SHT_ARM_ATTRIBUTES):Tag_CPU_arch/Tag_CPU_arch_profile/Tag_ARM_ISA_use/Tag_THUMB_ISA_usederived from the selected-ttarget (cortex-m3 = v7/M/Thumb-2, thumbv7em = v7E-M, thumbv8.1m = v8.1-M, cortex-m0 = v6-M/Thumb-1, cortex-r5 = v7/R/A32-only). Emitted on the relocatable-object path and both Cortex-M image paths, appended as the LAST section so every existing section index (.text=4, .data/.bss=5/6, DWARF tail) is untouched. Synth objects are now self-describing: plainobjdump -dwith no--triplealready prints correct Thumb-2.synth disasmISA auto-detect instead of the A32 default:.ARM.attributesTag_THUMB_ISA_usewhen present → the STT_FUNC thumb bit (oddst_value, the standard interworking convention the issue pointed at) →e_entrybit 0 → A32. Non-ARM/non-ELF inputs keep the previous behavior.#656 — internal
func_Nemitted STB_GLOBAL → multiple-definition collisions co-linking two dissolved objectsfunc_{wasm_index}) and everyfunc_Ncall alias of an exported function are now STB_LOCAL; export names stay STB_GLOBAL. Both are per-object labels keyed by wasm function index — exactly the names that collided across independently-dissolved objects..symtabsh_info=1):ElfBuilder::buildnow stable-sorts locals before globals, setssh_infoto the first-non-local index, and rewrites every relocation symbol index through the permutation (.rel.textand the.rel.debug_*tables) — the arm backend: every wasm call lowered to __meld_dispatch_import placeholder — no inlining, no relocations, non-linkable ELF #167/arm --relocatable: import-call relocations use func_N, not the wasm import field name — won't link against a real host #173 R_ARM_THM_CALL machinery indexes symbols and stays consistent. With zero locals the permutation is the identity andsh_infostays 1: pre-Internal (non-exported) func_N emitted as GLOBAL symbols → multiple-definition collision when co-linking two dissolved .o's #656 objects byte-identical.Kill-criterion from the issue, verified live:
Oracles
crates/synth-cli/tests/elf_tooling_637_656.rs(5 tests): bindings + locals-before-globals +sh_info= first-global (pyelftools-equivalent via theobjectcrate),.rel.textreindex resolution (name + address + LOCAL), co-link viaarm-none-eabi-ld/ld.lld-r(graceful skip on bare runners),.ARM.attributesbytes + SHT type, andsynth disasmprinting Thumb mnemonics on the thumb-2: i32.shl/shr_s/shr_u don't mask the shift amount mod 32 — amounts >=32 silently compile to 0 (VCR-SEL regression; Rocq ARM model masks like WASM so proof is vacuous) #682 masked-shift shape (skips without objdump, per the ci(vcr-oracle): CI-gate the RV32 immediate-shift-fold execution oracle (#472, #242) #489 host-dependence lesson).elf_builderunit tests: locals-first sort + reloc remap +sh_info, zero-locals identity freeze, attributes blob structure (M and R profiles)..textuntouched (symtab/attributes only).control_step_differential.py13/13 match (0x00210A55cases),flight_seam_differential.pyMATCH (0x07FDF307).-D warningsclean, fmt clean; rebased onto fix(selector): param liveness extends across loop back-edges — loop bound survives the induction increment (#663) #689 and re-verified.Closes #637
Closes #656
🤖 Generated with Claude Code