2

I'm reading through how pointer guard works, and looking at the glibc macro that does it:

#  define PTR_MANGLE(var)        asm ("xor %%fs:%c2, %0\n"                      \
                                     "rol $2*" LP_SIZE "+1, %0"                      \
                                     : "=r" (var)                              \
                                     : "0" (var),                              \
                                       "i" (offsetof (tcbhead_t,              \
#  define PTR_DEMANGLE(var)        asm ("ror $2*" LP_SIZE "+1, %0\n"              \
                                     "xor %%fs:%c2, %0"                              \
                                     : "=r" (var)                              \
                                     : "0" (var),                              \
                                       "i" (offsetof (tcbhead_t,              \
                                                      pointer_guard)))

The syntax is a little cryptic so I'm having a hard time understanding how PTR_DEMANGLE eventually produces assembly code like this:

ror    rdx,0x11
xor    rdx,QWORD PTR fs:0x30
call   rdx

How is string substitution working here? What is the meaning of : in this context? (I don't see a conditional assignment?)

Omar Darwish
  • 1,536
  • 2
  • 15
  • 23
  • 3
    https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html – HolyBlackCat Mar 20 '20 at 00:03
  • "The syntax is a little cryptic". That's an understatement. – Michael Burr Mar 20 '20 at 00:37
  • 2
    `fs` is an x86 _segment_ register. Under linux, `fs` is used as the base address of the "thread local storage" area. Application variables defined with `__thread` go in this area. The contents of `fs` is _different_ for each thread in a process, thus any variable defined this way will have a [possibly] different/independent value for each thread. On other arches, usually a given register is designated as the TLS base register. Because x86 has so few, `fs` was co-opted for this purpose. This is a way to prevent/reduce inter-thread demangle of another thread's encrypted pointer – Craig Estey Mar 20 '20 at 02:22
  • Indeed, there's quite a lot going on with these few lines of code. Explaining everything from start to finish, from macro expansion to assembly output, would require a very long answer. Maybe you can be a bit more specific about what stages you do and don't understand? In particular, I am not sure exactly what you mean by "string substitution". – Nate Eldredge Mar 20 '20 at 14:33
  • A couple hints, though: the `:` symbols are part of the gcc extended inline assembly syntax (see the link posted above by HolyBlackCat), and they have nothing to do with the `?:` ternary operator. Also, this asm statement is using AT&T assembly syntax, whereas your disassembly is in Intel syntax, which may be part of what is confusing you. The assembly it generates will actually look like `ror $2*8+1, %rdx ; xor %fs:0x30, %rdx`. The `call` is not produced by this macro and presumably comes from code that follows the macro invocation. – Nate Eldredge Mar 20 '20 at 14:37
  • Thanks all! I was not familiar with Extended Asm, and that fills the gap for me. Should I write an answer to this breaking down the syntax or are the comments here enough for future readers? – Omar Darwish Mar 25 '20 at 17:35

0 Answers0