【问题标题】:What are the real ELF TLS ABI requirements for each cpu arch?每个 cpu 架构的真正 ELF TLS ABI 要求是什么?
【发布时间】:2012-10-04 10:16:08
【问题描述】:

Ulrich Drepper's paper on thread-local storage 概述了几种不同 cpu 架构的 TLS ABI,但我发现它不足以作为实现 TLS 的基础,原因有两个:

  1. 它省略了一些重要的架构,如 ARM、MIPS 等(同时包括一堆完全不相关的架构,如安腾)
  2. 更重要的是,它将许多实现细节与 ABI 混合在一起,因此很难区分互操作性需要哪些属性,而哪些只是其实现的方面。

例如,i386 的唯一实际 ABI 要求是:

  • %gs:0 指向一个指向自身的指针。
  • 主可执行文件的 TLS 段(如果有)必须位于距该地址的固定(由链接器确定为负)偏移处。
  • 初始加载的库的所有其他 TLS 段必须有一个运行时常量(即每个线程相同,但不同程序运行之间不一定相同)相对于该地址的偏移量(并且动态链接器必须能够填充在具有这些偏移量的重定位中)。
  • ___tls_get_addr__tls_get_addr 函数必须具有正确的语义才能查找任意 TLS 段。

特别是,DTV 的存在或布局不是 ABI 的一部分,除主程序之外,TLS 段的排序/布局也不是。

似乎任何使用“TLS 变体 II”的拱门都大致具有上述 ABI 要求。但是我根本不太了解“TLS 变体 I”的要求,而且从阅读资料(在 uClibc 和 glibc 中)看来,甚至可能存在多个“变体 I”的变体。

是否有更好的文档我应该查看,或者熟悉 TLS 工作原理的人可以向我解释 ABI 要求吗?

【问题讨论】:

  • 很抱歉,如果我问的是显而易见的问题,但您检查过GCC TLS 支持吗?例如,gcc-patches 邮件列表从今年 6 月 1 日开始有一个线程,关于添加 MIPS16 TLS 支持 (marc.info/?l=gcc-patches&m=132586147826602)。编译器人员似乎比 C 库开发人员更正式地处理这类事情。他们可能有更好的正式文档。

标签: c linux elf abi thread-local-storage


【解决方案1】:

到目前为止我能收集到的最好的东西是:

对于任一 TLS 变体,__tls_get_addr 或其他特定于架构的函数必须存在并且具有查找任何 TLS 对象的正确语义,并且任何两个 TLS 段之间的相对偏移量必须是运行时常量(每个线程)。

对于 TLS 变体 II(i386 等),“线程指针寄存器”(实际上可能不是寄存器,但可能是 %gs:0 之类的某种机制,甚至是进入内核空间的陷阱;为简单起见,我们只调用它是一个寄存器)指向主可执行文件的 TLS 段的 刚刚结束,其中“刚结束”包括四​​舍五入到 TLS 段对齐的下一个倍数。

对于 TLS 变体 I,“线程指针寄存器”指向主可执行文件的 TLS 段的开始处的某个固定偏移量。此偏移量因拱门而异。 (在一些丑陋的 RISC 拱门上选择了它来最大化通过有符号的 16 位偏移量可访问的 TLS 数量,这让我觉得非常无用,因为编译器无法知道重定位的偏移量是否适合 16 位,因此必须总是使用 load-upper/add 指令生成更慢、更大的 32 位偏移代码)。

据我所知,TCB、DTV 等都不是 ABI 的一部分,因为不允许应用程序访问这些结构,也不允许除主可执行文件之外的任何 TLS 段的位置ABI 的一部分。在变体 I 和 II 中,将线程的实现内部信息存储在距“线程指针寄存器”的固定偏移量处是有意义的,无论哪种方式都可以安全地避免重叠 TLS 段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    • 1970-01-01
    • 2011-02-03
    • 2016-10-06
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多