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?
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.