c++ - 共享库的外部符号如何在主程序中解析?
问题描述
我已经阅读了很多关于共享库的加载时链接的语义,而我无法理解的一件事是主程序如何引用共享库中定义的函数?例如,假设我有这个代码
myShared.sh
int get(){
return 0;
}
主程序
extern int get();
int main(){
int a = get();
}
我理解,由于共享库不能对它们的放置位置做出任何断言,它们必须使用 GOT 和 PLT 来引用它们自己的函数和全局数据。但是使用上述库的实际程序如何知道函数将被加载到哪里,以便可以引用它们呢?显然,链接器不知道,因为这些库的链接直到加载时才会发生。所以,我能想到的只有两种方法可以引用这些外部函数。
链接器只需将一些占位符放置在
get
(在上面的示例中)被调用的位置,然后添加一些必要的元数据,然后加载器来用函数的实际地址替换占位符(例如共享库如何使用 Load -在 PIC 之前重新定位)但这会导致显着的开销,并且是最初引入 PIC 的动机(我认为)主程序也有自己的 GOT 和 PLT,加载程序还必须沿着共享库的 GOT 填充主程序的 GOT(在加载全局变量的情况下一次全部完成,或者以惰性方式使用 PLT对于函数)但这听起来像是一个主要的重复工作。
那么,如果有的话,这两个中的哪一个是用于解析共享库的外部符号的方法?
解决方案
主程序中的符号解析与共享库中的符号解析没有太大区别,是通过主程序的 GOT 和 PLT 表来实现的。您是正确的,这会在静态(ld
)和动态(ld.so
)链接器之间产生一定量的重复,并减慢程序启动速度,但另一方面允许在运行时增加灵活性(例如通过 插入符号LD_PRELOAD
)。
推荐阅读
- java - 使用 Enum 的 Spring 请求 notempty 验证
- android - 如何从字符串变量中的 Firebase 数据库访问此嵌套值?
- javascript - 在 webpack 中操作(第一个)块的名称?
- python - 如何在 python 中使用 request.post() 方法处理异常
- c# - C# - 将 Int 转换为 Hex 4 字节
- c++ - 如何从 C++ 中的张量流变量中获取数据
- ruby-on-rails - Rails6.0.0 + Faker +Devise + Seed
- neo4j - 项目启动时如何让 Spring Data Neo4j 忽略连接检查?
- sql - 当列小于0时如何计算SQL中的总时间
- wordpress - 如何仅针对移动设备禁用来自 wordpress 网站的一个信号推送通知