SPARC: 常规动态 (General Dynamic, GD)
SPARC: 局部动态 (Local Dynamic, LD)
32 位 SPARC: 初始可执行 (Initial Executable, IE)
64 位 SPARC: 初始可执行 (Initial Executable, IE)
SPARC: 局部可执行 (Local Executable, LE)
32 位 x86: 常规动态 (General Dynamic, GD)
32 位 x86: 初始可执行 (Initial Executable, IE)
32 位 x86: 局部可执行 (Local Executable, LE)
x64: 常规动态 (General Dynamic, GD)
x64: 初始可执行 (Initial Executable, IE)
x64: 局部可执行 (Local Executable, LE)
编译时分配的线程局部数据的独立副本必须与各个执行线程关联。要提供此数据,要使用 TLS 节指定大小和初始内容。编译环境在 SHF_TLS 标志标识的节中分配 TLS。这些节根据存储的声明方式提供已初始化的 TLS 和未初始化的 TLS。
已初始化的线程局部变量分配在 .tdata 或 .tdata1 节中。此初始化可能需要重定位。
未初始化的线程局部变量定义为 COMMON 符号。最终分配在 .tbss 节中进行。
在分配了任何已初始化的节后会立即分配未初始化的节,并进行填充以便正确对齐。合并的节一起构成 TLS 模板,每次创建新线程时,都会使用此模板分配 TLS。此模板的已初始化部分称为 TLS 初始化映像。所有因已初始化的线程局部变量而生成的重定位将应用于此模板。当新线程需要初始值时,将使用重定位的值。
TLS 符号的符号类型为 STT_TLS。这些符号被指定了相对于 TLS 模板开头的偏移。与这些符号关联的实际虚拟地址与此无关。地址仅指向模板,而不指向每个数据项的每线程副本。在动态可执行文件和共享目标文件中,对于已定义符号,STT_TLS 符号的 st_value 字段包含指定的 TLS 偏移。对于未定义的符号,此字段包含零。
定义了多个重定位以支持访问 TLS。请参见SPARC: 线程局部存储的重定位类型、32 位 x86: 线程局部存储的重定位类型和x64: 线程局部存储的重定位类型。通常,TLS 重定位引用 STT_TLS 类型的符号。TLS 重定位还可以引用与 GOT 项关联的局部节符号。在这种情况下,指定的 TLS 偏移存储在关联的 GOT 项中。
对于根据 TLS 项进行的重定位,重定位地址在 TLS 模板的末尾编码为负偏移。计算该偏移时,首先将模板大小舍入到 32 位目标文件中最接近的 8 字节边界,然后舍入为 64 位目标文件中最接近的 16 字节边界。此舍入操作确保静态 TLS 模板合理对齐以便可用于任何用途。
在动态可执行文件和共享目标文件中,PT_TLS 程序项用于描述 TLS 模板。此模板包含以下成员:
表 8-1 ELF PT_TLS 程序头项
|