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

myShared.sh

int get(){
   return 0;
}

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

我知道,由于共享库无法对放置位置进行任何断言,因此它们必须使用GOT和PLT引用其自身的功能和全局数据。但是,使用上述库的实际程序如何知道将在何处加载函数,以便可以对其进行引用?显然,链接器不知道,因为此类库的链接要等到加载时才发生。因此,我只能想到两种方法来引用此类外部函数。
  • 链接器只是在调用get的地方放置了一些占位符(在上面的示例中),然后添加了一些必要的元数据,以使加载程序可以使用该数据并将占位符替换为函数的实际地址(例如共享库的方式)在PIC之前使用了加载时重定位),但是这导致了显着的开销,并且(我认为)是最初引入PIC的动机(
  • )
  • 主程序还具有自己的GOT和PLT,并且加载程序还必须同时填充主程序的GOT和共享库的GOT(在全局变量加载过程中一次全部加载,也可以使用函数的PLT)但这听起来像是一项主要的重复工作。

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

    最佳答案

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

    关于c++ - 如何在主程序中解析共享库的外部符号?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54785183/

    10-10 17:10
    查看更多