此代码序列实现线程局部存储的访问模型中介绍的 IE 模型。
IE 模型存在两个代码序列。一个序列用于使用 GOT 指针的位置无关代码。另一个序列用于不使用 GOT 指针的位置相关代码。
表 8–10 32 位 x86: 初始可执行的、位置无关线程局部变量的访问代码
代码序列 |
初始重定位 |
符号 |
0x00 movl %gs:0, %eax 0x06 addl x@gotntpoff(%ebx), %eax # %eax - contains address of TLS variable |
<none> R_386_TLS_GOTIE |
x |
未完成的重定位 |
符号 |
|
GOT[n] |
R_386_TLS_TPOFF |
x |
addl 指令生成 R_386_TLS_GOTIE 重定位。此重定位指示链接编辑器在 GOT 中创建空间,以存储符号 x 的静态 TLS 偏移。针对 GOT 表的 R_386_TLS_TPOFF 重定位未完成,以便运行时链接程序使用符号 x 的静态 TLS 偏移填充。
表 8–11 32 位 x86: 初始可执行的、位置相关线程局部变量的访问代码
代码序列 |
初始重定位 |
符号 |
0x00 movl %gs:0, %eax 0x06 addl x@indntpoff, %eax # %eax - contains address of TLS variable |
<none> R_386_TLS_IE |
x |
未完成的重定位 |
符号 |
|
GOT[n] |
R_386_TLS_TPOFF |
x |
addl 指令生成 R_386_TLS_IE 重定位。此重定位指示链接编辑器在 GOT 中创建空间,以存储符号 x 的静态 TLS 偏移。此序列和位置无关序列之间的主要差别在于,指令直接绑定到所创建的 GOT 项,而不是使用 GOT 指针寄存器的偏移。针对 GOT 的 R_386_TLS_TPOFF 重定位未完成,以便运行时链接程序使用符号 x 的静态 TLS 偏移填充。
将偏移直接嵌入到内存引用中可以装入变量 x 的内容(而不是地址),如下面两个序列中所示。
表 8–12 32 位 x86: 初始可执行的、位置无关动态线程局部变量的访问代码
代码序列 |
初始重定位 |
符号 |
0x00 movl x@gotntpoff(%ebx), %eax 0x06 movl %gs:(%eax), %eax # %eax - contains address of TLS variable |
R_386_TLS_GOTIE <none> |
x |
未完成的重定位 |
符号 |
|
GOT[n] |
R_386_TLS_TPOFF |
x |
表 8–13 32 位 x86: 初始可执行的、位置无关线程局部变量的访问代码
代码序列 |
初始重定位 |
符号 |
0x00 movl x@indntpoff, %ecx 0x06 movl %gs:(%ecx), %eax # %eax - contains address of TLS variable |
R_386_TLS_IE <none> |
x |
未完成的重定位 |
符号 |
|
GOT[n] |
R_386_TLS_TPOFF |
x |
在最后一个序列中,如果使用的是 %eax 寄存器而不是 %ecx 寄存器,则第一个指令的长度可为 5 或 6 字节。