天天看点

关于动态符号表及“全局符号表”

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并没有被加载到内存中。

elf