feat(dwarf): emit .rel.debug_* so a linker fixes up DWARF .text addresses (VCR-DBG-001 PR C, #394) - #430
Merged
Merged
Conversation
…sses (VCR-DBG-001 PR C, #242, #394) PR B emitted DWARF whose .text addresses were object-relative (base 0) with NO relocations — correct in the ET_REL object but silently WRONG on a linked image, so a `--debug-line` consumer (jess, debugging gust on silicon) would get wrong source lines after `ld`. This wires the relocations that make the linker shift them. C1 — elf_builder per-section REL generalization: - ElfBuilder gains `extra_relocations` + `add_section_relocations(target, ..)`, emitting `.rel.<name>` sections (REL form, sh_link=symtab, sh_info=target). - Byte-identical when empty: every new byte (shstrtab names, rel tables, section headers, +N to e_shnum) is appended after `.rel.text` and only when non-empty. The frozen cabi_arena_realloc_linkability_418 `.rel.text` fixture stays byte-identical. C2 — gimli RelocWriter + .text base symbol: - A custom `write::Writer` delegates to EndianVec but overrides ONLY write_address, so just the two `.text` references (the line program's DW_LNE_set_address anchor + the CU DW_AT_low_pc) become relocations; internal DWARF section cross-refs stay concrete (no section symbols needed). - Single-base-reloc + addend 0 ⇒ the `.debug_*` bytes are byte-identical to PR B (Address::Symbol{_,0} writes the same in-place 0 as Address::Constant(0)); rows stay text-relative deltas, so one relocation per section covers all rows. - A dedicated GLOBAL `__synth_text_base` (st_shndx=.text, value 0) anchors the R_ARM_ABS32 records; global + appended last ⇒ no symbol-index shift, symtab sh_info untouched, present only under --debug-line. - `--debug-line` on a self-contained ET_EXEC / RISC-V build (where DWARF is not emitted) now warns LOUDLY rather than silently dropping (#383 honest-fail). Oracle C (relocate-at-nonzero-base, correct line): asserts `.debug_line` / `.debug_info` each carry exactly one R_ARM_ABS32 against __synth_text_base with in-place addend 0, then APPLIES the `.debug_line` reloc at base 0x08000000 and re-walks the line program — every row shifts by exactly the base and its source line is preserved. Confirmed end-to-end with a real `arm-none-eabi-ld -Ttext= 0x08000000` link: readelf --debug-dump=decodedline shows rows at 0x800023c… on the correct source lines. All four dwarf_debug_line_emit_394 oracles green; PR B additivity/no-op oracles unchanged (bytes identical); fmt + clippy clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This was referenced Jun 22, 2026
avrabe
added a commit
that referenced
this pull request
Jun 22, 2026
, #394) (#440) First release of the north-star verified-codegen campaign. Pin sweep 0.11.51 -> 0.12.0 (workspace + all path-dep versions + MODULE.bazel + Cargo.lock), CHANGELOG, and VCR-DBG-001 roadmap status -> implemented. Ships: - VCR-DBG-001 `--debug-line` DWARF emission (PR A #427 / B #429 / C #430): debugger-readable .debug_* mapping ARM .text -> wasm source lines, with .rel.debug_* relocations verified end-to-end against arm-none-eabi-ld. Purely additive; default build bit-identical. - VCR-MEM-001 layer-2 frozen-safe budget decision logic + oracles (#421-#425). - gimli 0.33 adaptation (#439) + wast 252 (#438). Minor bump: new user-facing `--debug-line` feature (semver-correct). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
avrabe
added a commit
that referenced
this pull request
Jul 10, 2026
… func_N goes STB_LOCAL, symtab locals-first + real sh_info (#656) (#693) #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>
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.
What
PR C of v0.12.0 (VCR-DBG-001, epic #242). PR A captured the per-instruction
machine_offset → wasm_op_indexmap; PR B (#429) emitted debugger-reachable DWARF — but with object-relative (.textbase 0) addresses and no relocations. Correct in the unlinkedET_RELobject, silently wrong on a linked image: a--debug-lineconsumer (jess, debugging gust on silicon via gdb/lldb) would get wrong source lines afterld. This wires the relocations that make the linker shift them — the property the v0.12.0 tag was held for.How
C1 —
elf_builderper-section REL generalizationElfBuildergainsextra_relocations+add_section_relocations(target, ..), emitting.rel.<name>sections (REL form,sh_link=symtab,sh_info=target section).+Ntoe_shnum) is appended after.rel.textand only when non-empty.C2 — gimli
RelocWriter+.textbase symbolwrite::Writerdelegates toEndianVecbut overrides onlywrite_address, so just the two.textreferences (the line program'sDW_LNE_set_addressanchor + the CUDW_AT_low_pc) become relocations; internal DWARF cross-refs stay concrete (no section symbols needed)..debug_*bytes are byte-identical to PR B (Address::Symbol{_,0}writes the same in-place 0 asAddress::Constant(0)); rows stay text-relative deltas, so one relocation per section covers all 110 rows.__synth_text_base(st_shndx=.text, value 0) anchors theR_ARM_ABS32records; appended last ⇒ no symbol-index shift,.symtabsh_infountouched, present only under--debug-line.--debug-lineon a self-containedET_EXEC/ RISC-V build (where DWARF isn't emitted) now warns loudly rather than silently dropping (native-pointer-abi: size the wasm .bss to data high-water-mark, not the full declared memory page (blocks tiny-RAM targets) #383 honest-fail).Oracle (the gate the advisor required)
rel_debug_relocations_shift_addresses_to_correct_line_394: asserts.debug_line/.debug_infoeach carry exactly oneR_ARM_ABS32against__synth_text_basewith in-place addend 0, then applies the.debug_linereloc at base0x08000000and re-walks the line program — every row shifts by exactly the base and its source line is preserved (relocate-at-nonzero-base, correct line, not just "a reloc exists").Confirmed end-to-end with a real linker:
A real toolchain links it and GNU's own DWARF reader resolves correct linked addresses.
Frozen-safe
dwarf_debug_line_emit_394oracles green; PR B additivity/no-op oracles unchanged (the gust whole-.ono-op oracle is the end-to-end C1 byte-identity proof).cabi_arena_realloc_linkability_418.rel.textfixture byte-identical.bazel build //crates:synthgreen.Known limitation (EXPERIMENTAL, documented in
--debug-linehelp)__synth_text_baseis a global symbol, so linking >1 synth--debug-lineobject into one image collides (multiple definition) — fails loud, not the silent-wrong-line shape. Common case (one synth.o+ the C kiln bridge) is correct and verified. Idiomatic fix (a localSTT_SECTIONsymbol) is a fast-follow blocked by the hardcoded.symtabsh_info=1; jumps priority if jess's image links multiple synth objects.Closes the v0.12.0 tag-hold on VCR-DBG-001.
🤖 Generated with Claude Code