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?
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.