4

背景:如果一个可执行文件有一个在共享对象中定义的外部数据引用,编译器将使用复制重定位并在其.bss 部分中放置一个副本。复制搬迁在本站有详细说明:http: //www.shrubbery.net/solaris9ab/SUNWdev/LLM/p22.html#CHAPTER4-84604

但是,我的问题是:

是否可以通过 GOT 来实现,就像共享对象中的外部数据引用一样?可执行文件可以通过它的 GOT 入口间接访问这个外部代码,并且这个 GOT 入口可以在运行时填充这个符号的真实地址。我不知道为什么 GCC 不这样实现它。副本重定位的好处是什么?

4

2 回答 2

3

是否可以通过 GOT 来实现,就像共享对象中的外部数据引用一样?

是的。为此,您需要构建与主可执行文件链接的代码-fPIC。由于这通常效率较低(额外间接),并且通常这样做,因此链接器必须进行复制重定位。

更多信息在这里

于 2014-11-11T15:44:35.510 回答
3

在像 C 和 C++ 这样的语言中,具有静态存储持续时间的对象的地址符合地址常量。这意味着从概念上讲,在语言级别上,它们被视为在编译时它们的值是“已知的”。

当然,当涉及到所讨论的问题时,实际情况并非如此。为了反驳编译器-链接器-加载器组合必须实现一种动态机制,该机制将提供完全支持地址常量的语言级概念。直观地说,基于 GOT 的机制,基于完整的运行时间接,将比基于加载时重定位的机制更远离该概念。

一方面,C 语言被设计为一种不需要动态初始化具有静态存储持续时间的对象的语言,即在概念上没有初始化启动代码,也没有与初始化顺序相关的问题。但在基于 GOT 的实现中,使用此类地址常量初始化全局变量将需要启动代码从 GOT 中提取实际值并将其放入变量中。同时,基于重定位的方法会产生一种这样的全局变量的完全错觉,即在没有任何启动代码的情况下以适当的值开始其生命。

如果您查看重定位机制提供的功能,您会注意到它们与地址常量的 C 规范同步。例如,最终值可能涉及添加一个固定偏移量,该偏移量旨在充当 C[]->运算符的加载器端实现,在 C 地址常量表达式中是允许的。

于 2014-11-11T16:05:43.863 回答