链接的接口——符号

链接的本质就是将多个目标文件拼接到一起形成可执行文件。为了使不同的目标文件之间能够拼接,必须有一定的规则才行,就像协议一样。在链接中,目标文件之前的相互拼接实际上是目标文件之间对地址的引用,即对函数和变量的地址的引用。比如目标文件B用到了目标文件A中的函数foo,就称目标文件A定义了函数foo,目标文件B引用了目标文件A中的函数foo。在链接中,我们将函数和变量统称为符号,函数名或变量名就是符号名。

整个链接的过程正是基于符号才能够正确完成。链接过程中很关键的一部分就是符号管理,每一个目标文件都会有一个相应的符号表,这个表里记录了目标文件中所用到的所有符号。每个定义的符号有一个对应的值,叫做符号值,对于变量和函数来说,符号值就是他们的地址。

符号表中的分类:

  • 定义在本目标文件中的全局符号,可以被其他目标文件引用。
  • 在本目标文件中引用的全局符号,却没有定义在本目标文件。
  • 段名,这种符号往往由编译器产生,它的值就是该段的起始地址。
  • 局部符号,这类符号只在编译单元内部可见。这些局部符号对于链接过程没有作用,链接器往往忽略它们。
  • 行号信息,即目标文件指令与源代码中代码行的对应关系,它也是可选的。

对于我们来说,最值得关注的就是全局符号,即上面分类中的第一类和第二类。因为链接过程只关心全局符号相互黏合,局部符号、段名、行号都是次要的,它们对于其他目标文件来说是不可见的,在链接过程中也是无关紧要的。