【问题标题】:Position independent code: what is the difference at compile time?位置无关代码:编译时有什么区别?
【发布时间】:2014-10-20 10:00:01
【问题描述】:

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

【问题讨论】:

  • 可能更多关于 SO 的主题。这真的是 unix 特有的吗?

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


【解决方案1】:

我想知道为什么我们需要告诉编译器生成与位置无关的代码。毕竟,生成的目标文件还不知道它将链接到地址空间的哪个位置,所以一个目标文件应该是位置独立的任何时候,不应该吗?

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

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

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

此外,要生成共享对象库,这不只是意味着将构成该库的所有对象文件一起烘焙,并可能将所有已成为“实习生”的相对引用设置为烘焙在一起的库,同时离开稍后由链接器加载器填写的所有其他引用(绝对和相对)?为什么这也是编译器的一个问题?

在共享库的情况下,libtool 当看到预处理器中设置了“PIC”标志时,它会自动为共享库构建目标文件。它们还没有成为“实习生”,因为共享库可以位于进程内存布局中的任何位置,并且它们可以通过构建时设置的一些标志间接访问。

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

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

【讨论】:

  • 好吧,我想我现在知道了,我错过了共享库的要点:共享库愚蠢.so 可以出现在一个进程的地址 X 和另一个进程的地址 Y,对吗?
  • 实际上每个进程都有自己的虚拟地址空间,所以如果像傻瓜一样的共享库是用PIC构建的,那么它可以在进程虚拟地址空间内的任何地方。
  • 我们不应该说:它必须使用 PIC 构建,否则它可能会与实际尝试使用 lib 的进程中的代码发生冲突?
  • 是的,它应该按照 libtool 的建议使用 PIC 构建。尽管理论上你可以构建一个没有 PIC 的共享库。但是在系统中拥有共享库的全部目的是动态地使用共享库,因为事先程序员/编译器不知道所需/需要的共享库可以位于哪里,而这就是 PIC很有用,它提供了位置独立性。关于地址冲突:使用 PIC,可以在每个程序地址空间中加载相同的库代码,这样它就不会与内存的任何其他用途重叠。
猜你喜欢
  • 1970-01-01
  • 2011-03-31
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
  • 2023-02-05
  • 1970-01-01
  • 2018-07-11
  • 2021-08-29
相关资源
最近更新 更多