2016-03-30 8 views
-1

gccのコンパイルの基礎を初めて学びました。私が知る限り、スタックはセキュリティ上の理由から実行できません。それでは、スタック上にどのようにコードを記述して実行するのですか?関数へのポインタを返す関数の場合、これを観察しました。コードへのポインタを返すのではなく、実行されるコードを持つスタック上の位置に戻ります。それはどのようにLinuxで許可されていますか?スタック上のコードの実行

すでにgccによって行われています。私はそれがどのように可能であるか知りたいですか?ここで

はCコードです:

 #include<stdio.h> 

    typedef int (* funcptr)(); 


funcptr f() 
{ 

    int g() 
    { 

} 
return (&g); 
} 


main() 
{ 
    funcptr fp; 
    fp = f(); 

    fp(); 

} 

そしてここでは、スタック上のコードをgeeratingアセンブリコードの一部です:

#Starting trampoline code. The trampoline code is a small 
    #piece of code set up inside the stack!!!. This code, when 
    #executed, loads ecx with the static link and calls the 
    #function g 
     movb $-71, (%eax) # This is B9, the opcode for 
            "movl address_in_next_loc ecx" 
            this, when executed, will 
            load the static link in ecx 

     movl %edx, 1(%eax) # address_in_next_loc=ebp-16 
            the static link effectively 

     movb $-23, 5(%eax) # This is E9. the opcode for 
            jmp addr_nxt_ins + offset_ 
            in_nxt_loc 
            Since the offset_in_nxt_loc 
            is &g - addr_nxt_ins, this 
            results in a jump to &g 

     movl $g.1831, %ecx # Stores &g - addr_nxt_ins 
     leal 10(%eax), %edx # 
     subl %edx, %ecx # 
     movl %ecx, %edx # 
     movl %edx, 6(%eax) # 
    #End of trampoline code 
+0

gccはこれをどうしていますか? –

+0

gccで作成されたアセンブリを読み込んでいるためです。私はアセンブリを作成し、それを読んだ。 –

+1

このアセンブリコードを表示できますか? –

答えて

1

あなたのCコードは、ネストされた関数を含むコードの場所が必要になることを示していセクションをx(実行可能スタックが必要であることを示します)に設定します。

リンカが呼び出されると、リンカはこのセクションのすべてのオブジェクトファイルをチェックします。いずれかの入力ファイルが.note.GNU-stackxに設定されているため、リンカーはスタックが実行可能でなければならないことを認識します。

これを示すには、最終実行ファイルのELFヘッダーGNU_STACKにフラグPF_Xが追加されていることを示します。

コマンド:

readelf -l a.out | grep -A1 GNU_STACK 

があなたの代わりにRWセットRWEフラグを参照できるようにする必要があります。

カーネルは、プロセスのメモリマップを設定するときに、特にこのヘッダを探します。

詳細はこちらoriginal patch

+0

ありがとう答えのためにたくさん:) –

1

スタックとは対照的に、あなたはヒープからメモリを割り当てます。しかし、現代のプロセッサ/ OSは、コードを含むメモリ領域とデータを含むメモリ領域とを区別することができる(明らかなセキュリティ上の理由から)。

0

スタックがコード自体を保持していると仮定します。そうではないかもしれません。スタックは、コード領域へのポインタのホルダです。あなたはスタックがhere

This SO answerをどのように機能するかについての詳細を学ぶことができ

はGCCが.note.GNU-stackを設定しますので、関数ポインタや機能自体は、

+0

スタックには、すべての機能コードではなく一部のコードが含まれています。ジャンプや静的リンクなどを設定するためのコードがスタックにあります。 –

+0

多分このリンクは役立ちます:http://hokstad.com/how-to-implement-closures – CarlH

関連する問題