2016-01-23 23 views
20

當鏈接一個hello世界般的程序在C(或C++)與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中的純彙編代碼中不添加這些,因爲他們來自libc。 – Jester

+0

@Jester看起來非常好,謝謝!如果它包含任何我問過的問題,你可以用這個信息回答(當然有一些信息)。 –

回答

20

其中大多數是在「main」程序本身之前或之後執行代碼的各種方法,並且大部分都是crtstuff.chttps://github.com/gcc-mirror/gcc/blob/master/libgcc/crtstuff.c)。 它們的存在,以支持各種類C語言的功能,但它們可以在C訪問也是如此。它也許看起來過於複雜,因爲其中的一些代表遺留行李,有的用來支持GCC運行在各種不同架構所需要的變化。

 

從你的列表中,一個接一個(或兩個兩個):

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信息庫用於異常處理和類似功能(例如用__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上文)。

 

[編輯]一些附加註釋:

  • 從小丑的問題評論的鏈接 http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html 包含一個很好的圖,示出了總體順序這些小樣品 程序事情運行以及如何從 訪問這些功能的一些C.

  • 術語 '構建函數' 和 'dtors' 分別是 '構造' 和 '' 縮寫。

  • 當您的程序是由多個目標文件構建的 時,全局構造函數/析構函數和目標文件 構造函數/析構函數之間的差異最爲明顯。

  • 標記爲 'Ť'(__libc_csu_init,__libc_csu_fini,_fini) 是 「全局」(外部可見的),所述的滯留(標記爲 '')的符號都沒有。

+0

請你補充一點,澄清什麼是'全局析構函數'程序級初始值設定項和終結符?這將使我的觀點看起來更完整。 –

+1

每個*共享*目標文件,而不是每個目標文件。 – o11c