背景:
如果可执行文件具有在共享对象中定义的外部数据引用,则编译器将使用副本重定位并将副本放置在其 .bss 部分中。
复制重定位在此站点中有详细说明:
http://www.shrubbery.net/solaris9ab/SUNWdev/LLM/p22.html#CHAPTER4-84604
但是,我的问题是:
是否可以通过GOT来实现,就像共享对象中的外部数据引用一样?可执行文件可以通过它的 GOT 入口间接访问这个外部代码,并且这个 GOT 入口可以在运行时填充这个符号的真实地址。
我不知道为什么 GCC 没有像这样实现它。副本重定位的好处是什么?
最佳答案
在像 C 和 C++ 这样的语言中,具有静态存储持续时间的对象的地址被称为地址常量。这意味着从概念上讲,在语言级别,它们被视为在编译时它们的值是“已知的”。
当然,现实中的情况并非如此,就问题而言。为了解决编译器-链接器-加载器组合必须实现一种动态机制,该机制将提供完全支持地址常量的语言级概念。直观地说,基于完全运行时间接的基于 GOT 的机制与基于加载时重定位的机制相比,与该概念相距甚远。
一方面,C 语言被设计为一种不需要动态初始化具有静态存储持续时间的对象的语言,即概念上没有初始化启动代码,也没有与初始化顺序相关的问题。但是在基于 GOT 的实现中,使用这种地址常量初始化全局变量需要启动代码从 GOT 中提取实际值并将其放入变量中。同时,基于重定位的方法会产生这种全局变量的完整错觉,即在没有任何启动代码的情况下以正确的值开始其生命周期。
如果您查看重定位机制提供的功能,您会注意到它们与地址常量的 C 规范是同步的。例如。最终值可能涉及添加一个固定偏移量,它旨在充当 C []
和 ->
运算符的加载器端实现,在 C 地址常量表达式中是允许的。
关于gcc - 复制重定位的目的是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26863009/