在可重定位目标文件中,符号表实际是为了标识出符号定义于何处,即符号表条目中的 section/Ndx 记录了这个符号定义在哪个节。
- 对于在该模块定义的全局符号,符号表中很明确的给出了定义在何处
- 而对于引用的外部符号,符号表中也会出现这个条目,但符号表不知道该符号定义在哪里,所以在符号解析时,才会知道具体定义在哪个节。
符号表的主要功能就是记录定义或引用的全局符号定义在哪个位置,等到符号解析时将多个文件的符号表进行整合,确保每一个引用都可以对应上其定义,而不是说记录了符号在哪里被引用了,或引用了多少次。
符号表中存在三类符号:
- 全局符号:定义在本模块的全局变量和函数,和是否被该模块引用过无关。
- 外部符号:引用定义了其他模块的全局符号。即便这些符号被声明了,但没有进行引用,也不会出现在符号表中。
- 局部符号
int unusedg_x = 3;
int g_x = 5;
extern int unusede_x;
extern int e_x;
int unused_test();
int used_test();
int main(){
int a = 5;
used_test();
g_x = a;
g_x = a;
e_x = a;
used_test();
}
其中全局符号 unusedg_x 定义了未被引用,g_x 定义了被引用了两次。
其中外部全局变量 unusede_x 声明了未被引用,e_x 声明后被引用了一次。
外部函数 unused_test() 声明后未被引用, used_test() 声明后被引用了两次。
Num: Value Size Type Bind Vis Ndx Name
8: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 unusedg_x
9: 0000000000000004 4 OBJECT GLOBAL DEFAULT 3 g_x
10: 0000000000000000 69 FUNC GLOBAL DEFAULT 1 main
11: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND used_test
12: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND e_x
- 定义在该模块中无论是否被该模块函数引用的符号,只会在符号表中出现一次
- 没有被引用,但是声明了的外部符号不会出现在该模块的符号表中
- 符号表中没有重复的符号,即便是被引用多次
- 符号表中条目的主要意义就是标识符号被定义的位置,便于让其他模块引用、记录未定义且引用了的外部符号,在链接时从其他模块的符号表中找到该符号的定义。