In my previous talks at BSDCan 2025 and EuroBSDCon 2025 I discussed how the compiler, static linker, and runtime loader work together to map abstract symbol names in source code to concrete addresses runtime. Those prior talks focused on symbols with (mostly) fixed addresses such as global variables and function symbols. However, C and C++ support another class of symbols that are mapped to per-thread storage: where the same abstract name maps to a different runtime address in each thread.
This talk will cover the abstract model of thread local storage (TLS) on FreeBSD including the data structures used such as the static TLS block and DTV array. It will also describe different methods of storing these data structures in memory (Variant I and Variant II) as well as the four different modes of TLS access employed by the toolchain (local-exec, initial-exec, local-dynamic, general-dynamic).