PIC和PIE
Posted Spider-spiders
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PIC和PIE相关的知识,希望对你有一定的参考价值。
PIC指的是位置无关代码,用于生成位置无关的共享库,所谓位置无关,指的是共享库的代码断是只读的,存放在代码段,多个进程可同时公用这份代码段而不需要拷贝副本。库中的变量(全局变量和静态变量)通过GOT表访问,而库中的函数,通过PLT->GOT->函数位置进行访问。Linux下编译共享库时,必须加上-fPIC参数,否则在链接时会有错误提示(有资料说AMD64的机器才会出现这种错误,但我在Inter的机器上也出现了)。这篇资料不错:http://ixuan.org/2015/01/%E5%8A%A8%E6%80%81%E5%BA%93%E4%B8%AD%E7%9A%84%E4%BD%8D%E7%BD%AE%E6%97%A0%E5%85%B3%E4%BB%A3%E7%A0%81-position-independent-code-pic-in-shared-libraries/
PIE指的是位置无关的可执行程序,用于生成位置无关的可执行程序,所谓位置无关的可执行程序,指的是,可执行程序的代码指令集可以被加载到任意位置,进程通过相对地址获取指令操作和数据,如果不是位置无关的可执行程序,则该可执行程序的代码指令集必须放到特定的位置才可运行进程。(可执行程序和进程的区别,简单来说,可执行程序就是一堆指令集,而进程是系统分配资源之后利用该指令集进行的一次工作)。在Linux下,使用-fPIE时需要注意:
1.如果-fPIE和-shared同时使用,生成的结果即可作为动态库,也可作为可执行程序:
1)作为动态库时,必须满足:不存在main函数且模块中不存在对外输出的全局变量。这是因为-fPIE默认总是将生成的位置无关代码看作是属于程序本身(http://www.ibm.com/developerworks/cn/linux/l-cn-sdlstatic/),如果有一个对外输出的变量且结果又是作为共享的动态库,这个时候对外输出的变量就会和fPIC的作用产生矛盾,因此,这种情况下,不允许有对外可见的变量。这种情况下,编译生成的可执行程序可作为动态库被调用。
2)如果是作为可执行程序,必须有main函数,此时模块中可以有全局变量,是一个可执行程序。
2.如果-fPIE不和-shared一起使用,那么生成的结果只能作为可执行程序,其中必须包含main函数。
PIC生成的共享库是会被其它程序调用的,所以可以在调用时对GOT中的变量地址重定位来确定全局变量地址。
而PIE本身的目的不是生成共享库,而是生成位置无关的可执行程序,所以在连接时所有的变量都已经确定好了,包括全局的对外可见变量也默认视为程序内部变量。因此,如果用PIE生成共享库,一旦存在全局对外可见的变量,一方面,作为共享库,该变量地址被期望是可重定位的,另一方面,作为PIE,该变量地址被期望是固定的,就会产生矛盾。
根本原因在于变量地址是否应该可以被重定位。
原文链接:https://www.cnblogs.com/yanqi0124/p/4816343.html
以上是关于PIC和PIE的主要内容,如果未能解决你的问题,请参考以下文章