首页 > 解决方案 > 符号迁移

问题描述

以下是如何解决函数调用(第一次)PIC

  1. 跳转到PLT我们符号的条目。
  2. 跳转到GOT我们符号的条目。
  3. 跳回PLT入口并在堆栈上压入一个偏移量。偏移量实际上是Elf_Rel描述如何修补符号的结构。
  4. 跳转到PLT存根条目。
  5. 推送一个指向link_map结构的指针,以便链接器找到符号所属的库。
  6. 调用解析程序例程。
  7. 修补GOT条目。

这与仅使用GOT表的数据引用方式不同

那么,为什么会有这种差异呢?为什么有两种不同的方法?


标签: linkersymbolsrelocation

解决方案


为什么会有这种差异?为什么有两种不同的方法?

你描述的是懒惰的搬迁。

您不必使用它,如果在环境中设置了eg ,您也不会使用它。LD_BIND_NOW=1

这是一种优化:当特定程序调用没有使用许多可能的程序执行路径时,它允许您减少动态链接器必须执行的工作量。

想象一个程序,它可以根据参数调用或foo(),并且在任何给定的执行中恰好调用其中一个例程。bar()baz()

如果您不使用延迟重定位,动态加载程序将必须在程序启动时解析所有 3 个例程。惰性重定位允许动态加载器仅在任何给定执行(被调用的一个函数)中以及在正确的时间(调用函数)仅执行一个实际需要的重定位。

现在,为什么变量也不能这样解决?

因为动态加载器没有方便的方法知道何时执行该重定位。

假设全局变量是a, band c, andfoo()引用aand b,bar()引用band c, andbaz()引用aand c。理论上,动态加载器可以扫描 和 的主体foobarbaz构建“如果调用foo,则还解析全局变量aand b”等映射。但是在启动时解析对全局变量的所有引用要简单得多,而且速度更快。


推荐阅读