linux符号表简介

来源:互联网 发布:dnf上号就网络连接中断 编辑:程序博客网 时间:2024/06/10 00:25

既然在链接时,需要重定位目标文件中引用的外部符号,显然,链接器需要知道这些符号的定义在哪里,为此汇编器在每个目标文件中创建了一个符号表,符号表中记录了这个模块定义的可以提供给其他模块引用的全局符号。可以使用工具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