GDB:如何解读x86_64调用堆栈和寄存器(特别是$rbp)

3
在我看来,x86_64调用约定规定返回地址,也称为保存的$rip应该在当前帧基址$rbp正上方 - 例如:
8(%rbp) return address
0(%rbp) previous %rbp value

x86_64调用约定的参考资料: 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/

然而,我从一个进程的gdb中获得的帧和$rbp寄存器对我来说没有意义:

寄存器:

(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

框架:

(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

如果我从堆栈指针($rsp, $rsp+0x8, $rsp+0x10,等)遍历回去,我应该能在堆栈上找到保留的$rip。好消息是 - 我找到了

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

问题:

您可以在此处看到,地址为0x7ff7143fb4c8的8字节内存与gdb中info framesaved $rip完全相同。根据这个,根据x86_64调用约定,$rbp的值不应该是0x7ff7143fb4c0吗?为什么当前的$rbp0x7ff7143fbb00?能否有人帮助填补这个空白?

1个回答

4
在我的理解中,x86_64调用规约规定返回地址即保存的$rip应该位于当前帧基础$rbp正上方。但是你的理解完全是错误的: x86_64 ABI没有将$RBP指定为帧寄存器,$RBP的值可以是任何值。现在,在没有优化编译或使用-fno-omit-frame-pointer选项,或在使用alloca的例程中,或在具有可变参数数量的例程中,$RBP通常被用作帧指针。但是在其他例程中,例如libc.so.6内部,则不会使用。由于你没有说明停止GDB的例程以及该例程是如何编译的,甚至你在该例程的哪个位置停止,因此你提供的大部分GDB输出缺乏任何有意义的上下文。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接