共享库的外部符号如何在主程序中解析?
Posted
技术标签:
【中文标题】共享库的外部符号如何在主程序中解析?【英文标题】:How are external symbols of a shared library resolved in the main program? 【发布时间】:2019-02-20 11:24:12 【问题描述】:我已经阅读了很多关于共享库的加载时链接的语义,但我无法理解的一件事是主程序如何引用共享库中定义的函数?例如,假设我有这个代码
myShared.sh
int get()
return 0;
main.c
extern int get();
int main()
int a = get();
我理解,由于共享库不能对它们的放置位置做出任何断言,它们必须使用 GOT 和 PLT 来引用它们自己的函数和全局数据。但是使用所述库的实际程序如何知道函数将被加载到哪里,以便它可以引用它们呢?显然,链接器不知道,因为这些库的链接直到加载时才会发生。所以,我能想到的只有两种方法可以引用这些外部函数。
-
1234563函数(就像共享库如何在 PIC 之前使用加载时重定位)但这会导致显着的开销,并且是(我认为)首先引入 PIC 的动机
主程序也有自己的 GOT 和 PLT,加载器还必须沿着共享库的 GOT 填充主程序的 GOT(在全局变量的情况下在加载期间一次全部完成,或者以一种懒惰的方式将 PLT 用于函数)但这听起来像是重复劳动。
那么,如果有的话,这两种方法中的哪一种是用于解析共享库的外部符号的方法?
【问题讨论】:
this 有用吗? @JulianH 如果我没记错的话,在 Linux 和共享对象上,链接发生在加载时(在运行之前,而不是编译时)。请注意,该 OP 明确标记了 Linux。 (我知道 Windows 上的 DLL 在这方面有点不同。) @Scheff 我认为在 Linux 上您必须将库的名称传递给 g++,以便链接器能够解析这些符号。如果你用dlopen
链接,你不能用extern
来寻址get
@JulianH 我刚刚发现:Static, Shared Dynamic and Loadable Linux Libraries: 为运行时链接编译 ... 这些库不会包含在可执行文件中,但会包含在可执行文件中在运行时执行期间动态链接。 ;-) 我将其理解为:在编译时它是“链接的”,为运行时链接做准备。我在吹毛求疵吗?
是的,我明白了,Linux 和 Windows 之间存在差异,抱歉。
【参考方案1】:
主程序中的符号解析与共享库中的符号解析没有太大区别,是通过主程序的 GOT 和 PLT 表来实现的。您是正确的,这会在静态 (ld
) 和动态 (ld.so
) 链接器之间产生一定量的重复,并减慢程序启动速度,但另一方面可以提高运行时的灵活性(例如,通过 LD_PRELOAD
插入符号) .
【讨论】:
以上是关于共享库的外部符号如何在主程序中解析?的主要内容,如果未能解决你的问题,请参考以下文章