以下是如何在PIC
中解决函数调用(第一次)
PLT
条目。GOT
条目。PLT
条目并在堆栈上推送偏移量。那个
offset实际上是一个描述如何修补符号的Elf_Rel
结构。PLT
存根条目。link_map
结构,以便链接器可以
找到符号所属的库。GOT
条目。这与仅使用GOT
表
那么,为什么会出现这种差异呢?为什么有两种不同的方法?
答案 0 :(得分:1)
为什么会出现这种差异?为什么有两种不同的方法?
您所描述的是 lazy 重定位。
您 LD_BIND_NOW=1
已在环境中设置。
它是一种优化:当特定程序调用不执行许多可能的程序执行路径时,它允许您减少动态链接器必须执行的工作量。
想象一个程序可以根据参数调用foo()
,bar()
或baz()
,并且在任何给定的执行中调用完全其中一个例程
如果您没有使用延迟重定位,动态加载程序必须在程序启动时解析所有3个例程。延迟重定位允许动态加载器仅执行任何给定执行中实际需要的一个重定位(正在调用的一个函数),并且在恰当的时间( 正在调用该函数。)
现在,为什么变量也能以这种方式解决?
因为没有方便的方法让动态加载程序知道何时执行重定位。
假设全局变量为a
,b
和c
,foo()
引用a
和b
,bar()
引用b
和c
以及baz()
引用a
和c
。从理论上讲,动态加载程序可以扫描foo
,bar
和baz
的主体,并构建一个&#34的映射;如果调用foo
,则还可以解析全局a
1}}和b
"等等。但是在启动时解决对全局变量的所有引用要简单得多,速度更快。