bohanl bohanl - 2 months ago 8
C Question

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?

Answer

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.