zoukankan      html  css  js  c++  java
  • 了解动态链接(六)—— 重定位表

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

    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 源码分析笔记时再描述。

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

  • 相关阅读:
    打成jar包运行,依然可以找到指定路径的xml
    Springboot整合Ehcache 解决Mybatis二级缓存数据脏读 -详细
    Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/dom4j/io/SAXReader
    Springboot + Mybatis + Ehcache
    Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class
    缓存的设计与使用
    一二级缓存
    HttpServletResponse 返回的json数据不是json字符串,而是json对象
    消息中间件选型
    为什么要使用MQ消息中间件?
  • 原文地址:https://www.cnblogs.com/ilocker/p/4641769.html
Copyright © 2011-2022 走看看