7

我发现当我们使用嵌套函数时,GCC 需要一个用于蹦床代码的可执行堆栈。但是,以下代码在使用 gcc 编译时不显示可执行堆栈。(我使用execstack来验证堆栈是否可执行)

#include <stdio.h>
#include <unistd.h>

int main()
{
        int add( int a, int b)
        {
                return a + b;
        }
        return add(2, 3);
}

为什么这不会导致可执行堆栈?如果不应该这样做,那么有人可以举一个给出可执行堆栈的代码结构的例子

4

2 回答 2

5

如果嵌套函数根本不依赖于其“父”的堆栈,那么它只是一个普通函数 - 嵌套是语法(和范围)糖。

如果不取嵌套函数的地址,也不需要蹦床代码。所以你需要更多的东西来触发这一切。

这是一个虚拟示例:

// file t.c
int doit(int (*fun)(int), int x)
{
    return fun(x);
}

int foo(int a)
{
        int add(int b)
        {
                return a + b;
        }
        return doit(&add, 2);
}

int main(void)
{
    return foo(1);
}
$ gcc -Wtrampolines t.c
t.c: In function 'foo':
t.c:8:13: warning: trampoline generated for nested function 'add'
$ ./a.out 
$ echo $?
3
$ execstack a.out 
X a.out
于 2012-05-12T14:15:07.770 回答
3

如您的链接中所述http://gcc.gnu.org/onlinedocs/gccint/Trampolines.html

蹦床是一小段代码,它在运行时获取嵌套函数的地址时创建。它通常驻留在堆栈上,在包含函数的堆栈框架中。

在您的示例地址中,未采用嵌套地址,并且 gcc 不需要使用 execstack。

这是一个带有蹦床的代码示例:http: //www.win.tue.nl/~aeb/linux/hh/protection.html

% cat trampoline.c
#include <stdio.h>
int main(int ac, char **av) {
        int localfn(int a) {
                return a+ac;
        }
        int (*fptr)(int) = localfn;

        printf("%d\n", fptr(-1));
        return 0;
}
于 2012-05-12T14:13:59.300 回答