linux符号表简介
既然在链接时,需要重定位目标文件中引用的外部符号,显然,链接器需要知道这些符号的定义在哪里,为此汇编器在每个目标文件中创建了一个符号表,符号表中记录了这个模块定义的可以提供给其他模块引用的全局符号。可以使用工具readelf查看文件中的符号表,如目标文件foo2.o的符号表如下:root@baisheng:~/demo# readelf -s foo2.oSymbol table '.sy
-
既然在链接时,需要重定位目标文件中引用的外部符号,显然,链接器需要知道这些符号的定义在哪里,为此汇编器在每个目标文件中创建了一个符号表,符号表中记录了这个模块定义的可以提供给其他模块引用的全局符号。可以使用工具readelf查看文件中的符号表,如目标文件foo2.o的符号表如下:
root@baisheng:~/demo# readelf -s foo2.o
Symbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS foo2.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 6
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 5
8: 00000000 4 OBJECT GLOBAL DEFAULT 3 foo2
9: 00000000 16 FUNC GLOBAL DEFAULT 1 foo2_func根据输出可见,foo2.o符号表包含10个符号。Value列表示的是符号的地址。前面我们提到,链接时链接器才会为符号分配地址,所以我们看到的符号的地址全部是0。Size列表示符号对应的实体占据的内存大小,如变量foo2占据4字节,函数foo2_func占据16字节。Type列表示符号的类型,如foo2类型为OBJECT,表示变量;foo2_func类型为FUNC,表示函数。Bind列表示符号绑定的相关信息,LOCAL表示模块内部符号,对外部不可见;GLOBAL表示全局符号,foo2和foo2_func都属于全局变量。Ndx列表示该符号在哪个段,如foo2在第3个段,即“.data”段,foo2_func在第1个段,即“.text”段。Name列表示符号的名称。
除了模块定义的符号外,符号表中也包括了模块引用的外部符号,如模块hello的符号表如下:
root@baisheng:~/demo# readelf -s hello.o
Symbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS hello.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 6
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 5
8: 00000000 33 FUNC GLOBAL DEFAULT 1 main
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND foo2
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND foo2_func符号foo2和foo2_func都在模块foo2中定义,对于模块hello来说是外部符号,没有在任何一个段中, 所以在列Ndx中,foo2和foo2_func的值是UND。UND是Undefined的缩写,表示符号foo2、foo2_func是未定义的。
在链接时,对于模块中引用的外部符号,链接器将根据符号表进行符号的重定位。如果我们将符号表删除了,那么链接器在链接时将找不到符号的定义,从而不能进行正确的符号解析。如我们将foo2.o中的符号表删除,再次进行链接,则链接器将因找不到符号定义而终止链接,如下所示:
root@baisheng:~/demo/tmp# strip foo2.o
root@baisheng:~/demo# gcc -o hello *.o
/usr/bin/ld: error in foo2.o(.eh_frame); no .eh_frame_hdr table will be created.
hello.o: In function 'main':
hello.c:(.text+0xb): undefined reference to 'foo2'
hello.c:(.text+0x1b): undefined reference to 'foo2_func'
collect2: error: ld returned 1 exit status
更多推荐
所有评论(0)