2016-01-23 17 views
20

c(またはasm)でhello-world-likeプログラムをgccにリンクすると、結果の実行可能オブジェクトファイルにいくつかの要素が追加されます。私はランタイムダイナミックリンカと_startエントリポイントについてのみ知っていますが、これらの追加された関数の種類は何ですか?gccはlinux ELFにどのような機能を追加しますか?

00000000004003f0 t deregister_tm_clones 
0000000000400430 t register_tm_clones 
0000000000400470 t __do_global_dtors_aux 
0000000000400490 t frame_dummy 
00000000004004e0 T __libc_csu_init 
0000000000400550 T __libc_csu_fini 
0000000000400554 T _fini 
0000000000600668 t __frame_dummy_init_array_entry 
0000000000600668 t __init_array_start 
0000000000600670 t __do_global_dtors_aux_fini_array_entry 
0000000000600670 t __init_array_end 

とは何ですか?それはどこかに書かれていますか?グーグルは助けにはならない。

+6

参照[パトリック・ホーガンによるLinuxのx86のプログラムのスタートアップ](http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html)、libcのない純粋なASMコードがこれらを追加しないことに注意してくださいので、彼らはlibcから来ています。 – Jester

+0

@Jesterはとても素敵ですね、ありがとう!もし私があなたにこの情報で答えるかもしれないことを尋ねたものがあれば(そこからの情報もあれば) –

答えて

20

これらのほとんどは、「メイン」プログラムの前または後にコードを実行するさまざまな方法で、ほとんどがcrtstuff.chttps://github.com/gcc-mirror/gcc/blob/master/libgcc/crtstuff.c)に存在します。 さまざまなC言語のプログラミング言語の機能をサポートするために存在しますが、C言語でもアクセスできます。これらは、従来の手荷物を表すものと、GCCが実行するさまざまなアーキテクチャをサポートするために必要なものがあるため、おそらく複雑すぎるようです。

リストから

 

、1つ(または2つずつ)による1:

00000000004003f0 t deregister_tm_clones 
0000000000400430 t register_tm_clones 

トランザクショナルメモリは単純なスレッドを使ったプログラミングにすることを目的としています。 これは、ロックベースの同期の代替方法です。 これらのルーチンは、これらの機能をサポートするライブラリ(libitm)が使用するテーブルをそれぞれ破棄して設定します。ここではTMの 詳細情報https://gcc.gnu.org/wiki/TransactionalMemory、ここhttp://pmarlier.free.fr/gcc-tm-tut.html

 

0000000000400470 t __do_global_dtors_aux 

.fini_arrayが利用できないシステム上のプログラムからの終了時にすべてのグローバルデストラクタを実行します。

 

0000000000400490 t frame_dummy 

この機能は.initセクションに住んでいます。それはvoid frame_dummy (void)と定義され、その全ライフポイントは引数を持つ__register_frame_info_basesを呼び出すことです。明らかに、.initセクションからの引数を持つ関数への呼び出しは信頼できない可能性があります。したがって、__register_frame_info_bases.init sectionから直接呼び出されることはありません。 .eh_frameのinfobaseは、例外処理や同様の機能(例えば、__attribute__((cleanup(..)))で宣言された関数)に使用されます。

 

00000000004004e0 T __libc_csu_init 
0000000000400550 T __libc_csu_fini 

これらは、任意のプログラム・レベルの初期化子とファイナライザ(あなたの全体のプログラムのようなコンストラクタ/デストラクタのようなもの)を実行します。 あなたのような関数を定義する場合:

void __attribute__ ((constructor)) mefirst() { 
    /* ... do something here ... */ 
} 

void __attribute__ ((destructor)) melast() { 
    /* ... do something here ... */ 
} 

彼らはこれらのルーチンで前とmain()後にそれぞれ呼び出されます。 も参照してくださいhttps://gcc.gnu.org/onlinedocs/gccint/Initialization.html

 

0000000000400554 T _fini 

これは、プログラムレベル(オブジェクトファイル・レベルの実際)デストラクタを(これにはほとんど情報がman dlcloseで見つけることができます)を実行するために現在では非推奨の方法です。 コンストラクタの対応する廃止された関数は__initです。

 

0000000000600668 t __frame_dummy_init_array_entry 
0000000000600668 t __init_array_start 

これらは終了し、すべてのプログラム・レベルの初期化子へのポインタを含ん.init_array部、(__libc_csu_init上記を参照)の開始をマークします。

 

0000000000600670 t __do_global_dtors_aux_fini_array_entry 
0000000000600670 t __init_array_end 

これらは終了し、すべてのプログラムレベルのファイナライザへのポインタを含ん.fini_array部、(上記__libc_csu_finiを参照)の開始をマークします。

 

[EDIT]いくつかの追加の注意事項:

  • リンク http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html ジェスターの質問コメントからは、これらの全体的な順序を示す素敵図と小さなサンプル プログラムが含まれていますどのようにして がCからこれらの機能の一部にアクセスするのかと同様に動作します。

  • 用語 'ctors' および 'dtorsは' 'コンストラクタ' および 'デストラクタ' は、それぞれの省略形です。

  • グローバルコンストラクタ/デストラクタとオブジェクトファイル コンストラクタ/デストラクタの違いは、プログラムが複数のオブジェクトファイルで構成されている場合に最も顕著になります。 'T'(__libc_csu_init、__libc_csu_fini、_fini) が "グローバル"(外部から見える)であり、remainer(マークされた 'T')マーク

  • 記号はありません。

+0

''グローバルデストラクタ ''プログラムレベルイニシャライザとファイナライザ 'が何であるかを明確にするためにいくつか追加してください。これは、私の意見では、答えがより完成したように見えるでしょう。 –

+1

Per * shared *オブジェクトファイル。オブジェクトファイルではありません。 – o11c

関連する問題