Search code examples
assemblyx86-64abibare-metalthread-local-storage

`fs` relative address in x86-64


I am trying to use thread local storage in Rust on bare bones. I initially set the FsBase MSR to the target value. This is also confirmed by reading the FsBase register again and by running info registers fs_base in gdb.

When I try to read a thread local variable, rust generates the following asm code (disassembly from gdb)

mov    %fs:0x0,%rax
mov    -0x2000(%rax),%cl
mov    %cl,-0x189(%rbp)

When i try to step through these instructions, I observe that after instruction 1, the value of %rax stays as 0x0 rather than using the value in FsBase. This is not expected behavior.

In my case, the FsBase is set to 0xffffc00000002000. After running into instruction 3, the cpu raises a page fault exception with the target location being 0xffffffffffffe000 meaning that the instruction is trying to load data from 0x0 - 0x2000 rather than an offset from 0xffffc00000002000. This is not the expected behavior.

Are there more steps required to instantiate fs registers?


Solution

  • The code generation here is according to System V ABI as Ross mentioned in the comment. The ABI requires %fs:0 to be set to the value of %fs itself.

    So, here, setting the value at address 0xffffc00000002000 to be 0xffffc00000002000 satisfies the ABI and uses the FsBase as expected.

    In other words, mov %fs:0x0, %rax is trying to access the value at FsBase and not at 0x0. The value at FsBase just happens to be 0.