繁体   English   中英

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

[英]how does dynamic linker resolve references while the application is running?

假设我有一个源文件dll.c ,它使用dlopendlsym函数在运行时加载一个名为F.so的共享库。

dll.c有对some_function()的引用,而F.sosome_function()的定义。

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

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

在此处输入图片说明

所以.text部分包含了some_function()的引用,当 porgram 加载F.so并开始调用some_function()时需要解析该引用

我的问题是:

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

Q2-如果动态链接器需要修改RAM中的.text段,它是怎么做的? 根据我的理解, .text段是 RAM 中的只读段,如果它被称为只读,如何修改只读段?

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

不必如此。 有PLT(程序链接表)。 它本质上是这样的:

foo@PLT:
        jmp <someTemporaryAddress>
main:
        call foo@PLT

然后,在运行时,动态链接器只修补这一部分,因为它比在大量机器代码中查找调用更简单。

Q2-如果动态链接器需要修改RAM中的.text段,它是怎么做的? 根据我的理解,.text 段是 RAM 中的只读段,如果它被称为只读,如何修改只读段?

它在使其可执行/只读之前完成。

Q1 - 在我看来,RAM 中的 .text 部分(some_function() 所属的部分)(可执行文件被复制到内存中)需要由动态链接器修改......

不。实际代码使用间接跳转:

.text
    ...
    call *xsome_function
    ...

.data
xsome_function:
    .long some_function

...所以call指令不会跳转到某个地址,而是会跳转到存储在.data部分中的某个地址。 动态链接器必须替换.long some_function行中的地址,而不是call指令中的地址。

如果链接包含“直接” call指令的代码,链接器将执行 JCWasmx86 在其回答中所写的操作:

.text
    ...
    call some_function@PLT
    ...
some_function@PLT:
    jmp *xsome_function

.data
xsome_function:
    .long some_function

再一次,动态链接器只需要替换.data部分中的地址。

dlopen

如果您使用dlopendlsym访问您的库,则动态链接器甚至不会替换任何内容:

dlsym()返回一些函数指针,该指针的处理方式与其他函数返回的任何其他指针一样(如malloc()返回的指针)。 调用dlsym()的程序负责以某种方式存储指针。

当使用函数指针调用函数时,编译器总是会创建一个间接跳转指令(例如call %eax )。

Q2 - 如果动态链接器需要修改 RAM 中的 .text 部分,...

几年前,我为 Linux 编写了一些小型编译器/链接器。

因为我来自 Windows 开发,并且 Window 的动态链接器实际上替换了.text部分中的地址,所以我编写编译器/链接器的方式与在 Windows 下相同:

结果:动态链接器 ( ld-linux.so ) 在运行使用我的编译器编译的程序时崩溃,导致“分段错误”,因为动态链接器无法写入 Linux 下的.text段。

- 编辑 -

一个例子:

如果使用dlopen()dlsym() ,C 代码看起来不是这样的:

extern double sin(double x);
...
sine = sin(angle);

相反,C 代码如下所示:

static double (*psin)(double x);
...
sofile = dlopen("libm.so",FLAGS);
psin = dlsym(sofile,"sin");
...
sine = psin(angle);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM