这一节显示了,对于描述扩展 ELF 格式必须的,新引入的常量的实际定义。通用的扩展是:
#define SHF_TLS (1 << 10)
#define STT_TLS 6
#define PT_TLS 7
#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 相对偏移。
#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 项的绝对地址。
#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 的项的偏移。
#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 项。
#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 可能仅用在上面所示的初始可执行模式中。
略