我知道 ELF 可执行文件需要有一个可见的_start
子例程来开始执行。然而,据我所知,内核实际上调用了ld-linux.so
(或其他一些解释器)并将执行移交给它。所以,我的问题是:
- 谁规定了
_start
入口点? - 内核如何“调用”
ld-linux.so
?有稳定的API吗?_start
可以这么说,一个函数?
奖金问题:粗略一看,Glibclibdl
和ld-linux.so
都是同一个代码库的一部分,并且紧密地缠绕在一起(使用彼此的私有接口)。这是否意味着不可能编写一个自定义的libdl
等效库来实现dlopen
等?非C系统语言是否不可能生成不依赖libc
且仍然可以加载*.so
文件的二进制文件?
答案1
入口点通常命名为_start
,并在链接到可执行文件的 C 运行时汇编例程中定义。这段简短的代码负责设置堆栈,可能调用 C++ 构造函数,最后调用main
.程序从何处开始执行的最终答案是e_entry
可执行文件中 ELF 标头中的值。该值_start
由链接器设置为指向。
您可以通过使用检查可执行程序来看到这一点readelf -a progfile
。
动态链接使事情变得有点复杂,因为动态链接器首先被加载和启动,负责加载和链接程序所需的共享库。动态链接器也在可执行文件中指定(称为“程序解释器”。)