8

With this function:

mov    1069833(%rip),%rax        # 0x2b5c1bf9ef90 <_fini+3250648>
add    %fs:0x0,%rax
retq

How do I interpret the second instruction and find out what was added to RAX?

starblue
  • 55,348
  • 14
  • 97
  • 151
Alex B
  • 82,554
  • 44
  • 203
  • 280
  • 3
    Assming you're running under linux, [this](http://stackoverflow.com/questions/6611346/amd64-fs-gs-registers-in-linux) question might be relevant. – user786653 Oct 21 '11 at 05:45
  • 2
    Possible duplicate of [What does "DS:\[40207A\]" mean in assembly?](http://stackoverflow.com/questions/3819699/what-does-ds40207a-mean-in-assembly) – Ciro Santilli OurBigBook.com Nov 07 '15 at 09:15

2 Answers2

9

This code:

mov    1069833(%rip),%rax        # 0x2b5c1bf9ef90 <_fini+3250648>
add    %fs:0x0,%rax
retq

is returning the address of a thread-local variable. %fs:0x0 is the address of the TCB (Thread Control Block), and 1069833(%rip) is the offset from there to the variable, which is known since the variable resides either in the program or on some dynamic library loaded at program's load time (libraries loaded at runtime via dlopen() need some different code).

This is explained in great detail in Ulrich Drepper's TLS document, specially §4.3 and §4.3.6.

ninjalj
  • 42,493
  • 9
  • 106
  • 148
3

I'm not sure they've been called segment register since the bad old days of segmented architecture. I believe the proper term is a selector (but I could be wrong).

However, I think you just need at the first quadword (64 bits) in the fs area.

The %fs:0x0 bit means the contents of the memory at fs:0. Since you've used the generic add (rather than addl for example), I think it will take the data width from the target %rax.

In terms of getting the actual value, it depends on whether you're in legacy or long mode.

In legacy mode, you'll have to get the fs value and look it up in the GDT (or possibly LDT) in order to get the base address.

In long mode, you'll need to look at the relevant model specific registers. If you're at this point, you've moved beyond my level of expertise unfortunately.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I figured as much, but how do I get the actual address from a selector? I don't have a running process, only a core dump. – Alex B Oct 21 '11 at 04:34
  • Yes, selectors are indexes (amongst other things, such as a flag that specifies LDT/GDT, from memory). You have to know where the GDT/LDT is, and I'm not _entirely_ certain you can actually get that from register info. – paxdiablo Oct 21 '11 at 04:50
  • 1
    If you're afraid you're in long mode, I'm even _more_ afraid I can't help you further :-) – paxdiablo Oct 21 '11 at 04:51
  • By "bad old days" do you mean 8x86 or 8x286? I think the 8x86 segments were brilliant; even today, if the x86 architecture had a mode that worked just like virtual 8086 mode but with 32-bit rather than 16-bit segment registers, something like the .NET framework would be able to access 64GB of memory using 32-bit object references, which I would expect would be a pretty big "win". If it were possible to use the top 4 bits of the 32-bit value to select one of 16 logical segments, each with an independent base address and scaling factor, the "smoothly" addressable memory could be even bigger. – supercat Oct 19 '14 at 22:14