在x86-64架构上,两个寄存器有一个特殊用途:FS和GS。在linux 2.6。*中,FS寄存器似乎被用来存储线程本地信息。Linux AMD64中使用的fs/gs寄存器如何?
- 这是正确的吗?
- 存储在fs:0的内容是什么?有没有描述这个内容的C结构?
- 什么是GS的使用?
在x86-64架构上,两个寄存器有一个特殊用途:FS和GS。在linux 2.6。*中,FS寄存器似乎被用来存储线程本地信息。Linux AMD64中使用的fs/gs寄存器如何?
在x86-64的有3 TLS entries,经由FS and GS入店其中的两个,FS由glibc的内部使用(在IA32显然FS is used by Wine and GS by glibc)。
Glibc将其TLS入口点指向包含一些线程内部结构的struct pthread
。 Glibc通常是指struct pthread
变量为pd
,推测为pthread描述符。
在x86-64上,struct pthread
以tcbhead_t
开头(这取决于体系结构,请参阅宏TLS_DTV_AT_TP
和TLS_TCB_AT_TP
)。此线程控制块标题AFAIU包含一些即使在单线程时也需要的字段。 DTV是动态线程向量,包含指向通过dlopen()
加载的DSO的TLS块的指针。在TCB之前或之后,有一个静态TLS块,用于在(程序)加载时链接的可执行文件和DSO。 TCB和DTV在Ulrich Drepper's TLS document中有相当好的解释(查看第3章中的图表)。
实际回答你的fs:0
问题:x86_64 ABI要求fs:0
包含fs
本身的“指向”地址。即,fs:-4
加载存储在fs:0 - 4
处的值。此功能是必需的,因为您无需通过内核代码即可轻松获取fs
指向的地址。使地址存储在fs:0
从而使线程本地存储的工作效率更高。
static __thread int test = 0;
int *f(void) {
return &test;
}
int g(void) {
return test;
}
编译成
f:
movq %fs:0, %rax
leaq -4(%rax), %rax
retq
g:
movl %fs:-4, %eax
retq
i686的不相同,但与%gs
:
您可以在行动,当你把一个线程局部变量的地址看到这一点。在aarch64上这不是必须的,因为地址可以从tls寄存器本身读取。
FS被x86上的win32用来指向windows线程信息 - wine与之相匹配。 –