[英]how does dynamic linker resolve references while the application is running?
[英]How does dynamic linker changes text segment of process?
如果我正确理解当用户尝试执行动态链接的可执行文件(使用execve("foo", "", "")
)而不是加载“foo”的文本段时,会加载动态链接器(ld-linux.so.2)和执行。 它必须加载程序所需的库(“foo”)来运行并更改“foo”中的一些地址并将控制传递给foo,但这是如何完成的?
如何(它使用什么系统调用)以及动态加载器在内存中加载库和“foo”代码和数据的位置(我猜它不能简单地使用malloc或mmap然后跳转到代码,因为那应该是不可能的,对吧?它似乎也不太可能创建完整可执行文件的临时文件(如静态链接的)和再次调用。)。
实际的实现非常复杂,因为它建立在ELF之上,由于它试图适应许多场景,因此非常复杂,但从概念上讲它非常简单。
基本上(在库依赖项被定位并open
),它是几个mmap , mprotect ,通过绑定符号实现链接的一些修改(可以延迟),然后跳转到代码。
理想情况下,链接的共享库将使用-fpic
/ -fPIC
进行编译,这将允许链接器将它们放在进程地址空间中的任何位置,而无需写入库的.text
部分(=可执行代码)。 这样的库/可执行文件将通过可修改的表调用来自其他库的函数,链接器将修复(可能是懒惰)以指向它已加载依赖库的实际位置。 从一个共享库到另一个共享库的变量访问同样是间接的。
尽可能限制修改库数据/代码允许将代码段标记为只读(通过MMU / mprotect
系统调用)并映射到在使用该特定库的所有进程之间共享的内存中。
要了解在系统调用级别发生的事情,您可以尝试例如:
strace /bin/echo hello world
并且所有包含sbrk
的系统调用(=设置堆/ .data
段)应该是动态链接器的操作。
( malloc
确实对链接器不可用,因为malloc
是c库的一个特性,而不是系统malloc
是关于增长和管理堆部分,并且可能对其他单独的块进行mmap
ping并管理那些以及可写的“堆”,并且动态链接器不关心过程映像的这些部分,主要是它的可写间接表以及它映射库的位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.