如何确定堆栈上的返回地址?

vin*_*rak 18 c linux stack gcc

我知道如果我在函数foo()中某处调用某个bar()函数,那么这个返回地址就会被推送到堆栈中.

    #include <stdio.h>

    void foo()
    {
            unsigned int x;
            printf("inside foo %x\n", &x);
    }
    int main()
    {
            foo();
            printf("in main\n");
            return 0;
    }
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,当foo函数处于活动状态时,我将获得堆栈上第一个推送的局部变量的地址.如何访问在堆栈上此变量之前某处推送的返回地址(主要称为foo)?该位置是固定的,可以相对于第一个局部变量访问吗?我怎么修改它?

编辑:我的环境是使用gcc编译器的x86处理器上的Ubuntu 9.04.

Dig*_*oss 26

为此建立了一个gcc: void * __builtin_return_address (unsigned int level)

请参阅http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html

在某些体系结构上,您可以在堆栈中找到它相对于第一个参数.例如,在ia32上,按下参数(按相反顺序),然​​后调用将推送返回地址.请记住,堆栈几乎总是(并且在ia32上)向下增长.虽然从技术上讲,您需要为您的语言和硬件平台使用ABI调用约定(有时称为链接约定),但实际上您通常可以猜测您是否知道过程调用机器op的工作方式.

函数的第一个参数与堆栈上的返回地址的位置之间的关系更可能是一个可靠的固定值,而不是本地和返回地址之间的关系.但是,您当然可以打印出本地地址和第一个参数的地址,并且您经常可以找到它们之间的PC.

$ expand < ra.c
#include <stdio.h>

int main(int ac, char **av) {
  printf("%p\n", __builtin_return_address(0));
  return 0;
}
$ cc -Wall ra.c; ./a.out
0xb7e09775
$ 
Run Code Online (Sandbox Code Playgroud)

  • 然而,正如DigitalRoss所说,这完全取决于架构.在ARM上(我提到的问题是标记为"linux gcc",而不是"linux gcc x86"),链接指针在r14中,而不是(必然)在堆栈上.你用'MOV r15,r14`或'BX R14`返回.所以在gcc上你应该总是使用内置而不是试图猜测调用约定. (7认同)
  • 一般来说,是的.参数被推送,然后PC,然后堆栈进一步减少本地和编译器需要的任何临时.由于您可以获取参数和本地地址,因此您可以追踪您的PC.请记住,负的下标在C中工作得很好.`f(int p){printf("%p",(&p)[ - 1]); }` (2认同)