动态链接器如何在运行时解析引用?

动态链接器如何在运行时解析引用?

假设我有一个源文件dll.c,它使用dlopen和函数来加载在运行时dlsym调用的共享库。F.so

dll.c引用some_function(),并F.so具有 的定义some_function()

假设下图是prog通过以下方式获得的可执行对象

linux> gcc -rdynamic -o prog dll.c -ldl

在此输入图像描述

so部分包含程序加载并开始调用时需要解析.text的引用some_function()F.sosome_function()

我的问题是:

  1. 在我看来, RAM中的.text部分(some_function()属于哪里)(可执行文件被复制到内存中)需要由动态链接器修改,以便some_function()可以解析 的引用,我的理解正确吗?

  2. 如果动态链接器需要修改.textRAM中的部分,它是如何做到的呢?根据我的理解,.textsection是RAM中的只读段,如果只读段被称为只读,那么如何修改它呢?

答案1

您的图表中缺少 ELF 的两个功能,它们用于动态链接:全局偏移表 (GOT) 和过程链接表 (PLT)。 GOT 是用于多种目的的偏移量表,PLT 是用于间接跳转的过程存根表。 GOT 通常是可读写的; PLT 可以是读写的,也可以是只读的(然后由 GOT 条目或单独的 PLT 特定 GOT 支持)。

这允许动态链接器更新符号地址而不触及只读数据。

一些较旧的二进制文件需要修改只读段中的重定位数据;这对于动态链接器来说不是问题,但它确实意味着内存中的相应内存区域不能再在进程之间共享。

如何编写共享库了解详情。

答案2

A.1

.text根据CPU的不同,调用部分的代码some_function()将是某种间接调用。它将在运行时计算地址,可能会缓存结果以提高效率。这使得.text可以保持不变,因此可以共享。代码通常会稍微大一些并且速度慢一些。

A2

这个假设是错误的,所以这个问题不会出现。然而,没有什么可以阻止内核复制内存页面并为其赋予不同的读/写/执行属性并将新页面映射到同一地址。例如,这可以通过ptrace系统调用来完成,并由调试器用来设置软件断点。

相关内容