ppc_85xx-gcc -shared -fPIC liberr.c -o liberr.so
不加fPIC编译出来的so,是要再载入时依据载入到的位置再次重定位的.(由于它里面的代码并非位置无关代码)
假设被多个应用程序共同使用,那么它们必须每一个程序维护一份so的代码副本了.(由于so被每一个程序载入的位置都不同,显然这些重定位后的代码也不同,当然不能共享)
我们总是用fPIC来生成so,也从来不用fPIC来生成a.
fPIC与动态链接能够说基本没有关系,libc.so一样能够不用fPIC编译,仅仅是这种so必需要在载入到用户程序的地址空间时重定向全部表目.
因此,不用fPIC编译so并不总是不好.
假设你满足下面4个需求/条件:
1.该库可能须要常常更新
2.该库须要非常高的效率(尤其是有非常多全局量的使用时)
3.该库并不非常大.
4.该库基本不须要被多个应用程序共享
假设用没有加这个參数的编译后的共享库,也能够使用的话,可能是两个原因:
1:gcc默认开启-fPIC选项
2:loader使你的代码位置无关
从GCC来看。shared应该是包括fPIC选项的,但似乎不是所以系统都支持,所以最好显式加上fPIC选项。參见例如以下
`-shared'
-fPIC 的使用,会生成 PIC代码,.so 要求为 PIC。以达到动态链接的目的。否则,无法实现动态链接。
non-PIC 与 PIC代码的差别主要在于 access global data, jump label 的不同。
比方一条 access global data的指令。
non-PIC 的形势是:ld r3,var1
PIC 的形式则是:ld r3,var1-offset@GOT,意思是从 GOT 表的 index 为 var1-offset的地方处
指示的地址处装载一个值,即var1-offset@GOT处的4个 byte 事实上就是 var1的地址。这个地址仅仅有在执行的时候才知道,是由 dynamic-loader(ld-linux.so)填进去的。
再比方 jump label指令
non-PIC 的形势是:jumpprintf 。意思是调用 printf。
PIC 的形式则是:jumpprintf-offset@GOT,
意思是跳到 GOT 表的 index 为 printf-offset 的地方处指示的地址去运行,
这个地址处的代码摆放在 .plt section,
每一个外部函数相应一段这种代码,其功能是呼叫dynamic-loader(ld-linux.so)来查找函数的地址(本例中是 printf),然后将其地址写到 GOT 表的 index 为 printf-offset的地方,
同一时候运行这个函数。这样。第2次呼叫printf 的时候,就会直接跳到 printf 的地址,而不必再查找了。
GOT是 data section, 是一个 table, 除专用的几个 entry。每一个 entry的内容能够再运行的时候改动;
PLT是 text section, 是一段一段的 code,运行中不须要改动。
每一个 target 实现 PIC的机制不同,但大同小异。
比方 MIPS 没有 .plt, 而是叫 .stub,功能和 .plt一样。
可见,动态链接运行非常复杂。比静态链接运行时间长;可是,极大的节省了size。PIC 和动态链接技术是计算机发展史上非常重要的一个里程碑。
gccmanul上面有说
-fpic
-fPIC
关键在于GOT全局偏移量表里面的跳转项大小。
intel处理器应该是统一4字节,没有问题。
powerpc上因为汇编码或者机器码的特殊要求,所以跳转项分为短、长两种。
-fpic为了节约内存,在GOT里面预留了“短”长度。
而-fPIC则採用了更大的跳转项。
posted on 2017-05-21 08:55 cynchanpin 阅读(434) 评论(0) 编辑 收藏 举报