• 了解动态链接(六)—— 重定位表


    柳条青青,南风熏熏,幻化奇峰瑶岛,一天的黄云白云,那边麦浪中间,有农妇笑语殷殷。问后园豌豆肥否,问杨梅可有鸟来偷;好几天不下雨了,玫瑰花还未曾红透;梅夫人今天进城去,且看她有新闻无有。—— 徐志摩·夏日田间即景

    ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287

    无论是可执行文件还是 so,只要它依赖于其他 so(.dynsym 动态符号表中有导入符号存在),那么在编译链接阶段,这些符号的地址未知,所以只能在动态链接阶段对其进行地址重定位。

    注意:以 PIC 编译的 so,虽然称“地址无关代码”,但也需要重定位。因为对于 PIC 的 so 来说,只不过是把代码中的绝对地址提出来,放到了数据段的 GOT 表中。所以,虽然代码段不需重定位,但数据段的 GOT 表需要重定位。(以 PIC 编译 so,是为了复用 so 的代码段)

    以 android liblog.so 为例。在代码中调用 memset 时,实际上会跳转到标号 memset_ptr 指向的内存。

     

    而标号 memset_ptr 指向的内存就定义在 GOT 表中:

     

    那么如何为 GOT 表做重定位呢?GOT 表中的每一项应该指向哪一个符号在内存中的地址呢?这些信息就由重定位表来描述。具体到 android 来说,重定位表保存在 .rel.dyn 和 .rel.plt 中。

     

    从表中可以看出,位于 .rel.dyn 中的主要是 R_ARM_GLOB_DAT 类型的重定位项,而位于 .rel.plt 中的主要是 R_ARM_JUMP_SLOT 类型的重定位项。前者用于对数据引用做重定位,而后者用于对函数引用做重定位。除此之外,还看到了 R_ARM_RELATIVE 类型的重定位。

    在 android linker 的源码中,调用了两次 soinfo_relocate 函数,分别为 .rel.dyn 和 .rel.plt 做重定位:

     

    在 soinfo_relocate 函数的源码中可以看到,对于不同类型的重定位,计算符号地址的方式也有所不同。

     

    实际上对于 R_ARM_GLOB_DAT、R_ARM_JUMP_SLOT 这两种重定位类型来说,只需将符号地址填入被修正的内存即可。而 R_ARM_RELATIVE 类型看起来特殊些,它的作用是进行基址重置 (Rebasing) 。

    比如指针 p 指向静态变量 a,而静态变量 a 相对于 so 基址的偏移为 A。在编译时,so 的基址为 0,此时 p 的值为 A。而当 so 被装载到内存中时,p 的值就需要加上一个 so 在内存中的基址 base。R_ARM_RELATIVE 类型的重定位就是用来干这个的。

    对于 android linker 的重定位细节,以及其他重定位类型,在后面写 android linker 源码分析笔记时再描述。

    学习资料: 《程序员的自我修养——链接、装载和库》

  • 相关阅读:
    Java母牛繁殖问题
    【转】区块链交易的并发执行
    Cinder 架构分析、高可用部署与核心功能解析
    【转】区块链的隐私保护方案介绍
    如何在ES6中判断类中是否包含某个属性和方法
    阿里云MySQL及Redis灵异断连现象:安全组静默丢包解决方法
    如何区别ES5和ES6创建类(异同点)
    这两家独角兽企业在强敌缠斗中崛起
    来看一看那些已经倒闭的互联网公司
    《并行计算的编程模型》一3.6.1 全局同步屏障
  • 原文地址:https://www.cnblogs.com/ilocker/p/4641769.html
Copyright © 2020-2023  润新知