Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 000000000 NOTYPE LOCALDEFAULT UND 1: 000000000 NOTYPE WEAK DEFAULT UND __gmon_start__ 2: 000000000 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2) 3: 0804846c 4OBJECT GLOBAL DEFAULT16 _IO_stdin_used
Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 000000000 NOTYPE LOCAL DEFAULT UND 1: 000000000 NOTYPE WEAK DEFAULT UND __gmon_start__ 2: 000000000 FUNC GLOBALDEFAULT UND __libc_start_main@GLIBC_2.0 (2) 3: 0804846c 4 OBJECT GLOBALDEFAULT16 _IO_stdin_used root@AI-Machine:/home/hongjh/2019_project#
复制
编译观察
我们来写一个测试程序: oop.c:
#include<stdio.h> int g_a = 10; staticint g_s_b; staticint g_s_c = 0; int g_d; __thread int g_tls_e; static __thread int g_tls_s_f; __thread int g_tls_g = 0; externint g_e_h; externvoidfun1(); voidfun() { int l_i; g_d = 10; staticint l_s_i; g_e_h= 10;//外部变量和函数如果不使用的话,编译器不会为其产生符号表,因为会优化 fun1(); printf("hello\n"); return; }
root@AI-Machine:/home/hongjh/2019_project# readelf -S oop.o There are 13 section headers, starting at offset 0x3d0:
Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000000000000 [ 1] .text PROGBITS 0000000000003400005800 AX 004 [ 2] .rel.text REL 0000000000034000002808 I 1014 [ 3] .data PROGBITS 0000000000008c 00000400 WA 004 [ 4] .bss NOBITS 0000000000009000000c 00 WA 004 [ 5] .tbss NOBITS 0000000000009000000c 00 WAT 004 [ 6] .rodata PROGBITS 0000000000009000000d 00 A 004 [ 7] .comment PROGBITS 0000000000009d 00002c 01 MS 001 [ 8] .note.GNU-stack PROGBITS 000000000000c9 00000000001 [ 9] .ARM.attributes ARM_ATTRIBUTES 000000000000c9 00003100001 [10] .symtab SYMTAB 000000000000fc 0001e01011214 [11] .strtab STRTAB 000000000002dc 00006300001 [12] .shstrtab STRTAB 0000000000036800006700001 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)
Symbol table '.symtab' contains 30 entries: Num: Value Size Type Bind Vis Ndx Name 0: 000000000 NOTYPE LOCALDEFAULT UND 1: 000000000FILELOCALDEFAULT ABS oop.c 2: 000000000 SECTION LOCALDEFAULT1 3: 000000000 SECTION LOCALDEFAULT3 4: 000000000 SECTION LOCALDEFAULT4 5: 000000000 NOTYPE LOCALDEFAULT3 $d 6: 000000004OBJECTLOCALDEFAULT4 g_s_b 7: 000000000 NOTYPE LOCALDEFAULT4 $d 8: 000000044OBJECTLOCALDEFAULT4 g_s_c 9: 000000000 SECTION LOCALDEFAULT5 10: 000000000 TLS LOCALDEFAULT5 $d 11: 000000044 TLS LOCALDEFAULT5 g_tls_s_f 12: 000000000 SECTION LOCALDEFAULT6 13: 000000000 NOTYPE LOCALDEFAULT6 $d 14: 000000000 NOTYPE LOCALDEFAULT1 $a 15: 000000340 NOTYPE LOCALDEFAULT1 $d 16: 000000400 NOTYPE LOCALDEFAULT1 $a 17: 000000084OBJECTLOCALDEFAULT4 l_s_i.4609 18: 000000000 SECTION LOCALDEFAULT8 19: 000000000 SECTION LOCALDEFAULT7 20: 000000000 SECTION LOCALDEFAULT9 21: 000000004OBJECT GLOBAL DEFAULT3 g_a 22: 000000044OBJECT GLOBAL DEFAULT COM g_d 23: 000000004 TLS GLOBAL DEFAULT5 g_tls_e 24: 000000084 TLS GLOBAL DEFAULT5 g_tls_g 25: 0000000064 FUNC GLOBAL DEFAULT1 fun 26: 000000000 NOTYPE GLOBAL DEFAULT UND fun1 27: 000000000 NOTYPE GLOBAL DEFAULT UND puts 28: 000000000 NOTYPE GLOBAL DEFAULT UND g_e_h 29: 0000004024 FUNC WEAK DEFAULT1 fun_weak
复制
可以看到该符号表包含了30项(entry),每一项用Elf32_Sym结构体描述:
typedefstruct { Elf32_Word st_name; /* Symbol name (string tbl index) */ Elf32_Addr st_value; /* Symbol value */ Elf32_Word st_size; /* Symbol size */ unsignedchar st_info; /* Symbol type and binding */ unsignedchar st_other; /* Symbol visibility */ Elf32_Section st_shndx; /* Section index */ } Elf32_Sym;
Value 该符号的值(注意不是变量的值),符号的值就是指符号的地址,对于编译的中间文件.ol来说,value其实是该符号在其所在的section的偏移,是个相对值;对于链接后的可执行文件来说,该值是个绝对值,表示符号的绝对地址。
Type 表示符号的类型,常见的几种类型如下:
484#define STT_NOTYPE 0 /* Symbol type is unspecified */ 485#define STT_OBJECT 1 /* Symbol is a data object */ 486#define STT_FUNC 2 /* Symbol is a code object */ 487#define STT_SECTION 3 /* Symbol associated with a section */ 488#define STT_FILE 4 /* Symbol's name is file name */ 489#define STT_COMMON 5 /* Symbol is a common data object */ 490#define STT_TLS 6 /* Symbol is thread-local data object*/
复制
OBJECT 表示全局变量和static变量 FUNC 表示函数 FILE 文件名 COM 公用全局变量 TLS 线程本地数据
Bind列有以下几个常见值:
472#define STB_LOCAL 0 /* Local symbol */ 473#define STB_GLOBAL 1 /* Global symbol */ 474#define STB_WEAK 2 /* Weak symbol */
复制
分别表示局部、全局、弱符号。
最后一列Vis,表示该符号的可见范围,visibility的缩写:
/* Symbol visibility specification encoded in the st_other field. */ #define STV_DEFAULT 0 /* Default symbol visibility rules */ #define STV_INTERNAL 1 /* Processor specific hidden class */ #define STV_HIDDEN 2 /* Sym unavailable in other modules */ #define STV_PROTECTED 3 /* Not preemptible, not exported */
复制
我们看下.data段的序号是不是2:
[ 2].dataPROGBITS 00000000 00003c 000004 00 WA 0 0 4
Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 000000000 NOTYPE LOCALDEFAULT UND 1: 000000000 NOTYPE WEAK DEFAULT UND __gmon_start__ 2: 000000000 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2) 3: 0804849c 4OBJECT GLOBAL DEFAULT16 _IO_stdin_used