如何在主程序中解析共享库的外部符号?

时间:2019-02-20 11:24:13

标签: c++ linux shared-libraries dynamic-linking relocation

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

myShared.sh

int get(){
   return 0;
}

main.c

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

我知道,由于共享库无法对它们的放置位置进行任何断言,因此它们必须使用GOT和PLT来引用其自身的功能和全局数据。但是使用所述库的实际程序如何知道将在何处加载函数,以便可以对其进行引用?显然,链接器不知道,因为此类库的链接要等到加载时才发生。因此,我只能想到两种方法来引用此类外部函数。

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

  2. 主程序还具有自己的GOT和PLT,并且加载程序还必须将主程序的GOT和共享库的GOT一起填充(要么在加载过程中一次加载全局变量,要么使用PLT实现功能的懒惰方式),但这听起来像是重复的工作。

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

1 个答案:

答案 0 :(得分:4)

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