Linux 的内核在执行 execve() 的时候不关心目标 elf 文件是不是可以执行的,它只是通过程序头表里的描述对文件进行装载和把控制权交给 elf 的入口地址(如果没有 .interp 就是 e_entry,如果有就是动态链接器的 e_entry

所以动态链接器也是可以作为可执行文件运行的,这也从一个侧面说明了共享库和可执行文件其实没有什么区别,除了文件头的标志位和拓展名有不同之外,其他都是一样的。Windos 也有一个 rundll32 工具来运行 dll 文件

ELF 动态链接器的入口在 dl-manchine.h,普通程序的入口地址在 start.S

_start 调用 rtld.c_ld_start() 函数,对 ld.so 进行重定位,完成自举,然后调用 _dl_start_final 收集一些基本的运行数值,进入 _dl_sysdep_start 进行平台相关处理,进入 _dl_main,动态链接器的主函数先进行判断:用户的入口地址是不是动态链接器本身,如果是的话,说明动态链接器是可以被当作可执行文件在执行,这种情况下,动态链接器会解析相应的参数进行处理。随后对依赖的共享对象进行装载、符号解析和重定位等等

  • 动态链接器是静态链接的,因为它不能够依赖其他共享对象
  • 动态链接器是 PIC 的,这样可以简化操作,不用在自举的时候最自己重定位
  • 作为一个共享库,动态链接器在装载的时候会自动选择一个合适的装载地址,即不是固定的