Hi,
As the title suggests, I am trying to write the FSBASE register of the app, directly after a new app thread gets created.
As far as I know, there are only two ways to do so, the first being the arch_prctl system call, and the second being the wrfsbase instruction.
So, here's what I do. I use drmgr_register_thread_init_event to create a TLS area for each thread. In the same function provided to it I try three different things separately (merged below for space):
dr_switch_to_app_state(dr_get_current_drcontext());
// I try reading here, this reads fine the original value of FSBASE and I am able to verify the variables fsbase_value and fs_value
asm inline("rdfsbase %0 \t\n"
"movq %%fs, %1 \t\n"
: "=&r"(fsbase_value), "=&r"(fs_value));
// This is trying the wrfsbase instruction, no effect
asm inline("wrfsbase %0 \t\n"
:
: "g" (SYSCALLREPLACEMENTS::virtual_tls));
// This is trying the syscall instead of the wrfsbase instruction, still no effect
asm inline("movq $0x9E, %%rax \t\n"
"movq $0x1002, %%rdi \t\n"
"movq %0, %%rsi \t\n"
"syscall \t\n"
:
: "g" (SYSCALLREPLACEMENTS::virtual_tls)
: "rax", "rdi", "rsi");
dr_switch_to_dr_state(dr_get_current_drcontext());
Googling a bit, it seems that wrfsbase and its family require enabling in the CR4 register. I don't know how check if it is enabled, but I will just assume it is not (even though its rdfsbase counterpart works fine).
But what about the syscall? Why does it not work? it does not produce any errors either, just no effect. What is the right way of creating a syscall in this condition? Or achieving what I want in general?
As a side question, I know DR uses the GS/GSBASE for its own TLS, but does it have any uses with FS/FSBASE that would cause interference with what I am doing?