2013-03-20 53 views
2

我想在C++文件中計算靜態初始值設定項。如何計算ELF文件中的靜態初始值設定項?

我已經擁有的解決方案(曾經使用gcc-4.4)正在查看.ctors ELF部分的大小。

升級到gcc-4.6後,這似乎不再返回有效結果(計算出的靜態初始值設定項數爲0,與實際值不符,例如由nm返回)。

現在的問題是我想解決方案即使在沒有符號的情況下也能工作(否則我會用nm)。

下面是一個例子可執行的readelf -SW的輸出:

有35個區段標題,起始於偏移0x4f39820:

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .interp   PROGBITS  00000174 000174 000013 00 A 0 0 1 
    [ 2] .note.ABI-tag  NOTE   00000188 000188 000020 00 A 0 0 4 
    [ 3] .note.gnu.build-id NOTE   000001a8 0001a8 000024 00 A 0 0 4 
    [ 4] .gnu.hash   GNU_HASH  000001cc 0001cc 000918 04 A 5 0 4 
    [ 5] .dynsym   DYNSYM   00000ae4 000ae4 00a5e0 10 A 6 1 4 
    [ 6] .dynstr   STRTAB   0000b0c4 00b0c4 00ef72 00 A 0 0 1 
    [ 7] .gnu.version  VERSYM   0001a036 01a036 0014bc 02 A 5 0 2 
    [ 8] .gnu.version_r VERNEED   0001b4f4 01b4f4 000450 00 A 6 13 4 
    [ 9] .rel.dyn   REL    0001b944 01b944 268480 08 A 5 0 4 
    [10] .rel.plt   REL    00283dc4 283dc4 0048c8 08 A 5 12 4 
    [11] .init    PROGBITS  0028868c 28868c 00002e 00 AX 0 0 4 
    [12] .plt    PROGBITS  002886c0 2886c0 0091a0 04 AX 0 0 16 
    [13] .text    PROGBITS  00291860 291860 3ac5638 00 AX 0 0 16 
    [14] malloc_hook  PROGBITS  03d56ea0 3d56ea0 00075a 00 AX 0 0 16 
    [15] google_malloc  PROGBITS  03d57600 3d57600 008997 00 AX 0 0 16 
    [16] .fini    PROGBITS  03d5ff98 3d5ff98 00001a 00 AX 0 0 4 
    [17] .rodata   PROGBITS  03d5ffc0 3d5ffc0 ffa640 00 A 0 0 64 
    [18] .eh_frame_hdr  PROGBITS  04d5a600 4d5a600 0004b4 00 A 0 0 4 
    [19] .eh_frame   PROGBITS  04d5aab4 4d5aab4 001cb8 00 A 0 0 4 
    [20] .gcc_except_table PROGBITS  04d5c76c 4d5c76c 0003ab 00 A 0 0 4 
    [21] .tbss    NOBITS   04d5df0c 4d5cf0c 000014 00 WAT 0 0 4 
    [22] .init_array  INIT_ARRAY  04d5df0c 4d5cf0c 000090 00 WA 0 0 4 
    [23] .ctors   PROGBITS  04d5df9c 4d5cf9c 000008 00 WA 0 0 4 
    [24] .dtors   PROGBITS  04d5dfa4 4d5cfa4 000008 00 WA 0 0 4 
    [25] .jcr    PROGBITS  04d5dfac 4d5cfac 000004 00 WA 0 0 4 
    [26] .data.rel.ro  PROGBITS  04d5dfc0 4d5cfc0 1b160c 00 WA 0 0 32 
    [27] .dynamic   DYNAMIC   04f0f5cc 4f0e5cc 000220 08 WA 6 0 4 
    [28] .got    PROGBITS  04f0f7ec 4f0e7ec 00a800 04 WA 0 0 4 
    [29] .data    PROGBITS  04f1a000 4f19000 0206b8 00 WA 0 0 32 
    [30] .bss    NOBITS   04f3a6c0 4f396b8 04c800 00 WA 0 0 32 
    [31] .comment   PROGBITS  00000000 4f396b8 00002a 01 MS 0 0 1 
    [32] .shstrtab   STRTAB   00000000 4f396e2 00013e 00  0 0 1 
    [33] .symtab   SYMTAB   00000000 4f39d98 4ff960 10  34 140163 4 
    [34] .strtab   STRTAB   00000000 54396f8 144992a 00  0 0 1 
Key to Flags: 
    W (write), A (alloc), X (execute), M (merge), S (strings) 
    I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 
    O (extra OS processing required) o (OS specific), p (processor specific) 

我應該看的.init或.init_array代替?你能指點我相應的文檔,解釋gcc或鏈接器版本之間的變化嗎?

+1

爲什麼你到底在問什麼? – 2013-03-20 19:25:06

回答

7

靜態構造函數可以由三個部分.init,.ctors.init_array(按照該順序最早到最新)中的任何一個來觸發。 .init包含一段代碼,.ctors.init_array包含指向代碼的指針。 .ctors.init_array之間的區別與構造函數的執行順序有關。據我所知,除了代碼註釋和郵件列表文章以外,其他地方都沒有文檔記錄,但可能需要檢查ELF ABI文檔(g-和ps-兩者)。

無法這些部分的任何大小推斷在文件中靜態構造函數的數量。對於編譯器來說,允許並且通常會生成一個調用文件中所有構造函數的特殊函數,並且只使用它所使用的任何部分中的那個函數。所有您可以確切知道的內容(無需檢查各部分的內容,應用重定位,將指針/調用指令放入.text段並對所調用的對象進行逆向工程)爲:,其中包含目標文件,如果其中至少有一個部分具有非零大小,那麼文件中至少有一個文件或全局範圍構造函數;如果所有三個部分都是空的,那麼沒有。 (在一個可執行文件中,所有三個部分總是非空的,因爲他們定義的數據結構需要標題和尾部,並在鏈接時自動添加。)

還要注意,用於塊範圍的靜態對象的構造函數不是從任何這些部分引用;他們在第一次控制達到他們的聲明時被調用。

+0

沒有人禁止'main()'在其開始時調用構造函數(或者甚至在它之前運行的代碼中),沒有任何部分shenanigans。有一天海灣合作委員會做到了這一點,或者是另一種方式是他們的業務。 – vonbrand 2013-03-22 22:44:57

+1

@vonbrand C++標準允許您正在考慮的技術,但許多年來沒有人這樣做過,並且在共享庫的存在下無法正常工作。編譯器的業務也不僅僅是它如何實現靜態構造函數; ELF ABI文檔確實指定了'.init','.ctors'和'.init_array'部分的功能。 – zwol 2013-03-22 23:59:05

0

我假設你有權訪問你的應用程序的所有源代碼(也可能是所有它被稱爲的庫)。自由軟件顯然是這樣的。

然後,您可以在編譯時(使用GCC的最新版本,例如4.7或4.8)編譯時更精確地測量您的應用程序。你可以用MELT(這是一個高級別的域特定語言來擴展GCC)或用C++編寫的痛苦的GCC插件來擴展它來測量這些事情。

我不完全確定你的問題具有確切的意義。如果您的申請是例如鏈接到一些使用可見性技巧隱藏其靜態構造函數的共享庫,瞭解庫調用的靜態構造函數沒有真正定義。

相關問題