Search code examples
cgdbx86-64cpu-registerscalling-convention

GDB: how to interpret x86_64 call stack & registers (specifically $rbp)


In my understanding, x86_64 calling convention specifies that return address a.k.a saved $rip should be right above the current frame base $rbp - for example:

8(%rbp) return address
0(%rbp) previous %rbp value

References for x86_64 calling convention: http://6.035.scripts.mit.edu/sp16/x86-64-architecture-guide.html http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/

However, the frame and $rbp register I got from gdb of a process doesn't make sense to me:

Registers:

(gdb) info registers
rax            0xfffffffffffffffc       -4
rbx            0x7ff7143fbc40   140699173370944
rcx            0xffffffffffffffff       -1
rdx            0x80     128
rsi            0x7ff7143fb4e0   140699173369056
rdi            0x9      9
rbp            0x7ff7143fbb00   0x7ff7143fbb00
rsp            0x7ff7143fb4c0   0x7ff7143fb4c0
r8             0x7ff715e2a630   140699200824880
r9             0xa072   41074
r10            0x493e0  300000
r11            0x293    659
r12            0x7ff715e2a600   140699200824832
r13            0x7ff715e2a630   140699200824880
r14            0x7ff7143fb4e0   140699173369056
r15            0x7ff715c73078   140699199025272
rip            0x7ff71d466f33   0x7ff71d466f33 <epoll_wait+51>
eflags         0x293    [ CF AF SF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0

Frame:

(gdb) info frame
Stack level 0, frame at 0x7ff7143fb4d0:
 rip = 0x7ff71d466f33 in epoll_wait; saved rip = 0x459347
 called by frame at 0x7ff7143fbb10
 Arglist at 0x7ff7143fb4b8, args:
 Locals at 0x7ff7143fb4b8, Previous frame's sp is 0x7ff7143fb4d0
 Saved registers:
  rip at 0x7ff7143fb4c8

If I traverse back from stack pointer ($rsp, $rsp+0x8, $rsp+0x10, etc), I should be able to find saved $rip on the stack. The good thing is - I did!

(gdb) x/8x 0x7ff7143fb4c8
0x7ff7143fb4c8: 0x47    0x93    0x45    0x00    0x00    0x00    0x00    0x00

Question:

As you can see here, the 8 byte memory at address 0x7ff7143fb4c8 is exactly the same as saved $rip from info frame in gdb. According to this, shouldn't the value of $rbp be 0x7ff7143fb4c0 according to the x86_64 calling convention? Why the current $rbp is 0x7ff7143fbb00? Could someone help fill the gap here?


Solution

  • In my understanding, x86_64 calling convention specifies that return address a.k.a saved $rip should be right above the current frame base $rbp

    Your understanding is completely wrong: x86_64 ABI does not specify $RBP as a frame register. The value of $RBP could be anything.

    Now, when compiled without optimization, or with -fno-omit-frame-pointer, or in routines that use alloca, or in routines with variable number of arguments, $RBP usually is used as a frame pointer. But not in other routines, not inside libc.so.6, etc.

    You didn't say which routine you stopped GDB in, or how that routine was compiled, or even where in that routine you are stopped, so most of the GDB output you provided lacks any meaningful context.