7

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)

#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?

gjain
  • 4,468
  • 5
  • 39
  • 47
  • I think locally defined functions don't need executable stack because their code is still stored in the same code section as other functions, and not on the stack. – Alexey Frunze May 12 '12 at 13:49

2 Answers2

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.

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
Mat
  • 202,337
  • 40
  • 393
  • 406
3

As said in your link 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.

Here is an example of code with 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;
}
osgx
  • 90,338
  • 53
  • 357
  • 513