Skip to content

Native ELF TLS for the Vita target - #185

Draft
frangarcj wants to merge 5 commits into
masterfrom
next-native-tls
Draft

Native ELF TLS for the Vita target#185
frangarcj wants to merge 5 commits into
masterfrom
next-native-tls

Conversation

@frangarcj

Copy link
Copy Markdown
Contributor

What does this change?

The target compiler is built with --enable-tls and defaults to -ftls-model=local-exec; binutils gets two patches scoped to the armvita emulation (TP points at .tdata with no TCB; .tdata/.tbss share the read-only segment with module_start); newlib is built with --enable-newlib-reent-thread-local; libstdc++ is configured with HAVE___CXA_THREAD_ATEXIT for arm-vita-eabi so it defers thread_local destructor registration to newlib's __cxa_thread_atexit. [Pending in this PR: the TLS configuration as part of the newlib and pthread-embedded build identity, and a CI job that exercises an old-to-new incremental transition.]

Why is this change needed?

Phase B of vitasdk/.github#3: the toolchain side of native ELF TLS.

Testing

Compatibility

Breaks the target ABI (see the RFC); intended to ship as the nightly-tls channel first. Depends on vitasdk/newlib#115 and vitasdk/pthread-embedded#24; the NEWLIB_TAG/PTHREAD_TAG pins move to the merged commits before this merges. RFC: vitasdk/.github#3.

Third-party material

None.

AI assistance

  • Claude Opus 5
  • Claude Fable 5

Additional context

RFC: vitasdk/.github#3. Companions: vitasdk/vita-toolchain#294, vitasdk/newlib#115, vitasdk/pthread-embedded#24.

Local Exec / TPIDRURO is the model per vitasdk_native_tls_design.md
phase 1; verified against a standalone gcc-base build that it emits
STT_TLS/SHF_TLS/PT_TLS and R_ARM_TLS_LE32 instead of __emutls_*.

Assisted-by: Claude Opus 5
Vita's TP points straight at .tdata, with none of the ARM EABI's
8-byte TCB header in front of it, and the loader expects .tdata/.tbss
to share the same (read-only) segment as module_start. Two small
patches, scoped to the armvita emulation only, teach the linker both.

Assisted-by: Claude Opus 5
Pairs with the newlib side (struct _reent thread-local, kernel TLS slot
0x89 no longer holding it).

Assisted-by: Claude Opus 5
Design phase 1 says the main executable uses Local Exec, but nothing enforced
it: for a TLS symbol defined in another translation unit gcc falls back to
initial-exec, which wants a GOT entry the Vita loader never fills. Linking a
newlib with its reent in TLS produced 36 R_ARM_TLS_IE32 against _tls_errno
plus 15 R_ARM_TLS_LDO32, and vita-elf-create refused them.

CC1_SPEC only supplies the default, so -ftls-model= on the command line still
wins.

Assisted-by: Claude Opus 5
libstdc++ only defers thread_local destructor registration to libc when
HAVE___CXA_THREAD_ATEXIT is defined at its configure time, and the
--with-newlib branch never checks for the symbol: it hardcodes its
feature list. Without the define, libsupc++ compiles its own fallback,
which keeps the destructor list in a pthread key, only runs it when the
prebuilt library sees gthreads as active (a weak pthread_cancel
reference, satisfied only by a whole-archive libpthread), and never on a
raw kernel thread. Newlib on Vita now provides __cxa_thread_atexit,
running the destructors from the thread-exit path on every exit path, so
define it for arm-vita-eabi in that branch. Patched in both configure.ac
and the generated configure, since the build does not regenerate it.

Assisted-by: Claude Fable 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant