Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are the data segment registers always null in gdb?

Tags:

x86-64

gdb

glibc

Why do the data segment registers (ds/es/fs/gs) always seem to show up as 0x0 in GDB? For example, no matter what process or thread I look at, "info reg" always seems to give me output like this:

cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0

I am trying to debug glibc code where I see the fs segment prefix in the functions I am dissembling:

(gdb) disas __lll_lock_wait
Dump of assembler code for function __lll_lock_wait:
0x000000302800e240 <+0>:     push   %r10
0x000000302800e242 <+2>:     push   %rdx
0x000000302800e243 <+3>:     xor    %r10,%r10
0x000000302800e246 <+6>:     mov    $0x2,%edx
0x000000302800e24b <+11>:    xor    $0x80,%esi
0x000000302800e251 <+17>:    and    %fs:0x48,%esi
0x000000302800e259 <+25>:    cmp    %edx,%eax
0x000000302800e25b <+27>:    jne    0x302800e264 <__lll_lock_wait+36>
0x000000302800e25d <+29>:    mov    $0xca,%eax

I know that this is how glibc will reference the thread's TCB (tcbhead_t) for TLS and other important stuff. So wouldn't that mean that each thread would need to have a unique descriptor entry? Shouldn't each thread have a unique value for the fs register? I do not even believe 0x0 is a valid selector at all because the TI (table indicator) bit would indicate the GDT, and I thought there is no valid 0 GDT entry.

I know I must be missing something obvious, anyone know what it is?

Environment: CentOS 6.6, x86_64

like image 415
isamu Avatar asked Jan 29 '15 07:01

isamu


People also ask

How does segment register work?

A segment register changes the memory address accessed by 16 bits at a time, because its value is shifted left by 4 bits (or multiplied by 16) to cover the entire 20-bit address space. The segment register value is added to the addressing register's 16-bit value to produce the actual 20-bit memory address.

What is default segment register?

The default segment register is SS for the effective addresses containing a BP index, DS for other effective addresses. (note that SP isn't a valid base address for 16-bit addressing modes. Also note that when they say "index", that means when BP is used at all, even for [bp + si] or [bp+di] .

Can data segment register be loaded directly by its address?

In 8086 assembly programming, we can only load a data into a segment register by, first loading it into a general purpose register and then we have to move it from this general register to the segment register.

What is loaded into a segment register?

Segment register contains a selector that selects a descriptor from the descriptor table. The descriptor contains information about the segment, e.g., it's base address, length and access rights.


2 Answers

Shouldn't each thread have a unique value for the fs register?

No, each thread needs a unique FS segment base, but instead of requiring an LDT or GDT entry for each possible base, there's a mechanism for the kernel to simply set the FS base address directly in the internal segment descriptor without using a slower mov fs, eax instruction that loads a whole segment description including permissions and stuff.

The standard mechanism was writing an MSR (model-specific register); See Detail about MSR_GS_BASE in linux x86 64.

Intel since IvyBridge has supported the FSGSBASE feature, but apparently Linux is only just recently taking advantage of the wrfsbase instruction, which is faster than the WRMSR method. See https://lwn.net/Articles/769355/.

As well as being faster than wrmsr, wrfsbase has the added feature that the kernel can let user-space execute it, so VMs in user-space (like Java) could maybe take advantage instead of needing to make a system call for an always-privileged WRMSR instruction.

like image 154
Peter Cordes Avatar answered Dec 31 '22 09:12

Peter Cordes


So wouldn't that mean that each thread would need to have a unique descriptor entry?

Yes.

Shouldn't each thread have a unique value for the fs register?

No. The value of fs register is the same, but the memory it points to is different in every thread. See arch_prctl(2) man page and code for setting this up in GLIBC source.

like image 28
Employed Russian Avatar answered Dec 31 '22 10:12

Employed Russian