zoukankan      html  css  js  c++  java
  • 一个程序的前世今生(四)——延迟绑定和GOT与PLT

    简介:

      上一章描述了库文件存在静态和动态的区别,在现代操作系统中由于很多基础库已经存在且复用程度较高,所以使用动态链接库的场景较多。在大多数程序中使用了动态链接技术,使得编译出来的程序占用空间变小,一些公共的库函数如glibc在可执行文件中并没有对应的函数实现。但是动态绑定导致了程序运行时加载时间较长,因此产生了延迟绑定技术在程序运行再根据GOT和PLT查找动态链接库中的实际实现。当然,可以使用gcc链接选项-z,now取消延迟绑定。

    一: GOT表

      什么是 GOT 表?

          每一个外部定义的符号在全局偏移表(Global offset Table)中有相应的条目,GOT位于ELF的数据段中,叫做GOT段。

          GOT 表在 ELF 文件中分为两个部分:

      GOT 表的作用是什么?

          把位置无关的地址计算重定位到一个绝对地址。程序首次调用某个库函数时,运行时连接编辑器(rtld)找到相应的符号,并将它重定位到GOT之后每次调用这个函数都会将控制权直接转向那个位置,而不再调用rtld

      怎么查看 GOT 表?

          在 Linux 系统里,我们可以通过 objdump 命令来查看程序的 GOT 表,具体的指令如下:objdump -R file_name

      在 Linux 的实现中,.got.plt 的前三项的具体的含义如下

    • GOT[0],.dynamic 的地址。
    • GOT[1],指向内部类型为 link_map 的指针,只会在动态装载器中使用,包含了进行符号解析需要的当前 ELF对象的信息。每个 link_map 都是一条双向链表的一个节点,而这个链表保存了所有加载的 ELF 对象的信息。
    • GOT[2],指向动态装载器中 _dl_runtime_resolve 函数的指针。

      .got.plt 后面的项则是程序中不同 .so 中函数的引用地址。下面给出一个相应的关系。

      img

     二: PLT表

      什么是 PLT 表?

          过程连接表(Procedure Linkage Table),一个PLT条目对应一个GOT条目。

          当 main() 函数开始,会请求 plt 中这个函数的对应 GOT 地址,如果第一次调用那么 GOT 会重定位到 plt,并向栈中压入一个偏移,程序的执行回到 _init() 函数,rtld得以调用就可以定位 printf 的符号地址,第二次运行程序再次调用这个函数时程序跳入 plt,对应的 GOT 入口点就是真实的函数入口地址。

          动态连接器并不会把动态库函数在编译的时候就包含到 ELF 文件中,仅仅是在这个 ELF 被加载的时候,才会把那些动态函库数代码加载进来,之前系统只会在 ELF 文件中的 GOT 中保留一个调用地址。

    三:延迟绑定原理

  • 相关阅读:
    Android使用注解代替枚举从而节省系统使用的内存开销
    android9.0系统适配遇到的问题
    android 图片上传图片 报Socket: Broken pipe
    android H5支付 网络环境未能通过安全验证,请稍后再试
    Error:Execution failed for task ':app:processDebugManifest'. Manifest merger failed with multiple errors, see logs
    NightWatch端到端测试
    JavaScript生成斐波那契数列
    Vue Material
    Jasmine
    Postman
  • 原文地址:https://www.cnblogs.com/edver/p/13769582.html
Copyright © 2011-2022 走看看