首页 > 解决方案 > 共享库的外部符号如何在主程序中解析?

问题描述

我已经阅读了很多关于共享库的加载时链接的语义,而我无法理解的一件事是主程序如何引用共享库中定义的函数?例如,假设我有这个代码

myShared.sh

int get(){
   return 0;
}

主程序

  extern int get();
  int main(){
    int a = get();
  }

我理解,由于共享库不能对它们的放置位置做出任何断言,它们必须使用 GOT 和 PLT 来引用它们自己的函数和全局数据。但是使用上述库的实际程序如何知道函数将被加载到哪里,以便可以引用它们呢?显然,链接器不知道,因为这些库的链接直到加载时才会发生。所以,我能想到的只有两种方法可以引用这些外部函数。

  1. 链接器只需将一些占位符放置在get(在上面的示例中)被调用的位置,然后添加一些必要的元数据,然后加载器来用函数的实际地址替换占位符(例如共享库如何使用 Load -在 PIC 之前重新定位)但这会导致显着的开销,并且是最初引入 PIC 的动机(我认为)

  2. 主程序也有自己的 GOT 和 PLT,加载程序还必须沿着共享库的 GOT 填充主程序的 GOT(在加载全局变量的情况下一次全部完成,或者以惰性方式使用 PLT对于函数)但这听起来像是一个主要的重复工作。

那么,如果有的话,这两个中的哪一个是用于解析共享库的外部符号的方法?

标签: c++linuxshared-librariesdynamic-linkingrelocation

解决方案


主程序中的符号解析与共享库中的符号解析没有太大区别,是通过主程序的 GOT 和 PLT 表来实现的。您是正确的,这会在静态(ld)和动态(ld.so)链接器之间产生一定量的重复,并减慢程序启动速度,但另一方面允许在运行时增加灵活性(例如通过 插入符号LD_PRELOAD)。


推荐阅读