位置无关代码:编译时有什么区别?

时间:2014-10-20 10:00:02

标签: dynamic-linking linker compiler-construction dynamic-loading

阅读libtool docs我想知道为什么我们需要告诉编译器生成与位置无关的代码。毕竟,生成的目标文件还不知道它将链接到的地址空间中的哪个位置,因此一个单个目标文件应始终独立于位置,不应该吗?而且,为了生成共享对象库,这不仅仅意味着将所有目标文件一起烘焙,这些目标文件构成了lib并且可能设置所有相对引用,这些引用已经成为烘焙一起的lib的“实习生”,同时保留所有其他引用(绝对和相对)稍后由链接器加载器填写?为什么这也是编译器的问题?

1 个答案:

答案 0 :(得分:2)

  

我想知道为什么我们需要告诉编译器生成与位置无关的代码。毕竟,生成的目标文件还不知道它将链接到的地址空间中的哪个位置,因此一个单个目标文件应该是位置无关的在所有情况下,不应该吗?

当您告诉编译器生成位置无关代码(PIC)时,它完全不同于生成非PIC的编译器,主要是关于功能和数据访问。使用PIC的原因是为了避免缓冲区溢出或代码覆盖,当有人向您的应用程序地址空间输入几行代码时,这些代码覆盖大多是用C / C ++等低级语言编写的,因为默认情况下C / C ++不会检查为了界限。

它使用间接方法借助名为" Global Offset Table"(GOT)的表来访问数据和函数。此GOT通常位于特殊机器寄存器中。使用此表的主要好处是代码的生成将独立于实际的加载地址。在运行时,它将根据所需库的当前加载地址更新表中的偏移量。

当编译器生成一个目标文件(PIC中的.lo)时,它会在没有修改的情况下以随机地址加载对象,即使某个对象的加载地址对某些ABI是固定的,它也会在随机地址加载每个所需的库。生成的目标文件并不知道它将链接到的地址空间中的位置,这正是PIC想要这样做的,即没有修复链接地址,如果攻击者发现该地址,可能会危及应用程序的安全性

  

而且,为了生成共享对象库,不仅仅意味着将所有目标文件烘焙在一起,这些目标文件构成了lib并且可能设置了所有已成为"实习生"到烘焙的lib,同时留下所有其他引用(绝对和相对)以后由链接器加载器填写?为什么这也是编译器的问题?

对于共享库,libtool在看到PIC'标志在预处理器中设置,它自动为共享库构建目标文件。他们没有成为"实习生"因为共享库可以位于进程内存布局中的任何位置,并且可以通过构建时设置的某些标志间接访问它们。

维基:http://en.wikipedia.org/wiki/Position-independent_code

Gentoo:http://wiki.gentoo.org/wiki/Project:Hardened