I found that when we use nested functions, GCC requires an executable stack for trampoline code. However, following code, when compiled using gcc doesn't show an executable stack. (I used execstack to verify if the stack is executable)
我发现当我们使用嵌套函数时,GCC需要一个用于trampoline代码的可执行堆栈。但是,下面的代码,使用gcc编译时不会显示可执行堆栈。 (我使用execstack来验证堆栈是否可执行)
#include <stdio.h>
#include <unistd.h>
int main()
{
int add( int a, int b)
{
return a + b;
}
return add(2, 3);
}
Why does this not result in a executable stack? And if it is not supposed to, then can someone give example of a code construct that does give an executable stack?
为什么这不会导致可执行堆栈?如果它不应该,那么有人可以给出一个代码构造的例子,它确实给出了一个可执行的堆栈吗?
2 个解决方案
#1
5
If the nested function doesn't depend in its "parent"'s stack at all, then it's just a plain function - the nesting is syntactic (and scoping) sugar.
如果嵌套函数根本不依赖于它的“父”堆栈,那么它只是一个普通函数 - 嵌套是语法(和范围)糖。
And if you don't take the address of the nested function, no trampoline code is necessary either. So you'll need something a bit more involved to trigger all that.
如果你不采用嵌套函数的地址,也不需要trampoline代码。所以你需要更多的东西才能触发所有这些。
Here's a dummy example:
这是一个虚拟的例子:
// 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
#2
3
As said in your link http://gcc.gnu.org/onlinedocs/gccint/Trampolines.html
如您的链接http://gcc.gnu.org/onlinedocs/gccint/Trampolines.html中所述
A trampoline is a small piece of code that is created at run time when the address of a nested function is taken. It normally resides on the stack, in the stack frame of the containing function.
蹦床是在执行嵌套函数的地址时在运行时创建的一小段代码。它通常位于堆栈中,包含函数的堆栈帧中。
In your example address of nested is not taken and gcc needs no to use execstack.
在您的示例中,不执行嵌套的地址,并且gcc不需要使用execstack。
Here is an example of code with trampoline: http://www.win.tue.nl/~aeb/linux/hh/protection.html
以下是使用trampoline的代码示例: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;
}
#1
5
If the nested function doesn't depend in its "parent"'s stack at all, then it's just a plain function - the nesting is syntactic (and scoping) sugar.
如果嵌套函数根本不依赖于它的“父”堆栈,那么它只是一个普通函数 - 嵌套是语法(和范围)糖。
And if you don't take the address of the nested function, no trampoline code is necessary either. So you'll need something a bit more involved to trigger all that.
如果你不采用嵌套函数的地址,也不需要trampoline代码。所以你需要更多的东西才能触发所有这些。
Here's a dummy example:
这是一个虚拟的例子:
// 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
#2
3
As said in your link http://gcc.gnu.org/onlinedocs/gccint/Trampolines.html
如您的链接http://gcc.gnu.org/onlinedocs/gccint/Trampolines.html中所述
A trampoline is a small piece of code that is created at run time when the address of a nested function is taken. It normally resides on the stack, in the stack frame of the containing function.
蹦床是在执行嵌套函数的地址时在运行时创建的一小段代码。它通常位于堆栈中,包含函数的堆栈帧中。
In your example address of nested is not taken and gcc needs no to use execstack.
在您的示例中,不执行嵌套的地址,并且gcc不需要使用execstack。
Here is an example of code with trampoline: http://www.win.tue.nl/~aeb/linux/hh/protection.html
以下是使用trampoline的代码示例: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;
}