2012-05-12 7 views
6

Ich habe festgestellt, dass GCC, wenn wir nested functions verwenden, einen ausführbaren Stack für trampoline code benötigt. Folgender Code zeigt jedoch beim Kompilieren mit gcc keinen ausführbaren Stack an. (I verwenden execstack zu überprüfen, ob der Stapel ausführbar ist)Beispiel eines ausführbaren Stacks unter Linux (i386-Architektur)

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

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

Warum funktioniert das nicht in einem ausführbaren Stack führen? Und wenn es nicht soll, kann dann jemand ein Beispiel für ein Code-Konstrukt geben, das einen ausführbaren Stack gibt?

+0

Ich denke, lokal definierte Funktionen brauchen nicht ausführbaren Stack, weil ihr Code noch im selben Codeabschnitt wie andere Funktionen gespeichert ist, und nicht auf die Stapel. –

Antwort

4

Wenn die verschachtelte Funktion nicht in ihren „Eltern“ 's Stack es abhängt, dann nur eine einfache Funktion - die Verschachtelung syntaktischer (und scoping) Zucker.

Und wenn Sie nicht die Adresse der verschachtelten Funktion nehmen, ist auch kein Trampolin-Code notwendig. Du brauchst also etwas mehr, um all das auszulösen.

Hier ist ein Dummy-Beispiel:

// 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 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

Wie gesagt in Ihrem Link http://gcc.gnu.org/onlinedocs/gccint/Trampolines.html

Ein Trampolin ist ein kleines Stück Code, das zur Laufzeit erstellt wird, wenn die Adresse einer verschachtelten Funktion genommen wird. Es befindet sich normalerweise auf dem Stapel im Stapelrahmen der enthaltenden Funktion.

In Ihrem Beispiel Adresse von verschachtelt ist nicht genommen und gcc benötigt keine execstack verwenden.

Hier ein Beispiel für Code mit Trampolin ist: 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; 
}