通过 PLT 访问共享库函数
Accessing a shared library function through PLT
关于从用户代码访问共享库函数,我有些不明白。
我不明白为什么在那种情况下需要 PLT。我自己的代码没有共享所以可以改,那我们何不看看共享库的函数是在什么地址加载的,改代码直接访问,不用每次都通过PLT。
是不是我自己的代码加载到内存后才知道那个地址?
这到底是什么原因?
My own code is not shared so it can be changed,
您自己的代码不会共享 仅当您 运行 系统上有您的程序的单个副本时 。如果您 运行 多个副本,那么您的代码 是 在进程之间共享的,写入它会阻止这种共享。
注意:这是针对可执行文件的 独立 调用。如果多个进程具有 parent/child 关系,即使修改后的代码仍然可以共享。
x86_64
ELF 系统还有一个额外的考虑因素:在默认内存模型 (-mcmodel=medium
) 中,space 根本不够用,例如CALL
调用任意地址的指令:您只能调用距离当前指令 +/-2GiB 的地址。由于呼叫目标可能(通常)较远,因此您无论如何都需要通过 PLT 输入。
最后,通过 PLT 调用允许延迟符号解析,这将 运行时间成本推迟到调用函数的时间,并且 仅 为函数完成被调用。直接重新定位代码会使您的代码表现得好像 LD_BIND_NOW=1
有效,从而使您的二进制文件启动速度变慢(有时 显着 变慢)。
关于从用户代码访问共享库函数,我有些不明白。
我不明白为什么在那种情况下需要 PLT。我自己的代码没有共享所以可以改,那我们何不看看共享库的函数是在什么地址加载的,改代码直接访问,不用每次都通过PLT。
是不是我自己的代码加载到内存后才知道那个地址?
这到底是什么原因?
My own code is not shared so it can be changed,
您自己的代码不会共享 仅当您 运行 系统上有您的程序的单个副本时 。如果您 运行 多个副本,那么您的代码 是 在进程之间共享的,写入它会阻止这种共享。
注意:这是针对可执行文件的 独立 调用。如果多个进程具有 parent/child 关系,即使修改后的代码仍然可以共享。
x86_64
ELF 系统还有一个额外的考虑因素:在默认内存模型 (-mcmodel=medium
) 中,space 根本不够用,例如CALL
调用任意地址的指令:您只能调用距离当前指令 +/-2GiB 的地址。由于呼叫目标可能(通常)较远,因此您无论如何都需要通过 PLT 输入。
最后,通过 PLT 调用允许延迟符号解析,这将 运行时间成本推迟到调用函数的时间,并且 仅 为函数完成被调用。直接重新定位代码会使您的代码表现得好像 LD_BIND_NOW=1
有效,从而使您的二进制文件启动速度变慢(有时 显着 变慢)。