在Linux上访问x86-64体系结构上的堆栈帧

在Linux上访问x86-64体系结构上的堆栈帧,linux,assembly,stack,x86-64,Linux,Assembly,Stack,X86 64,我试图在x86-64体系结构的Linux系统上访问不同的堆栈帧。我能够访问所有帧的寄存器基指针(rbp)。现在我想访问每个函数调用的参数。我检查了一下,上面说前6个参数是通过寄存器传递的。然而,据我所知,通过读取寄存器,我只能得到最顶层函数调用的参数。但是发送到其他函数(即,位于当前帧下方的堆栈帧)的参数呢?据推测,它们必须存储在堆栈本身的某个位置,但我无法获取位置。有人能解释一下吗 非常感谢。接受以下代码: int f1(int a1, int a2, int a3) { return f

我试图在x86-64体系结构的Linux系统上访问不同的堆栈帧。我能够访问所有帧的寄存器基指针(rbp)。现在我想访问每个函数调用的参数。我检查了一下,上面说前6个参数是通过寄存器传递的。然而,据我所知,通过读取寄存器,我只能得到最顶层函数调用的参数。但是发送到其他函数(即,位于当前帧下方的堆栈帧)的参数呢?据推测,它们必须存储在堆栈本身的某个位置,但我无法获取位置。有人能解释一下吗

非常感谢。

接受以下代码:

int f1(int a1, int a2, int a3) {
  return f2(2 * a1, 2 * a2, 2 * a3);
}

int f2(int a1, int a2, int a3) {
  return a1 + a2 + a3;
}

现在假设我们调用f1():我们按照调用约定将其参数放入RDI、RSI和RDX中。然后将每个寄存器乘以2,并调用f2()。这些寄存器被定义为调用方已保存,但不需要保存它们,因为f1()将不再使用它们。因此,一旦进入f2(),我们就不能合理地期望有任何方法将原始参数传递给f1()。它们根本不存在,并且无法恢复,因为即使是简单的乘法2操作也无法“撤消”(因为它可能已溢出)。

它们不一定存储在堆栈上,因此通常您无法访问它们。还请注意,使用
rbp
作为堆栈帧指针也是可选的。但是,如果再次需要这些参数呢?在这种情况下,a1、a2和a3(f1的)必须保存在某个地方。但在哪里?它们可以保存在其他寄存器中。:)但是你不知道是哪一个。
gdb
只有在没有优化和调试信息的情况下编译时才能进行回溯。否则,即使是
gdb
也会告诉您这样的信息:
main(argc=,argv=)
。编写一个程序,其中包含如上所述的
f1
f2
,以及一个
void main
,它只调用
f1(1,2,3)
。不要包括
stdio
printf
或任何其他内容。现在编译它并反汇编main和两个
f
函数。观察值如何存储在堆栈上,并在执行计算时在寄存器中移动。当您在
f2
中时,您无法知道调用了什么
f1
,因为寄存器内容已被覆盖。@suprjami:差不多,我就是这样确认了上面写的一些内容的。不过我不需要反汇编——我只是编译成汇编并停在那里(例如,
g++-S
)。顺便说一句,请注意,您必须使用
int main
而不是
void main
——它不再是1988年的版本了