动态链接器如何更改进程的文本段?
How does dynamic linker changes text segment of process?
如果我在用户尝试执行动态链接时理解正确
可执行文件(使用 execve("foo", "", "")
)而不是加载 "foo" 动态链接器的文本段被加载(ld-linux.so.2)并执行。它必须加载
程序所需的库 ("foo") 到 运行 并更改一些地址
在 "foo" 并将控制权传递给 foo,但这是如何完成的?
如何(它使用什么系统调用)和在哪里
动态加载程序加载库和内存中的 "foo"s 代码和数据(我猜它不能简单地使用
malloc 或 mmap,然后跳转到代码,因为那应该是不可能的,
正确的?它似乎也不太可能创建完整的临时文件
可执行文件(如静态链接的)并再次调用 exceve。
实际实现相当复杂,因为它建立在 ELF 之上,ELF 非常复杂,因为它试图适应许多场景,但从概念上讲它非常简单。
基本上(在找到库依赖项并 open
ed 之后)它是几个 mmaps,mprotects ,一些修改以通过绑定符号(可以延迟)实现链接,然后跳转到代码。
理想情况下,链接的共享库将使用 -fpic
/-fPIC
进行编译,这将允许链接器将它们放置在进程地址 space 中的任何位置,而无需写入库的 .text
部分(=executable 代码)。
这样的 library/executable 将通过可修改的 table 调用其他库中的函数,链接器将修复(可能是懒惰地)以指向它加载依赖库的实际位置。
从一个共享库到另一个共享库的变量访问同样是间接的。
尽可能限制修改库data/code允许将代码段标记为只读(通过MMU/mprotect
系统调用)并映射到所有共享的内存中使用该特定库的进程。
要了解在系统调用级别发生了什么,您可以尝试例如:
strace /bin/echo hello world
以及包括的所有系统调用,直到大约 sbrk
(=设置堆/.data
段)应该是动态链接器的工作。
(malloc
确实对链接器不可用,因为 malloc
是 c 库的一个特性,而不是系统。malloc
是关于增长和管理堆部分并可能mmap
ping 其他单独的块并管理它们以及 writable "heap",并且动态链接器不关心过程映像的这些部分,主要只是它的 writable 间接 tables 及其映射库的位置)。
如果我在用户尝试执行动态链接时理解正确
可执行文件(使用 execve("foo", "", "")
)而不是加载 "foo" 动态链接器的文本段被加载(ld-linux.so.2)并执行。它必须加载
程序所需的库 ("foo") 到 运行 并更改一些地址
在 "foo" 并将控制权传递给 foo,但这是如何完成的?
如何(它使用什么系统调用)和在哪里 动态加载程序加载库和内存中的 "foo"s 代码和数据(我猜它不能简单地使用 malloc 或 mmap,然后跳转到代码,因为那应该是不可能的, 正确的?它似乎也不太可能创建完整的临时文件 可执行文件(如静态链接的)并再次调用 exceve。
实际实现相当复杂,因为它建立在 ELF 之上,ELF 非常复杂,因为它试图适应许多场景,但从概念上讲它非常简单。
基本上(在找到库依赖项并 open
ed 之后)它是几个 mmaps,mprotects ,一些修改以通过绑定符号(可以延迟)实现链接,然后跳转到代码。
理想情况下,链接的共享库将使用 -fpic
/-fPIC
进行编译,这将允许链接器将它们放置在进程地址 space 中的任何位置,而无需写入库的 .text
部分(=executable 代码)。
这样的 library/executable 将通过可修改的 table 调用其他库中的函数,链接器将修复(可能是懒惰地)以指向它加载依赖库的实际位置。
从一个共享库到另一个共享库的变量访问同样是间接的。
尽可能限制修改库data/code允许将代码段标记为只读(通过MMU/mprotect
系统调用)并映射到所有共享的内存中使用该特定库的进程。
要了解在系统调用级别发生了什么,您可以尝试例如:
strace /bin/echo hello world
以及包括的所有系统调用,直到大约 sbrk
(=设置堆/.data
段)应该是动态链接器的工作。
(malloc
确实对链接器不可用,因为 malloc
是 c 库的一个特性,而不是系统。malloc
是关于增长和管理堆部分并可能mmap
ping 其他单独的块并管理它们以及 writable "heap",并且动态链接器不关心过程映像的这些部分,主要只是它的 writable 间接 tables 及其映射库的位置)。