当使用虚拟内存时,我很难理解对PIC可执行文件的需求。根据我收集到的信息,每个程序都被分配到页面表中的一个条目中,因此产生了这样的错觉:当分页机制处理可能的重定位、分页结果和on.So时,它有整个内存可供使用,如果任何程序有拥有所有可能的内存地址的错觉,为什么要使用PIC?
发布于 2019-05-19 03:24:07
我们不需要它,直到最后一两年,所有的Linux可执行文件都依赖于位置(而不是PIC)。见在x86-64 Linux中不再允许32位绝对地址?。
您仍然可以使用gcc -fno-pie -no-pie构建非饼式可执行文件,静态ELF可执行文件总是在链接时选择其加载地址的非饼类文件。通常默认将文本段的开始放在401000上。
位置无关的ELF可执行文件从黑客开始:一个带有入口点的ELF共享对象。但如今,这已被广泛使用,而且大多数Linux发行版都默认使用gcc。负载地址可以在运行时随机分配。
还请注意,许多OSes在将可执行文件或库加载到其首选地址以外的位置时支持运行时修复。
例如,Linux上的ELF共享对象可以包含64位绝对地址的重定位,因此在用gcc -fPIC为x86和x86-64编译的代码中,可以有传统的跳转表(代码指针数组)或静态初始化的指针数组(指向数据或函数)。
请注意,gcc -fPIC还支持符号插入,因此函数不能直接访问全局变量;它们必须从GOT加载地址,除非符号具有“隐藏”ELF可见性。(当然,如果你把它变成static而不是全局的话)。
请参阅https://www.macieira.org/blog/2012/01/sorry-state-of-dynamic-libraries-on-linux/
(该博客中提出的一些想法已经实现,例如GCC支持-fno-plt。)
使用-fpie实现位置独立的实际成本非常小。但在OSes上仍然不是零,因为位置相关的可执行文件保证加载在虚拟地址空间的低32位(例如Linux)中,因此您可以利用5字节mov r32, imm32的32位绝对地址,而不是7字节的RIP相对LEA将静态地址放入寄存器,或者[array + reg]作为寻址模式的一部分以disp32置换中的地址索引静态数组。
发布于 2019-05-18 22:40:32
两个主要原因:
https://stackoverflow.com/questions/56203344
复制相似问题