如何在Linux AMD64中使用fs / gs寄存器?

时间:2011-07-07 13:27:57

标签: linux assembly architecture x86 x86-64

在x86-64架构上,两个寄存器有一个特殊用途:FS和GS。在linux 2.6。*中,FS寄存器似乎用于存储线程本地信息。

  • 这是对的吗?
  • fs:0中存储的内容是什么?是否有描述此内容的C结构?
  • 那么GS的用途是什么?

3 个答案:

答案 0 :(得分:37)

在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 pthreadtcbhead_t开头(这取决于架构,请参阅宏TLS_DTV_AT_TPTLS_TCB_AT_TP)。该线程控制块头(AFAIU)包含一些即使存在单个线程也需要的字段。 DTV是动态线程向量,包含指向通过dlopen()加载的DSO的TLS块的指针。在TCB之前或之后,存在用于在(程序)加载时链接的可执行文件和DSO的静态TLS块。 TCB和DTV在Ulrich Drepper's TLS document中得到了很好的解释(请参阅第3章中的图表)。

答案 1 :(得分:16)

要实际回答您的fs:0问题:x86_64 ABI要求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

编译到

%gs

i686使用Conf.FilesLocation做同样的事情。在aarch64上,这不是必需的,因为可以从tls寄存器本身读取地址。

答案 2 :(得分:2)

那么GS的用途是什么?

x86_64 Linux内核使用GS寄存器作为一种高效的方法来获取内核空间堆栈以进行系统调用。

GS寄存器存储每个CPU区域的基地址。要获取内核空间堆栈,请在entry_SYSCALL_64

movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp

扩展PER_CPU_VAR后,我们得到以下信息:

movq    %gs:cpu_current_top_of_stack, %rsp