C:函数的返回地址(mac)

以下简短c程序:

void foo(int a, int b) { printf("a = %pb = %p\n", &a, &b); } main() { foo(1, 2); } 

好的,现在我用gdb来查看这个程序。 我得到了输出:

 a = 0x7fff5fbff9ac b = 0x7fff5fbff9a8 

并在输出后停止执行(在foo()中)。 现在我检查了0x7fff5fbff9ac,内容是:

1 ….正确

那么0x7fff5fbff9a8和内容:

2 …正确

现在我想查看函数的返回地址并检查(a + 4个字节):

x / g 0x7fff5fbff9b1(8字节!!地址,因此“g”(巨字))

其内容是:

 (gdb) x/g 0x7fff5fbff9b1 0x7fff5fbff9b1: 0xd700007fff5fbff9 

但是:这不是主要的回报! 我的错在哪里?

你的问题中有很多错误的假设。

您假设整数参数在返回地址上方的堆栈上传递(因为它们在许多 –在默认调用约定下不是所有 –x86 ABI)。 如果是这种情况,那么在调用之后,您的堆栈将如下所示:

 // stack frame of main( ) // ... value of b value of a return address <--- stack pointer 

但是,您的假设是不正确的。 您已将代码编译为64位可执行文件(由您正在打印的指针的大小certificate)。 根据OS X ABI,在64位Intel可执行文件中,前几个整数参数在寄存器中传递,而不是在堆栈中传递。 因此,在调用之后,堆栈实际上看起来像这样:

 // stack frame of main( ) // ... return address <--- stack pointer 

由于你获取ab的地址,它们将在调用printf( )之前的某个时刻被写入堆栈(除非编译器非常聪明,并且意识到它实际上并不需要手持printf( )有效指针,因为它不会使用指向的值,但这将是非常邪恶的,因为优化去),但你真的不知道它们相对于返回地址的位置; 事实上,因为64位ABI提供了一个红色区域 ,你甚至不知道它们是在堆栈指针之上还是之下。 因此,在您打印出a和b的地址时,您的堆栈如下所示:

 // stack frame of main( ) // ... return address | // ... | // a and b are somewhere down here | <-- stack pointer points somewhere in here // ... | 

通常,C语言标准没有说明堆栈布局, 甚至根本不需要堆栈 。 您无法从C代码以任何便携方式获得此类信息。

首先, &a + 40x7FFF5FBFF9B0 ,所以你看起来偏离了你认为你的位置。

其次,保存的帧指针位于a和返回地址之间,这是你看到的值。

你做错了就是对你给定平台上堆栈框架的布局做出一堆不正确和随机的假设。 你在哪里得到关于“ a + 4字节”位置据说持有返回地址的奇怪想法?

如果您真的想这样做,请获取您的平台的文档(或进行一些逆向工程),以找出存储返回地址的确切位置和方式。 随机猜测,然后询问其他人为什么你的随机猜测没有产生结果你出于某种原因预期并不是一个有效的方法来做到这一点。