R..*_*R.. 9 c linux elf abi thread-local-storage
Ulrich Drepper关于线程本地存储的论文概述了几种不同cpu架构的TLS ABI,但我发现它不足以作为实现TLS的基础,原因有两个:
例如,i386唯一的实际ABI要求是:
%gs:0
指向指向自身的指针.___tls_get_addr
并且__tls_get_addr
函数必须以正确的语义存在,以便查找任意TLS段.特别是,DTV的存在或布局不是 ABI的一部分,也不是主程序之外的TLS段的排序/布局.
似乎任何使用"TLS变体II"的拱门都具有大致上述ABI要求.但我完全不了解"TLS变体I"的要求,而且从阅读来源(在uClibc和glibc中)看来,甚至可能存在"变体I"的几种变体.
有没有更好的文件我应该看一下,或者熟悉TLS工作的人能向我解释ABI的要求吗?
到目前为止我能收集到的最好的信息是:
对于任一 TLS 变体,__tls_get_addr
或其他特定于架构的函数,必须存在并且具有用于查找任何 TLS 对象的正确语义,并且任何两个 TLS 段之间的相对偏移量必须是运行时常量(每个线程的偏移量相同)。
对于 TLS 变体 II(i386 等),“线程指针寄存器”(实际上可能不是寄存器,但可能是某种机制%gs:0
,甚至是内核空间的陷阱;为简单起见,我们将其称为寄存器)指向仅指向超过主可执行文件的 TLS 段的末尾,其中“刚刚超过末尾”包括向上舍入到 TLS 段对齐的下一个倍数。
对于 TLS 变体 I,“线程指针寄存器”指向距主可执行文件的 TLS 段开头的某个固定偏移量。该偏移量因牙弓而异。(在一些丑陋的 RISC 架构上选择它是为了最大化通过签名 16 位偏移量访问的 TLS 数量,这让我觉得非常无用,因为编译器无法知道重定位的偏移量是否适合 16 位,因此必须始终使用加载上部/添加指令生成较慢、较大的 32 位偏移代码)。
据我所知,关于 TCB、DTV 等的任何内容都不是 ABI 的一部分,因为不允许应用程序访问这些结构,除了主可执行文件部分之外的任何 TLS 段的位置也不是 ABI 的一部分。 ABI。在变体 I 和 II 中,将线程的实现内部信息存储在距“线程指针寄存器”的固定偏移处是有意义的,无论哪种方式都可以安全地避免重叠 TLS 段。