Mel*_*lab 29 dynamic-linking strace dynamic-loading shared-library
在strace输出中,可执行文件调用的库的路径在调用中open()。这是动态链接的可执行文件使用的系统调用吗?怎么样dlopen()?open()不是我猜想的调用会在程序执行中发挥作用。
dlopen 与您认为的共享库无关。加载共享对象有两种方法:
main函数之前被调用,并设置应用程序的进程空间,以便应用程序找到库的函数。这涉及到open()ing lubrary,然后mmap()ing 它,然后设置一些查找表。libdl,然后你(使用第一种方法)可以调用dlopen()和dlsym()职能。使用 dlopen,您可以获得库的句柄,然后您可以将其与 dlsym 一起使用以接收指向特定函数的函数指针。对于程序员来说,这种方法比第一种方法复杂得多(因为您必须手动进行设置,而不是让链接器自动为您完成),而且它也更脆弱(因为您没有得到编译-time 检查您在第一个方法中获得的参数类型是否正确调用函数),但优点是您可以决定在运行时加载哪个共享对象(甚至是否加载它),使得这是一个用于插件类型功能的接口。最后,dlopen 接口的可移植性也低于其他方式,因为它的机制取决于动态链接器的确切实现(因此 libtool 的libltdl,它试图抽象出这些差异)。ltrace -S一个最小示例的分析表明它mmap在 glibc 2.23 中使用
在 glibc 2.23、Ubuntu 16.04 中,运行latrace -S在使用以下命令的最小程序上dlopen:
ltrace -S ./dlopen.out
Run Code Online (Sandbox Code Playgroud)
显示:
dlopen("libcirosantilli_ab.so", 1 <unfinished ...>
SYS_open("./x86_64/libcirosantilli_ab.so", 524288, 06267650550) = -2
SYS_open("./libcirosantilli_ab.so", 524288, 06267650550) = 3
SYS_read(3, "\177ELF\002\001\001", 832) = 832
SYS_brk(0) = 0x244c000
SYS_brk(0x246d000) = 0x246d000
SYS_fstat(3, 0x7fff42f9ce30) = 0
SYS_getcwd("/home/ciro/bak/git/cpp-cheat"..., 128) = 54
SYS_mmap(0, 0x201028, 5, 2050) = 0x7f1c323fe000
SYS_mprotect(0x7f1c323ff000, 2093056, 0) = 0
SYS_mmap(0x7f1c325fe000, 8192, 3, 2066) = 0x7f1c325fe000
SYS_close(3) = 0
SYS_mprotect(0x7f1c325fe000, 4096, 1) = 0
Run Code Online (Sandbox Code Playgroud)
所以我们立即看到dlopen调用open+ mmap。
这个很棒的ltrace工具可以跟踪库调用和系统调用,因此非常适合检查这种情况下发生的情况。
仔细分析表明,它open返回文件描述符3(stdin、out 和 err 之后的下一个空闲描述符)。
read然后使用该文件描述符,但是TODO 为什么mmap参数被限制为四个,并且我们看不到那里使用了哪个 fd,因为这是第五个参数。strace正如所料,证实了这3一点,宇宙的秩序得以恢复。
勇敢的灵魂也可以冒险进入 glibc 代码,但我在快速 grep 后找不到,mmap而且我很懒。
使用 GitHub 上的构建样板对这个最小示例进行了测试。
| 归档时间: |
|
| 查看次数: |
14052 次 |
| 最近记录: |