链接程序和库指南

32 位 x86: 初始可执行 (Initial Executable, IE)

此代码序列实现线程局部存储的访问模型中介绍的 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 指针寄存器的偏移。针对 GOTR_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 字节。