elf.h中對符号表的類型定義如下: #define DT_STRTAB 5 #define DT_SYMTAB 6
這裡DT_SYMTAB與DT_STRTAB對應的section其實是.dynsym和.dynstr,而非.symtab和.symstr!
.symtab和.dynsym兩個不同的symbol table, 它們有什麼差別? .dynsym是.symtab的一個子集, 為什麼要兩個資訊重合的結構? 需要先了解allocable/non-allocable ELF section, ELF檔案包含一些sections(如code和data)是在運作時需要的, 這些sections被稱為allocable; 而其他一些sections僅僅是linker,debugger等工具需要, 在運作時并不需要, 這些sections被稱為non-allocable的. 當linker建構ELF檔案時, 它把allocable的資料放到一個地方, 将non-allocable的資料放到其他地方. 當OS加載ELF檔案時, 僅僅allocable的資料被映射到記憶體, non-allocable的資料仍靜靜地呆在檔案裡不被處理. strip就是用來移除某些non-allocable sections的. .symtab包含大量linker,debugger需要的資料, 但并不為runtime必需, 它是non-allocable的; .dynsym包含.symtab的一個子集, 比如共享庫所需要在runtime加載的函數對應的symbols, 它世allocable的. 是以, 得到答案: 1. strip移除的應是.symtab. 2. nm讀取的應是.symtab: 上面發現的libattr等nm結果為空, libpthread nm結果非空應是正常的. 3. 共享庫包含的.dynsym是runtime必需的, 是allocable的.
另外,很多資料上經常用到的一個概念是“全局符号表“,其實這是一個僞概念,記憶體中并不存在這樣一個表,libdl中會将所有已加載到記憶體中的可執行子產品(主程式或動态庫)的相關指針放入一個全局的連結清單中,通過這個全局連結清單可以通路到所有可執行子產品的動态符号表,僅此而以。我們可以假定這個全局連結清單是一個“全局符号表“,但其存儲的内容遠遠不止符号表這麼簡單,而是可執行子產品的所有相關資訊,如重定位資訊、代碼段位址、got段位址等。
例子: [[email protected] src]$ mipsel-linux-readelf -S main.elf There are 42 section headers, starting at offset 0xef4: 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 00400154 000154 000014 00 A 0 0 1 [ 2] .reginfo MIPS_REGINFO 00400168 000168 000018 18 A 0 0 4 [ 3] .dynamic DYNAMIC 00400180 000180 000110 08 A 6 0 4 [ 4] .hash HASH 00400290 000290 0000a4 04 A 5 0 4 [ 5] .dynsym DYNSYM 00400334 000334 000160 10 A 6 1 4 [ 6] .dynstr STRTAB 00400494 000494 00010a 00 A 0 0 1 [ 7] .gnu.version VERSYM 0040059e 00059e 00002c 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 004005cc 0005cc 000020 00 A 6 1 4 [ 9] .rel.plt REL 004005ec 0005ec 000018 08 A 5 11 4 [10] .init PROGBITS 00400604 000604 000048 00 AX 0 0 4 [11] .plt PROGBITS 00400660 000660 000050 00 AX 0 0 32 [12] .text PROGBITS 004006b0 0006b0 000240 00 AX 0 0 16 [13] .MIPS.stubs PROGBITS 004008f0 0008f0 000020 00 AX 0 0 4 [14] .fini PROGBITS 00400910 000910 000038 00 AX 0 0 4 [15] .eh_frame_hdr PROGBITS 00400948 000948 000014 00 A 0 0 4 [16] .eh_frame PROGBITS 0041095c 00095c 000030 00 WA 0 0 4 [17] .ctors PROGBITS 0041098c 00098c 000008 00 WA 0 0 4 [18] .dtors PROGBITS 00410994 000994 000008 00 WA 0 0 4 [19] .jcr PROGBITS 0041099c 00099c 000004 00 WA 0 0 4 [20] .data PROGBITS 004109a0 0009a0 000010 00 WA 0 0 16 [21] .rld_map PROGBITS 004109b0 0009b0 000004 00 WA 0 0 4 [22] .got.plt PROGBITS 004109b4 0009b4 000014 00 WA 0 0 4 [23] .got PROGBITS 004109d0 0009d0 00000c 04 WAp 0 0 16 [24] .sdata PROGBITS 004109dc 0009dc 000004 00 WAp 0 0 4 [25] .bss NOBITS 004109e0 0009e0 000020 00 WA 0 0 16 [26] .pdr PROGBITS 00000000 0009e0 000080 00 0 0 4 [27] .comment PROGBITS 00000000 000a60 000038 01 MS 0 0 1 [28] .debug_aranges MIPS_DWARF 00000000 000a98 000020 00 0 0 1 [29] .debug_pubnames MIPS_DWARF 00000000 000ab8 00001b 00 0 0 1 [30] .debug_info MIPS_DWARF 00000000 000ad3 0000cc 00 0 0 1 [31] .debug_abbrev MIPS_DWARF 00000000 000b9f 00006a 00 0 0 1 [32] .debug_line MIPS_DWARF 00000000 000c09 000040 00 0 0 1 [33] .debug_frame MIPS_DWARF 00000000 000c4c 00002c 00 0 0 4 [34] .debug_str MIPS_DWARF 00000000 000c78 0000a5 01 MS 0 0 1 [35] .debug_loc MIPS_DWARF 00000000 000d1d 00002c 00 0 0 1 [36] .debug_pubtypes MIPS_DWARF 00000000 000d49 000012 00 0 0 1 [37] .gnu.attributes LOOS+ffffff5 00000000 000d5b 000010 00 0 0 1 [38] .mdebug.abi32 PROGBITS 00000030 000d6b 000000 00 0 0 1 [39] .shstrtab STRTAB 00000000 000d6b 000186 00 0 0 1 [40] .symtab SYMTAB 00000000 001584 000540 10 41 63 4 [41] .strtab STRTAB 00000000 001ac4 00022c 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) 從此處看出,symtab和strtab并沒有被加載到記憶體中。