Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions changelog.d/8127-elf-provider-runtime-exports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
`gc-native-roots` is green on ELF again. The gate failed on both Linux
platforms — Mach-O and Windows passed — with "stdlib provider is bound to a
different runtime image". Re-running the last-good job on its own commit shows
that commit still passes, so the environment was never at fault: the break came
with the ELF branch of the #8075 linker shim added in #8089.

The cause is that branch's `local: *`. The provider statically links the
runtime rlib as well as loading the runtime `.so`, so it carries its own
`js_gc_init` and friends; `local: *` binds those internally, and a local symbol
is not preemptible. The stdlib then resolved stateful runtime calls to its own
copy rather than the image the host loaded first — the exact condition the
fixture exists to detect. Before the shim parsed `--version-script` at all the
rustc-generated script was passed through and the gate passed, so the
regression is the hiding, not the export list.

The version script now names the 16 provider exports with no `local: *`, so
every other symbol keeps its default global, preemptible binding. Re-exporting
the runtime's symbol table explicitly (as the Mach-O branch does via `nm`) is
not an option on ELF: rustc also passes `--no-undefined-version`, so naming a
symbol the output does not define is a hard lld error.
19 changes: 18 additions & 1 deletion tests/fixtures/issue_8075_provider_gc/stdlib-linker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,27 @@ fi
if [[ -n "$original_version_script" ]]; then
if [[ "$saw_runtime_rlib" == true ]]; then
custom_version_script=$(mktemp "${TMPDIR:-/tmp}/perry-8075-version.XXXXXX")
# `global:` WITHOUT a `local: *`.
#
# The provider statically links the runtime rlib as well as loading the
# runtime .so, so it carries its own `js_gc_init` and friends. `local: *`
# binds those internally, and a local symbol is not preemptible — the
# stdlib then resolves stateful runtime calls to its OWN copy instead of
# the image the host loaded first, which is exactly what this fixture
# exists to detect ("stdlib provider is bound to a different runtime
# image"). Before this shim parsed `--version-script` at all, the
# rustc-generated script was passed through and the gate passed; the
# regression came with the hiding, not with the export list.
#
# Listing the runtime's symbols explicitly is NOT the fix: rustc also
# passes `--no-undefined-version`, so naming a symbol the output does not
# define is a hard lld error. Omitting `local: *` leaves every other
# symbol at its default (global, preemptible) binding and names only what
# must be added.
{
echo '{ global:'
printf ' %s;\n' "${stdlib_provider_exports[@]}"
echo 'local: *; };'
echo '};'
} > "$custom_version_script"
arguments+=("-Wl,--version-script=$custom_version_script")
else
Expand Down
Loading