[libc-commits] [libc] 4057f8e - [libc] Move Linux TLS routines from crt1.o into libc.a (#225418)
via libc-commits
libc-commits at lists.llvm.org
Tue Sep 22 22:46:45 PDT 2026
Author: Jeff Bailey
Date: 2026-09-23T06:46:39+01:00
New Revision: 4057f8e45b7fcadf99b60763c873802f8add8770
URL: https://github.com/llvm/llvm-project/commit/4057f8e45b7fcadf99b60763c873802f8add8770
DIFF: https://github.com/llvm/llvm-project/commit/4057f8e45b7fcadf99b60763c873802f8add8770.diff
LOG: [libc] Move Linux TLS routines from crt1.o into libc.a (#225418)
init_tls, cleanup_tls, and set_thread_ptr are per-thread routines used
by both Thread::run in libc.a and main-thread startup in crt1.o, but
tls.cpp was previously only merged into crt1.o. Linking libc.a without
crt1.o (such as a self-contained shared library statically linking
libc.a, or an executable built with -nostartfiles) failed with undefined
hidden symbols when thread.cpp.o was pulled in.
Move {x86_64,aarch64,riscv}/tls.cpp from libc/startup/linux/ to
libc/src/__support/threads/linux/ alongside tcb.h (matching prior
migrations of auxv and program_invocation_name from startup into src so
dependencies flow from startup -> src). Expose them via a forwarding
ALIAS target libc.src.__support.threads.linux.tls depended on by both
thread and do_start, and remove tls from merge_relocatable_object(crt1).
Mark init_tls with [[gnu::flatten]] and compile tls with
${libc_opt_high_flag}. Once tls.cpp.o is in libc.a rather than first on
the link line inside crt1.o, an earlier object compiled with
-fstack-protector-strong can otherwise win COMDAT selection for
LIBC_INLINE helpers (e.g. linux_syscalls::getrandom) in -O0 builds and
read %fs:0x28 before set_thread_ptr initializes the thread pointer.
Change AppProperties app in libc/config/linux/app.h from extern
[[gnu::weak]] (which resolved to NULL without crt1.o) to
LIBC_INLINE_VAR, providing a COMDAT-deduplicated .bss definition shared
by crt1.o and libc.a, matching auxv::value.
Assisted-by: Automated tooling, human reviewed.
Added:
libc/src/__support/threads/linux/aarch64/CMakeLists.txt
libc/src/__support/threads/linux/aarch64/tls.cpp
libc/src/__support/threads/linux/riscv/CMakeLists.txt
libc/src/__support/threads/linux/riscv/tls.cpp
libc/src/__support/threads/linux/x86_64/CMakeLists.txt
libc/src/__support/threads/linux/x86_64/tls.cpp
Modified:
libc/config/linux/app.h
libc/src/__support/threads/linux/CMakeLists.txt
libc/startup/linux/CMakeLists.txt
libc/startup/linux/aarch64/CMakeLists.txt
libc/startup/linux/do_start.cpp
libc/startup/linux/riscv/CMakeLists.txt
libc/startup/linux/x86_64/CMakeLists.txt
Removed:
libc/startup/linux/aarch64/tls.cpp
libc/startup/linux/riscv/tls.cpp
libc/startup/linux/x86_64/tls.cpp
################################################################################
diff --git a/libc/config/linux/app.h b/libc/config/linux/app.h
index ff4070eead0ca4..35d14f24df4617 100644
--- a/libc/config/linux/app.h
+++ b/libc/config/linux/app.h
@@ -10,6 +10,7 @@
#define LLVM_LIBC_CONFIG_LINUX_APP_H
#include "hdr/stdint_proxy.h"
+#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
@@ -61,7 +62,7 @@ struct AppProperties {
uintptr_t *env_ptr;
};
-[[gnu::weak]] extern AppProperties app;
+LIBC_INLINE_VAR AppProperties app;
// The descriptor of a thread's TLS area.
struct TLSDescriptor {
diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt
index ae449c1af799d7..fe9cb41b12877f 100644
--- a/libc/src/__support/threads/linux/CMakeLists.txt
+++ b/libc/src/__support/threads/linux/CMakeLists.txt
@@ -40,12 +40,27 @@ add_header_library(
libc.src.__support.time.abs_timeout
)
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
+ add_subdirectory(${LIBC_TARGET_ARCHITECTURE})
+endif()
+
+if(TARGET libc.src.__support.threads.linux.${LIBC_TARGET_ARCHITECTURE}.tls)
+ add_object_library(
+ tls
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_ARCHITECTURE}.tls
+ )
+ set(thread_tls_dep .tls)
+endif()
+
add_object_library(
thread
SRCS
thread.cpp
DEPENDS
.futex_utils
+ ${thread_tls_dep}
libc.config.app_h
libc.include.sys_syscall
libc.hdr.fcntl_macros
diff --git a/libc/src/__support/threads/linux/aarch64/CMakeLists.txt b/libc/src/__support/threads/linux/aarch64/CMakeLists.txt
new file mode 100644
index 00000000000000..b83ccbb1ee05fb
--- /dev/null
+++ b/libc/src/__support/threads/linux/aarch64/CMakeLists.txt
@@ -0,0 +1,20 @@
+add_object_library(
+ tls
+ SRCS
+ tls.cpp
+ DEPENDS
+ libc.config.app_h
+ libc.hdr.sys_mman_macros
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
+ libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
+ libc.src.__support.threads.linux.tcb
+ libc.src.string.memory_utils.inline_memcpy
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ -fno-stack-protector
+ -fno-omit-frame-pointer
+ -ffreestanding
+ -fno-builtin
+)
diff --git a/libc/startup/linux/aarch64/tls.cpp b/libc/src/__support/threads/linux/aarch64/tls.cpp
similarity index 96%
rename from libc/startup/linux/aarch64/tls.cpp
rename to libc/src/__support/threads/linux/aarch64/tls.cpp
index c7a4364ea2e2f3..fef46c109fa338 100644
--- a/libc/startup/linux/aarch64/tls.cpp
+++ b/libc/src/__support/threads/linux/aarch64/tls.cpp
@@ -12,7 +12,7 @@
#include "src/__support/OSUtil/linux/syscall_wrappers/munmap.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/macros/config.h"
-#include "src/__support/threads/tcb.h"
+#include "src/__support/threads/linux/tcb.h"
#include "src/string/memory_utils/inline_memcpy.h"
#include <arm_acle.h>
@@ -23,7 +23,7 @@
namespace LIBC_NAMESPACE_DECL {
-void init_tls(TLSDescriptor &tls_descriptor) {
+[[gnu::flatten]] void init_tls(TLSDescriptor &tls_descriptor) {
// aarch64 follows the variant 1 TLS layout:
//
// 1. First entry is the dynamic thread vector pointer
diff --git a/libc/src/__support/threads/linux/riscv/CMakeLists.txt b/libc/src/__support/threads/linux/riscv/CMakeLists.txt
new file mode 100644
index 00000000000000..b83ccbb1ee05fb
--- /dev/null
+++ b/libc/src/__support/threads/linux/riscv/CMakeLists.txt
@@ -0,0 +1,20 @@
+add_object_library(
+ tls
+ SRCS
+ tls.cpp
+ DEPENDS
+ libc.config.app_h
+ libc.hdr.sys_mman_macros
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
+ libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
+ libc.src.__support.threads.linux.tcb
+ libc.src.string.memory_utils.inline_memcpy
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ -fno-stack-protector
+ -fno-omit-frame-pointer
+ -ffreestanding
+ -fno-builtin
+)
diff --git a/libc/startup/linux/riscv/tls.cpp b/libc/src/__support/threads/linux/riscv/tls.cpp
similarity index 94%
rename from libc/startup/linux/riscv/tls.cpp
rename to libc/src/__support/threads/linux/riscv/tls.cpp
index f6d60ee3e6d27f..5bd338dbd991da 100644
--- a/libc/startup/linux/riscv/tls.cpp
+++ b/libc/src/__support/threads/linux/riscv/tls.cpp
@@ -12,13 +12,13 @@
#include "src/__support/OSUtil/linux/syscall_wrappers/munmap.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/macros/config.h"
-#include "src/__support/threads/tcb.h"
+#include "src/__support/threads/linux/tcb.h"
#include "src/string/memory_utils/inline_memcpy.h"
#include <sys/syscall.h>
namespace LIBC_NAMESPACE_DECL {
-void init_tls(TLSDescriptor &tls_descriptor) {
+[[gnu::flatten]] void init_tls(TLSDescriptor &tls_descriptor) {
// riscv follows the variant 1 TLS layout:
const uintptr_t TCB_SIZE = sizeof(ThreadControlBlock);
uintptr_t padding = 0;
diff --git a/libc/src/__support/threads/linux/x86_64/CMakeLists.txt b/libc/src/__support/threads/linux/x86_64/CMakeLists.txt
new file mode 100644
index 00000000000000..e827fb2d7e9c07
--- /dev/null
+++ b/libc/src/__support/threads/linux/x86_64/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_object_library(
+ tls
+ SRCS
+ tls.cpp
+ DEPENDS
+ libc.config.app_h
+ libc.hdr.sys_mman_macros
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.getrandom
+ libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
+ libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
+ libc.src.__support.threads.linux.tcb
+ libc.src.string.memory_utils.inline_memcpy
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ -fno-stack-protector
+ -fno-omit-frame-pointer
+ -ffreestanding
+ -fno-builtin
+)
diff --git a/libc/startup/linux/x86_64/tls.cpp b/libc/src/__support/threads/linux/x86_64/tls.cpp
similarity index 96%
rename from libc/startup/linux/x86_64/tls.cpp
rename to libc/src/__support/threads/linux/x86_64/tls.cpp
index f7436f60e065e8..82462e3975ae08 100644
--- a/libc/startup/linux/x86_64/tls.cpp
+++ b/libc/src/__support/threads/linux/x86_64/tls.cpp
@@ -12,7 +12,7 @@
#include "src/__support/OSUtil/linux/syscall_wrappers/mmap.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/munmap.h"
#include "src/__support/macros/config.h"
-#include "src/__support/threads/tcb.h"
+#include "src/__support/threads/linux/tcb.h"
#include "src/string/memory_utils/inline_memcpy.h"
#include <asm/prctl.h>
@@ -21,7 +21,7 @@
namespace LIBC_NAMESPACE_DECL {
// TODO: Also generalize this routine and handle dynamic loading properly.
-void init_tls(TLSDescriptor &tls_descriptor) {
+[[gnu::flatten]] void init_tls(TLSDescriptor &tls_descriptor) {
// We will assume the alignment is always a power of two.
uintptr_t tls_size = app.tls.size & -app.tls.align;
if (tls_size != app.tls.size)
diff --git a/libc/startup/linux/CMakeLists.txt b/libc/startup/linux/CMakeLists.txt
index e798b00e8819ae..04647dc4c612ca 100644
--- a/libc/startup/linux/CMakeLists.txt
+++ b/libc/startup/linux/CMakeLists.txt
@@ -124,6 +124,7 @@ add_object_library(
libc.src.__support.threads.tcb
libc.src.__support.threads.thread
libc.src.__support.threads.linux.futex_utils
+ libc.src.__support.threads.linux.tls
libc.src.__support.macros.config
libc.startup.linux.${LIBC_TARGET_ARCHITECTURE}.irelative
libc.src.link._r_debug
@@ -142,7 +143,6 @@ add_object_library(
merge_relocatable_object(
crt1
.${LIBC_TARGET_ARCHITECTURE}.start
- .${LIBC_TARGET_ARCHITECTURE}.tls
.${LIBC_TARGET_ARCHITECTURE}.irelative
.do_start
.gnu_property_section
diff --git a/libc/startup/linux/aarch64/CMakeLists.txt b/libc/startup/linux/aarch64/CMakeLists.txt
index 512ce24ba16587..a50d6d55e47d2d 100644
--- a/libc/startup/linux/aarch64/CMakeLists.txt
+++ b/libc/startup/linux/aarch64/CMakeLists.txt
@@ -1,21 +1,3 @@
-add_startup_object(
- tls
- SRC
- tls.cpp
- DEPENDS
- libc.config.app_h
- libc.hdr.sys_mman_macros
- libc.include.sys_syscall
- libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
- libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
- libc.src.__support.OSUtil.osutil
- libc.src.__support.threads.tcb
- libc.src.string.memory_utils.inline_memcpy
- COMPILE_OPTIONS
- -fno-omit-frame-pointer
- -ffreestanding # To avoid compiler warnings about calling the main function.
-)
-
add_startup_object(
start
SRC
diff --git a/libc/startup/linux/do_start.cpp b/libc/startup/linux/do_start.cpp
index b38929b66996f4..54b5dbebaafd42 100644
--- a/libc/startup/linux/do_start.cpp
+++ b/libc/startup/linux/do_start.cpp
@@ -55,7 +55,6 @@ void _r_debug_state() { // NOLINT
}
namespace LIBC_NAMESPACE_DECL {
-AppProperties app;
static struct link_map main_map;
diff --git a/libc/startup/linux/riscv/CMakeLists.txt b/libc/startup/linux/riscv/CMakeLists.txt
index be09b7e620d042..bca19fb374d241 100644
--- a/libc/startup/linux/riscv/CMakeLists.txt
+++ b/libc/startup/linux/riscv/CMakeLists.txt
@@ -1,21 +1,3 @@
-add_startup_object(
- tls
- SRC
- tls.cpp
- DEPENDS
- libc.config.app_h
- libc.hdr.sys_mman_macros
- libc.include.sys_syscall
- libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
- libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
- libc.src.__support.OSUtil.osutil
- libc.src.__support.threads.tcb
- libc.src.string.memory_utils.inline_memcpy
- COMPILE_OPTIONS
- -fno-omit-frame-pointer
- -ffreestanding # To avoid compiler warnings about calling the main function.
-)
-
add_startup_object(
start
SRC
diff --git a/libc/startup/linux/x86_64/CMakeLists.txt b/libc/startup/linux/x86_64/CMakeLists.txt
index a0938d403411e5..ac0a95f8f2d1d2 100644
--- a/libc/startup/linux/x86_64/CMakeLists.txt
+++ b/libc/startup/linux/x86_64/CMakeLists.txt
@@ -1,24 +1,3 @@
-add_startup_object(
- tls
- SRC
- tls.cpp
- DEPENDS
- libc.config.app_h
- libc.hdr.sys_mman_macros
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
- libc.src.__support.OSUtil.linux.syscall_wrappers.getrandom
- libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
- libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
- libc.src.__support.threads.tcb
- libc.src.string.memory_utils.inline_memcpy
- COMPILE_OPTIONS
- -fno-stack-protector
- -fno-omit-frame-pointer
- -ffreestanding
- -fno-builtin
-)
-
add_startup_object(
start
SRC
More information about the libc-commits
mailing list