全局偏移表(GOT)中非函数类型全局符号的表项如何初始化?
amd64 SysV ABI 中非函数全局符号的GOT初始化规则与懒加载说明
GOT项的初始化时机与方式
- 非函数类全局符号(包括全局变量、全局常量等)对应的GOT表项,重定位类型通常为
R_X86_64_GLOB_DAT,这类重定位没有对应的PLT表作为中间跳板,处理逻辑和函数类的R_X86_64_JUMP_SLOT重定位完全不同。 - 初始化操作统一由动态链接器完成,触发时机分两种场景:
- 若符号所属的共享库是程序启动时默认加载的依赖库,重定位会在程序启动阶段、主程序入口代码执行前全部完成,动态链接器会直接将符号的实际虚拟地址写入对应GOT表项。
- 若符号所属的共享库是运行时通过
dlopen动态加载的,重定位会在dlopen执行、加载该共享库的过程中完成。
是否支持懒加载
- 默认不支持懒加载,核心原因是变量类符号的访问没有统一的触发入口:函数的所有调用都会走PLT表的统一入口,因此可以在首次调用时插入重定位逻辑实现懒加载;但变量的访问是直接基于地址的操作,包括读取、写入、取地址等,没有统一的中间层可以插入重定位触发逻辑,无法做到首次访问时才解析地址。
- 特殊场景下可以间接实现类懒加载效果:如果将全局变量的所有访问都封装到对外暴露的get/set接口函数中,外部代码只能通过这些函数操作变量,那么可以利用函数PLT的懒加载特性,在首次调用get/set函数时再完成变量地址的解析,但这本质是函数的懒加载,并非变量本身的GOT支持懒加载。
内容的提问来源于stack exchange,提问作者Siam Habib
相关产品推荐
相关产品推荐

