码迷,mamicode.com
首页 > 移动开发 > 详细

android linker (1) —— __linker_init()

时间:2015-05-30 19:50:23      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:


__linker_init() 在 begin.S 中被调用,并传入两个参数:sp(堆栈指针)、#0。

                       技术分享

 

 

linker(动态链接器,也称解释器)本身也是一个 shared object,__linker_init() 负责初始化 linker,完成 linker 的重定位等工作。由于在调用 __linker_init() 之前,linker 的重定位还没有完成(GOT还不可用),所以任何对外部变量或函数的引用都会产生 segfault。

由于 linker 的重定位由其自己完成,所以该过程称为 bootstrap(自举)。


技术分享 

__linker_init() 的第一步是分解参数,把由 sp 参数传入的 argc、argv、环境变量、ELF aux vectors 分别装入KernelArgumentBlock 对象的相应成员中,方便访问。

技术分享

在 auxv 数组中,类型为 AT_BASE 的项存储有 linker 镜像的开始地址。__linker_init() 由此得到 linker_addr,继而得到 elf_hdr(elf header) 和 phdr(program header) 的地址。

 技术分享


__linker_init() 接着填充一个 soinfo 结构变量。

 技术分享

成员 flags 设置上 FLAG_LINKER,后面见此标记就不会打印调试信息,因为那些调试函数在 linker 完成重定位前尚不可用。

phdr_table_get_load_size() 计算整个 linker 镜像的大小,方法是根据 program header ,找到段内存的最大地址和最小地址,在完成页对齐之后相减。

get_elf_exec_load_bias() 得到 linker 在内存中的加载地址,实际上是第一个可加载段(PT_LOAD)在内存中的虚拟地址。


__linker_init() 接着以 linker_so 作为参数,调用 soinfo_link_image()。

在 soinfo_link_image() 中先找到动态链接段(PT_DYNAMIC)的地址,并得到动态链接结构的数量。然后遍历所有动态链接结构,获取诸如“字符串表地址”、“符号表地址”、“重定位表地址”等重要信息,填充到 soinfo 结构的相应成员中。接着加载所有依赖库,但其实在 linker 自举过程中,它并不依赖于任何其他shared object。重定位工作也是在 soinfo_link_image() 中完成,包括 rel 和 plt_rel(与 PLT 关联的重定位项)。


__linker_init() 最后调用 __linker_init_post_relocation(),从名字可以看出,那些需要在重定位之后才能进行的工作都在这个函数中完成。

__linker_init() 最后返回镜像的入口地址,也就是 elf header 中的 e_entry 保存的虚拟地址。


 

android linker (1) —— __linker_init()

标签:

原文地址:http://www.cnblogs.com/ilocker/p/4540797.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!