load_fs() and load_gs()
Jung-uk Kim
jkim at FreeBSD.org
Fri Jan 26 23:59:34 UTC 2007
I have been chasing TLS problem for Linuxulator/amd64. The whole
thing actually boils down to the following simulation:
----------------
#include <stdio.h>
#include <sys/types.h>
#include <machine/cpufunc.h>
#include <machine/sysarch.h>
static __thread u_int tls = 0xdeadbeef;
int
main(void)
{
#if defined(__amd64__)
u_int fs;
uint64_t fsbase;
fs = rfs();
if (sysarch(AMD64_GET_FSBASE, &fsbase))
return (-1);
printf("fsbase = 0x%lx, %%fs: 0x%08x, tls = 0x%x\n",
fsbase, fs, tls);
/*
* glibc does the following two calls.
* Note: Actually we don't do anything here
* but writing them back.
*/
if (sysarch(AMD64_SET_FSBASE, &fsbase))
return (-1);
load_fs(fs);
if (sysarch(AMD64_GET_FSBASE, &fsbase))
return (-1);
printf("fsbase = 0x%lx, %%fs: 0x%08x, tls = 0x%x\n",
fsbase, rfs(), tls);
#elif defined(__i386__)
u_int gs;
uint32_t gsbase;
gs = rgs();
if (sysarch(I386_GET_GSBASE, &gsbase))
return (-1);
printf("gsbase = 0x%lx, %%gs: 0x%08x, tls = 0x%x\n",
gsbase, gs, tls);
/*
* glibc does the following two calls.
* Note: Actually we don't do anything here
* but writing them back.
*/
if (sysarch(I386_SET_GSBASE, &gsbase))
return (-1);
load_gs(gs);
if (sysarch(I386_GET_GSBASE, &gsbase))
return (-1);
printf("gsbase = 0x%lx, %%gs: 0x%08x, tls = 0x%x\n",
gsbase, rgs(), tls);
#endif
return (0);
}
----------------
If you run it on amd64 (both amd64 and i386 binaries), it segfaults
at:
mov %fs:0x0,%rax (amd64)
or
mov %gs:0x0,%eax (i386)
which is basically reading tls. Why does it segfaults when we just
read and write them back? Can anyone enlighten me?
Thanks,
Jung-uk Kim
More information about the freebsd-amd64
mailing list