More on %gs:0x0

Mark Seaborn mrs@mythic-beasts.com
Mon Aug 24 18:25:00 GMT 2009


Amittai Aviram <amittai.aviram@yale.edu> wrote:

> Here is a follow-up to my previous query.  My question remains this:   
> how do values get into %gs:0x0?

> The final step will show me zillions of instances of moving data from  
> location %gs:0x0 to a general purpose register, but not a single  
> instance of moving data _into_ location %gs:0x0.  How does anything  
> except 0 ever get into %gs:0x0?

I'd suggest reading Ulrich Drepper's document about the TLS ABIs -
http://people.redhat.com/drepper/tls.pdf - and also read about how
segment registers work on i386.

%gs is not a normal register.  It is a segment register, which means
it indexes into a segment table that is set up by the kernel.

%gs points, indirectly, to the start of the thread control block (TCB)
[1].  The location of the TCB is allocated by glibc.  glibc fills out
the TCB using instructions with normal, non-segmented addressing modes
(i.e. without %gs), which is why you're not finding what you're
looking for.

As it happens, the first word of the TCB is a pointer to the TCB, so
"mov %gs:0x0,%ebx" fetches the location of the TCB into %ebx, after
which the program can use normal addressing modes to read the TCB.

The setup happens in TLS_INIT_TP() in nptl/sysdeps/i386/tls.h.  It
calls the set_thread_area syscall to set up the segment table (which
can only be done by the kernel).  It gets a segment index back and
sets %gs to that with TLS_SET_GS.  The line that fills out %gs:0 is
"_head->tcb = _thrdescr;".

Mark

[1] I think I have the right terminology here, but the ABI also uses
    the term "thread pointer" and the source uses the term "thread
    descriptor".



More information about the Libc-help mailing list