Zbr's days.
February
Sun Mon Tue Wed Thu Fri Sat
       
13
     
2007
Months
Feb

About TODO Blog RSS Old blog Projects Gallery Notes

Tue, 13 Feb 2007

All magic behind segments access has been uncovered.


So, I've written simple module which dumps Global Descriptor Table for each CPU in system and started my test application, which essentialy does "movl %%gs:0, %0", so I just present parts of the output so things just become clear and obious:

# gdt_reader /dev/gdt
...
 0/ 2:  6: TLS segment #1 [ glibc's TLS segment ] : start: b7ff06c0, size: 4294963200, 
 seg_type: 0x3, dpl: 0x8, AVL: 1, SEG_PRESENT: 1, DESC_TYPE: code or data, OP_SIZE: 32 bits.
...
 0/ 2: 14: default user CS : start: 00000000, size: 4294963200, 
 	seg_type: 0xb, dpl: 0x8, AVL: 0, SEG_PRESENT: 1, DESC_TYPE: code or data, OP_SIZE: 32 bits.
 0/ 2: 15: default user DS : start: 00000000, size: 4294963200, 
 	seg_type: 0x3, dpl: 0x8, AVL: 0, SEG_PRESENT: 1, DESC_TYPE: code or data, OP_SIZE: 32 bits.
...

ds: reg: 15, table: GDT, rpl: 0x3, val: should fail.
gs: reg: 6, table: GDT, rpl: 0x3, val: b7f736c0.
As we can see, %DS register is setup for the whole adress space (its size is 4gb minus one page), as long as %CS, so it is impossible to dereference them.
%GS points to some memory (accessible indirectly as "%gs:0"), where thread local storage is setup by kernel and libc, its size is the same 4gb minus one page.
That page is likely created to cover GDT itself.
Segmentation fault behind "movl %%ds:0, %0" becomes obvious too - it tries to dereference zero address, which ends up with SIGSEGV.

So, instead of searching for documentation on "movl %%gs:0, %0" command (and mainly to determine what is that magical ':0' is about) I created kernel module, dumped and analyzed GDT and finally detected how gcc inline asm treats that.

Btw, notice that %GS segment start is the same as result of the "movl %%gs:0, %0" command. It is impossible to actually get segment start, it just happens that glibc puts pinter to TCB (thread control block) as first pointer in the struct pthread (which is stored in %gs). TCB structure itself has pointer to itself as a first member.
It is only true on x86, other arches happily have special real register for that purpose instead of ugly indirect dereferencies.

/devel/threading :: Link / Comments (0)

Please solve this captcha to be allowed to post (need to reload in a minute): 33 - 33

Comments are closed for this story.