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 に答える