casaroli opened a new pull request, #20812: URL: https://github.com/apache/nuttx/pull/20812
## Summary A toolchain without native TLS (for example the Arm GNU toolchain for aarch64-none-elf, or arm-none-eabi 13 as in CI) compiles a `__thread` variable into calls to `__emutls_get_address()`. In a flat or protected CMake build, `nuttx_add_application()` links the extra libraries, libgcc too, into each loadable module (`MODULE m`, `DYNLIB y`). The linker puts `emutls.o` of libgcc into the module. That copy is built with the single thread model: all threads of the module share one instance of each `__thread` variable. The loader never binds the module to the per-thread version of libc. This PR links such a module with copies of the extra libraries in which `__emutls_get_address()` and `__emutls_register_common()` are local symbols (`objcopy -L`). The module keeps them undefined, and the loader binds them to libc through the system symbol table. The module still takes all the other helpers from libgcc. The new function `nuttx_add_module_extra_libraries()` makes the copies at build time in `module_libs/`, only when the build has a loadable module. depends-on: apache/nuttx/pull/20723 (it exports the per-thread `__emutls_get_address()` of libc in libc.csv). The Make build gets the same change in apache/nuttx-apps#3882 (`Application.mk`, `Library.mk`). ## Impact - CMake loadable modules of a flat or protected build that use `__thread`: each thread now has its own copy. Without the libc export, the module does not load (`Exported symbol "__emutls_get_address" not found`) instead of sharing one copy. - Modules without `__thread` variables: same link, with the copies of the libraries. - Kernel build programs: no change (they link libc, which comes before libgcc). ## Testing `qemu-armv8a:nsh` (flat, CMake, Arm GNU 14.2 aarch64-none-elf, QEMU HVF) with `CONFIG_ELF`, `CONFIG_EXECFUNCS_SYSTEM_SYMTAB`, `CONFIG_TLS_NELEM=4`, #20723 and #20807 (`get_environ_ptr` in libc.csv). The configure output of `qemu-armv8a:knsh` (kernel build) still links the programs with the libgcc of the toolchain, after libc. The test programs are built with `MODULE m` and loaded from a 9p share of the build directory. | Module | master | this PR | |---|---|---| | tlsgroup (2 threads) | FAIL (one address for all threads) | PASS | | tls4 (4 threads) | FAIL | PASS | | tlsmany (12 variables) | FAIL | PASS | | uctls (ucontext) | PASS | PASS | | tlscxx (C++ `thread_local`) | FAIL | PASS | `nm` of a module: master has `T __emutls_get_address` (from libgcc); this PR has `U __emutls_get_address`. The module link names `module_libs/libgcc.a` and `module_libs/libm.a`. The uctls test needs `getcontext()`, `makecontext()` and `swapcontext()` in libc.csv; the test tree added them locally. `tools/checkpatch.sh -c -u -m -g` passes. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
