ELF对线程局部储存的处理(8)

6.        ELF 新定义

这一节显示了,对于描述扩展 ELF 格式必须的,新引入的常量的实际定义。通用的扩展是:

#define SHF_TLS  (1 << 10)

#define STT_TLS   6

#define PT_TLS     7

6.1. IA-64 ELF 定义

#define R_IA64_TPREL14                  0x91 /* @tprel (sym+add), imm14 */

#define R_IA64_TPREL22                  0x92 /* @tprel (sym+add), imm22 */

#define R_IA64_TPREL64I                0x93 /* @tprel (sym+add), imm64 */

#define R_IA64_TPREL64MSB          0x96 /* @tprel (sym+add), data8 MSB */

#define R_IA64_TPREL64LSB           0x97 /* @tprel (sym+add), data8 LSB */

#define R_IA64_LTOFF_TPREL22      0x9a /* @ltoff (@tprel) (s+a)), imm2 */

#define R_IA64_DPTMOD64MSB      0xa6 /* @dtpmod (sym+add), data8 MSB */

#define R_IA64_DPTMOD64LSB       0xa7 /* @dtpmod (sym+add), data8 LSB */

#define R_IA64_LTOFF_DTPMOD22  0xaa /* @ltoff (@dtpmod (sym+add)), imm22 */

#define R_IA64_DTPREL14               0xb1 /* @dtprel (sym+add), imm14 */

#define R_IA64_DTPREL22               0xb2 /* @dtprel (sym+add), imm22 */

#define R_IA64_DTPREL64I              0xb3 /* @dtprel (sym+add), imm64 */

#define R_IA64_DTPREL32MSB        0xb4 /* @dtprel (sym+add), data4 MSB */

#define R_IA64_DTPREL32LSB         0xb5 /* @dtprel (sym+add), data4 LSB */

#define R_IA64_DTPREL64MSB        0xb6 /* @dtprel (sym+add), data8 MSB */

#define R_IA64_DTPREL64LSB         0xb7 /* @dtprel (sym+add), data4 LSB */

#define R_IA64_LTOFF_DTPREL22   0xba /* @ltoff (@dtprel (s+a)), imm22 */

在代码序列中用到的操作符被定义如下:

@ltoff (expr) 要求构建一个将保存 expr 完整值的 GOT 项,并计算到这个 GOT 项的 gp 相关的移位( displacement )。

@tprel (expr) 计算一个 tp 相关的移位——有效地址与线程指针值之间的差值。该表达式必须评估在一个线程特定数据段的一个有效地址。

@dtpmod (expr) 计算,对应于包含被该重定位引用的符号定义的,加载模块的索引。当与操作符 @ltoff () 结合在一起使用时,它评估一个,保存这个计算出来的加载模块索引的,可链接表项的 gp 相对偏移。

@dtprel (expr) 计算一个 dtv 相关的移位——有效地址与包含被该重定位引用的符号定义的线程局部储存块基址之间的差值。当与操作符 @ltoff () 结合在一起使用时,它评估一个,保存这个计算出来的移位的,链接表项的 gp 相对偏移。

6.2. IA-32 ELF 定义

#define R_386_TLS_TPOFF         14 /* Negative offset in static TLS block (GNU version */

#define R_386_TLS_IE                15 /* Absolute address of GOT entry for negative static

TLS block offset */

#define R_386_TLS_GOTIE         16 /* GOT entry for negative static TLS block offset */

#define R_386_TLS_LE                17 /* Negative offset relative to static TLS (GNU version) */

#define R_386_TLS_GD               18 /* Direct 32 bit for GNU version of GD TLS */

#define R_386_TLS_LDM            19 /* Direct 32 bit for GNU version of LD TLS in

LE code */

#define R_386_TLS_GD_32          24 /* Direct 32 bit fir GD TLS */

#define R_386_TLS_GD_PUSH    25 /* Tag for pushl in GD TLS code */

#define R_386_TLS_GD_CALL    26 /* Relocation for call to __tls_get_addr() */

#define R_386_TLS_GD_POP       27 /* Tag for popl in GD TLS code */

#define R_386_TLS_LDM_32       28 /* Direct 32 bit for local dynamic code */

#define R_386_TLS_LDM_PUSH  29 /* Tag for pushl in LDM TLS code */

#define R_386_TLS_LDM_CALL  30 /* Relocation for call to __tls_get_addr() in LDM

code */

#define R_386_TLS_LDM_POP    31 /* Tag for popl in LDM TLS code */

#define R_386_TLS_LDO_32        32 /* Offset relative to TLS block */

#define R_386_TLS_IE_32           33 /* GOT entry for negated static TLS block offset */

#define R_386_TLS_LE_32          34 /* Negated offset relative to static TLS block */

#define R_386_TLS_DTPMOD32  35 /* ID of module containing symbol */

#define R_386_TLS_DTPOFF32   36 /* Offset in TLS block */

#define R_386_TLS_TPOFF32      37 /* Negated offset in static TLS block */

在代码序列中用到的操作符被定义如下:

@dtlndx (expr) GOT 中分配两个连续项来保存一个 tls_index 结构(用于传递给 __tls_get_addr )。引用这个项的指令将被绑定到这两个 GOT 项中的第一个。

@tlsgd (expr) 这个表达式,在 GNU 版本的调用规范中,等价于 @dtlindx (expr) 。链接器也是在 GOT 中分配两个连续的项,并处理这个重定位产生第一个项的偏移作为这个表达式的值。唯一的区别在于被调用的函数是 ___tls_get_addr

@tlsptl 这个表达式用在 Sun 版本的对 __tls_get_addr call 指令中。这个 call 指令关联其所在整个代码序列处理的符号。为这个指令产生的 R_386_TLS_xxx _CALL 重定位将引用这个符号。链接器将向 __tls_get_addr 插入一个引用。

@tmndx (expr) GOT 中分配两个连续的项来保存一个 tls_index 结构(用于传递给 __tls_get_addr )。这个对象的 ti_offset 域将被设置为 0 ,而 ti_module 域在运行时填充。对 __tls_get_addr 的调用将返回动态 TLS 块的起始偏移。

@tlsldm (expr) 这个表达式是 GNU 版本的 @tmndx (expr) 。正如 @tlsgd (expr) ,唯一的区别在于,在紧跟着的 call 指令中调用的是 ___tsk_get_addr

@dtpoff 添加并计算变量相对于 TLS 块的偏移。这个值用作加数的立即值,并且不与特定寄存器关联。

@tpoff 添加并计算变量相对于静态 TLS 块的偏移。链接器为这个重定位的结果分配一个 GOT 项。

这个操作符必须被用于计算一个立即数。如果这个被引用的变量没有定义,或者它不是可执行映像的代码,链接器将报告错误。在这个情形下没有 GOT 项被创建。

如果使用 @tpoff (expr) 形式,则会计算在 expr 中的变量相对于静态 TLS 块的偏移。链接器为这个重定位的结果分配一个 GOT 项。

@ntpoff 添加并计算变量的相对于静态 TLS 块的负偏移。

这个操作符必须被用于计算一个立即数。如果这个被引用的变量没有定义,或者它不是可执行映像的代码,链接器将报告错误。在这个情形下没有 GOT 项被创建。

@gotntpoff 这个表达式的 GNU 版本的 @tpoff (expr) 。区别在于由它分配的 GOT 槽必须被加到一个变量,另外用于与这个代码序列相关的 movl addl 汇编指令的重定位,被链接器转换到局部可执行模式。

@gotntpoff 同样也不用于立即指令。相反 GNU 版本的局部可执行模式也将使用 @tpoff 表达式。因为局部可执行模式是尽可能简单的,链接器不需要了解两个版本的差别。没有转换可以被执行,因此这个表达式可以被单独地使用,让链接器填入正确的偏移。

@indntpoff 这个表达式类似于 @gotntpoff ,但用于位置无关代码。作为比较, @gotntpoff 解析到 GOT 项,相对于 movl addl 指令中的 GOT 开头,的地址。而 @indntpoff 解析到 GOT 项的绝对地址。

6.3. SPARC ELF 定义

#define R_SPARC_TLS_GD_HI22              56

#define R_SPARC_TLS_GD_LO10       57

#define R_SPARC_TLS_GD_ADD       58

#define R_SPARC_TLS_GD_CALL      59

#define R_SPARC_TLS_LDM_HI22     60

#define R_SPARC_TLS_LDM_LO10    61

#define R_SPARC_TLS_LDM_ADD     62

#define R_SPARC_TLS_LDM_CALL   63

#define R_SPARC_TLS_LDO_HIX22   64

#define R_SPARC_TLS_LDO_LOX10  65

#define R_SPARC_TLS_LDO_ADD     66

#define R_SPARC_TLS_IE_HI22         67

#define R_SPARC_TLS_IE_LO10        68

#define R_SPARC_TLS_IE_LD            69

#define R_SPARC_TLS_IE_LDX         70

#define R_SPARC_TLS_IE_ADD         71

#define R_SPARC_TLS_LE_HIX22      72

#define R_SPARC_TLS_LE_LOX10     73

#define R_SPARC_TLS_DTPMOD32   74

#define R_SPARC_TLS_DTPMOD64   75

#define R_SPARC_TLS_DTPOFF32     76

#define R_SPARC_TLS_DTPOFF64     77

#define R_SPARC_TLS_TPOFF32              78

#define R_SPARC_TLS_TPOFF64              79

在代码序列中用到的操作符被定义如下:

@dtlndx (expr) GOT 在分配两个连续的项来保存一个 tls_index 结构(用于传递给 __tls_get_addr )。引用这个项的指令将被绑定到这两个项中的第一个。

@tmndx (expr) (expr) GOT 在分配两个连续的项来保存一个 tls_index 结构(用于传递给 __tls_get_addr )。这个对象的 ti_offset 域将被设置为 0 ,而 ti_module 域在运行时填充。对 __tls_get_addr 的调用将返回动态 TLS 块的起始偏移。

@tlsldm (expr) 这个表达式是 GNU 版本的 @tmndx (expr) 。正如 @tlsgd (expr) ,唯一的区别在于,在紧跟着的 call 指令中调用的是 ___tsk_get_addr

@dtpoff 添加并计算变量相对于 TLS 块的偏移。这个值用作加数的立即值,并且不与特定寄存器关联。

@tpoff 添加并计算变量相对于静态 TLS 块的偏移。链接器为这个重定位的结果分配一个 GOT 项。

这个操作符必须被用于计算一个立即数。如果这个被引用的变量没有定义,或者它不是可执行映像的代码,链接器将报告错误。在这个情形下没有 GOT 项被创建。

如果使用 @tpoff (expr) 形式,则会计算在 expr 中的变量相对于静态 TLS 块的偏移。链接器为这个重定位的结果分配一个 GOT 项。

@gottpoff 代表在 GOT 中包含由重定位关联的 tls_index 的项的偏移。

6.4. x86-64 ELF 定义

#define R_X86_64_DTPMOD64    16 /* ID of module containing symbol */

#define R_X86_64_DTPOFF64     17 /* Offset in TLS block */

#define R_X86_64_TPOFF64        18 /* Offset in initial TLS block */

#define R_X86_64_TLSGD           19 /* PC relative offset to GD GOT block */

#define R_X86_64_TLSLD           20 /* PC relative offset to LD GOT block */

#define R_X86_64_DTPOFF32     21 /* Offset in TLS block */

#define R_X86_64_GOTTPOFF    22 /* PC relative offset to IE GOT entry */

#define R_X86_64_TPOFF32        23 /* Offset in initial TLS block */

在代码序列中用到的操作符被定义如下:

@tlsgd (%rip) GOT 在分配两个连续的项来保存一个 tls_index 结构(用于传递给 __tls_get_addr )。它可能仅被用在,上面所示的, x86-64 常规动态代码序列中。

@tlsld (%rip) GOT 在分配两个连续的项来保存一个 tls_index 结构(用于传递给 __tls_get_addr )。这个对象的 ti_offset 域将被设置为 0 ,而 ti_module 域在运行时填充。对 __tls_get_addr 的调用将返回动态 TLS 块的起始偏移。它可能仅用在上面所示的代码序列中。

@dtpoff 计算变量相对于 TLS 块的偏移。这个值用作加数的立即值,并且不与特定寄存器关联。

@gottpoff (%rip) 分配一个保存变量在初始 TLS 块中偏移(相对于 TLS 块尾, %fs:0 )的 GOT 项。这个操作符仅用在 movq addq 指令中。

@tpoff 计算变量相对于 TLS 尾的偏移, %fs:0 。不创建 GOT 项。

6.5. s390/s390x ELF 定义

#define R_390_TLS_LOAD          37 /* Tag for load insn in TLS code */

#define R_390_TLS_GDCALL      38 /* Tag for call insn in TLS code */

#define R_390_TLS_LDCALL       39 /* Tag for call insn in TLS code */

#define R_390_TLS_GD32           40 /* Direct 32 bit for general dynamic thread local data */

#define R_390_TLS_GD64           41 /* Direct 64 bit for general dynamic thread local data */

#define R_390_TLS_GOTIE12      42 /* 12 bit GOT offset for static TLS block offset */

#define R_390_TLS_GOTIE32      43 /* 32 bit GOT offset for static TLS block offset */

#define R_390_TLS_GOTIE64      44 /* 64 bit GOT offset for static TLS block offset */

#define R_390_TLS_LDM32         45 /* Direct 32 bit for local dynamic thread local data in

LE code */

#define R_390_TLS_LDM64         46 /* Direct 64 bit for local dynamic thread local data in

                                  LE code */

#define R_390_TLS_IE32             47 /* 32 bit address of GOT entry for negated static TLS

                                 block offset */

#define R_390_TLS_IE64             48 /* 64 bit address of GOT entry for negated static TLS

                                  block offset */

#define R_390_TLS_IEENT          49 /* 32 bit rel. offset to GOT entry for negated static TLS

                                 block offset */

#define R_390_TLS_LE32            50 /* 32 bit negated offset relative to static TLS block */

#define R_390_TLS_LE64            51 /* 64 bit negated offset relative to static TLS block */

#define R_390_TLS_LDO32         52 /* 32 bit offset relative to TLS block */

#define R_390_TLS_LDO64         53 /* 64 bit offset relative to TLS block */

#define R_390_TLS_DTPMO D     54 /* ID of module containing symbol */

#define R_390_TLS_DTPOFF       55 /* Offset in TLS block */

#define R_390_TLS_TPOFF         56 /* Negated offset in static TLS block */

在代码序列中用到的操作符被定义如下:

@tlsgd GOT 在分配两个连续的项来保存一个 tls_index 结构。表达式 x@tlsgd 的值是,符号 x tls_index 结构到 GOT 开头的偏移。使用这个偏移来调用 __tls_get_offset ,将返回线程局部变量 x TCB 指针的偏移。操作符 @tlsgd 可能仅用在上面所示的常规动态访问模式中。

@tlsldm GOT 在分配两个连续的项来保存一个 tls_index 结构。这个对象的 ti_offset 域将被设置为 0 ,而 ti_module 域在运行时填充。对 __tls_get_addr 的调用将返回动态 TLS 块的起始偏移。表达式 x@tlsldm 的值是从 GOT 开头到这个 tls_index 结构的偏移。使用这个偏移调用 __tls_get_offset 将返回这个动态 TLS 块到 TCB 指针的偏移。操作符 @tlsldm 可能仅用在上面所示的局部动态访问模式中。

@dtpoff 计算变量相对于 TLS 块开头的偏移。操作符 @dtpoff 可能仅用在上面所示的局部动态访问模式中。

@ntpoff 表达式 @ntpoff 的值是线程局部变量 x 相对于 TCB 指针的偏移。在这个情形中,不创建 GOT 项。操作符 @ntpoff 可能仅用在上面所示的局部可执行模式中。

@gotntpoff 分配一个 GOT 项来保存在初始 TLS 块中的变量相对于 TCB 指针的偏移。表达式 x@gotntpoff 的值是分配的项在 GOT 中的偏移。操作符 @gotntpoff 可能仅用在上面所示的初始可执行模式中。

@indntpoff 这个表达式类似于 @gotntpoff 。区别在于 x@indntpoff 不是一个 GOT 偏移,而是分配的 GOT 项自己的地址。它连同 larl 指令,用在位置无关代码中。操作符 @indntpoff 可能仅用在上面所示的初始可执行模式中。

7.      修改历史

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值