vms-83e8: classic GD/LD TLS relaxation — drop dead __tls_get_addr GOT slot + standing guard - #683
Open
baron-3dl wants to merge 2 commits into
Open
vms-83e8: classic GD/LD TLS relaxation — drop dead __tls_get_addr GOT slot + standing guard#683baron-3dl wants to merge 2 commits into
baron-3dl wants to merge 2 commits into
Conversation
…E relaxation The classic general-/local-dynamic TLS access model calls __tls_get_addr; when the object was built -fno-plt (Alpine's libstdc++/libgcc, whole-archived into every C++ OVMX image) that call reaches its target through an R_X86_64_GOTPCRELX cell against __tls_get_addr. LINK relaxes every classic GD/LD access to Local-Exec (patch_tls_le, vms-76a), overwriting the call, so no patched instruction ever reads that cell -- it is dead. The GOT-collection pass still collected a slot for it, and the GOT-fill pass then tried to resolve __tls_get_addr (defined nowhere in a static image) and died "GOT symbol undefined", so an otherwise clean classic-GD/LD link needed --allow-undefined purely to defer one dead slot. The import loop (vms-e65) and the datum loop (vms-76a) already skip __tls_get_addr for the same reason; the GOT-collection pass was the one place missing the guard. Add it. Effect on the real cpptest link (whole libstdc++/libgcc): GOT 2047->2046, deferred externals 184->183, output byte-identical otherwise; 1772 mov %fs LE landings, zero surviving __tls_get_addr / data16-GD sequences (verified). New standing guard: src/vmslink/test/run_test_x86_64_classic_tls.sh -- the classic-dialect sibling of run_test_x86_64_tls.sh (which only covers gnu2 TLSDESC and never emits a TLSGD/TLSLD/__tls_get_addr). It compiles a freestanding program with a cross-TU __thread (GD, data16 lea + -fno-plt indirect call) and a function-local static _Thread_local pair (LD, TLSLD + DTPOFF32) -- the exact shapes of libgcc's bid*.o and libsupc++'s eh_globals.o -- links it with NO --allow-undefined, asserts at byte level that no classic GD/LD sequence survives, then ACTIVATES it through the real x86_64 IMGACT.EXE and proves both variables read/write correctly through the relaxed LE sequences (exit 110). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-x86_64 CI job Runs src/vmslink/test/run_test_x86_64_classic_tls.sh alongside the gnu2 TLSDESC step, reusing the same /vms PT_INTERP setup. Native x86_64, no emulation. Co-Authored-By: Claude Opus 4.8 (1M context) <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 / why
Investigating the reported residual
__tls_get_addrSIGSEGV in C++ OVMX images (vms-83e8, epic vms-da0 F2b).Ground-truth finding: at base
work/vms-ad70-decc-delta@ 39dadb0, the classic GD/LD → Local-Exec relaxation (vms-76a: 16cf1f5 + 1f733a7) is complete. Linking the realcpptest.oagainst the whole upstream libstdc++/libsupc++/libgcc archives (525 objects) yields 1772mov %fs:0LE landings and ZERO surviving classic TLS sequences — no data16 GD lea/call, no direct GD call, no symbolic/deferred__tls_get_addr. The un-relaxed-lea-crashes-in-__tls_get_addrbug does not reproduce here; it was fixed by the two vms-76a commits already in the base. Both hypothesized residual forms (GD data16-indirect from libgccbid*.o, LD-indirect from libsupc++eh_globals.o) are handled.The one real gap found + fixed
The classic GD/LD
__tls_get_addrcall, under-fno-plt(how Alpine's libstdc++/libgcc are built), reaches its target via anR_X86_64_GOTPCRELXcell.patch_tls_lerelaxes the call away, so that cell is dead — but the GOT-collection pass still collected a slot for it, and GOT-fill then diedGOT symbol undefined(__tls_get_addris defined nowhere in a static image). So a clean classic-GD/LD link needed--allow-undefinedpurely to defer one dead slot. The import loop (vms-e65) and datum loop (vms-76a) already guard__tls_get_addr; the GOT-collection pass was the one place missing it. Added the matching guard (onecontinue).Effect on the real cpptest link: GOT
2047→2046, deferred externals184→183, otherwise byte-identical.New standing guard
src/vmslink/test/run_test_x86_64_classic_tls.sh— the classic-dialect sibling ofrun_test_x86_64_tls.sh(which only covers gnu2 TLSDESC and never emits a TLSGD/TLSLD/__tls_get_addr, so the classic path had no end-to-end coverage). Compiles a freestanding program with a cross-TU__thread(GD, data16 lea +-fno-pltindirect call) and a function-localstatic _Thread_localpair (LD, TLSLD + DTPOFF32) — the exact shapes ofbid*.o/eh_globals.o— links with no--allow-undefined, asserts at byte level that no classic GD/LD sequence survives, then activates through the real x86_64 IMGACT.EXE and proves both variables read/write correctly (exit 110). Wired into thevmslink-x86_64CI job.Verified
run_test_x86_64_tls.sh): PASS (no regression).run_test_x86_64.sh): PASS.run_as_native.sh): running.x86_64-only instruction rewriting; offset math unchanged (Alpha/VAX untouched, per the conductor's gate).
Routes to the conductor's batched post-0.5 gate.
🤖 Generated with Claude Code