动态链接器如何更改进程的文本段?

时间:2016-06-15 15:36:01

标签: c linux dynamic dynamic-linking

如果我在用户尝试动态链接时正确理解 可执行文件(用execve("foo", "", ""))而不是加载文本段“foo”动态链接器加载(ld-linux.so.2)并执行。它必须加载 程序(“foo”)运行和更改某些地址所需的库 在“foo”中并将控制传递给foo,但这是如何完成的?

如何(它使用什么系统调用)以及在哪里 动态加载器加载库和“foo”的代码和数据在内存中(我猜它不能简单地使用  malloc或mmap,然后跳转到代码,因为这应该是不可能的,   对?它似乎也不太可能创建完整的临时文件   可执行文件(如静态链接的)和再次调用。)。

1 个答案:

答案 0 :(得分:0)

实际的实现非常复杂,因为它建立在ELF之上,由于它试图适应许多场景,因此非常复杂,但从概念上来说它非常简单。

基本上(在找到库依赖项并且open之后),它有几个 mmap s, mprotect ,实现了一些修改通过绑定符号链接(可以延迟),然后跳转到代码。

理想情况下,链接的共享库将使用-fpic / -fPIC进行编译,这将允许链接器将它们放在进程地址空间中的任何位置,而无需写入.text部分库的(=可执行代码)。 这样的库/可执行文件将通过可修改的表调用来自其他库的函数,链接器将修复(可能是懒惰)以指向它已加载依赖库的实际位置。 从一个共享库到另一个共享库的变量访问同样是间接的。

尽可能限制修改库数据/代码允许将代码段标记为只读(通过MMU / mprotect系统调用)并映射到所有共享的内存中使用该特定库的进程。

要了解在系统调用级别发生的事情,您可以尝试例如:

strace /bin/echo hello world

并且所有包含约sbrk的系统调用(=设置堆/ .data段)应该是动态链接器的操作。

malloc确实对链接器不可用,因为malloc是c库的一个特性,而不是系统。malloc是关于增长和管理堆部分的,可能是{{} 1}} ping其他单独的块并管理那些以及可写的" heap",动态链接器不关心过程映像的这些部分,主要是它的可写间接表和哪里它映射了图书馆。)