|
About ::
TODO ::
Blog ::
RSS ::
Old blog ::
Projects ::
GIT ::
Gallery ::
Notes
Tue, 13 Feb 2007
All magic behind segments access has been uncovered. # 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 () |