fPIC作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),

  则产生的代码中,没有绝对地址,所有使用相对地址。故而代码能够被载入器载入到内存的随意

  位置,都能够正确的运行。这正是共享库所要求的,共享库被载入时。在内存的位置不是固定的。

gcc -shared -fPIC -o 1.so 1.c
这里有一个-fPIC參数
PIC就是position independent code
PIC使.so文件的代码段变为真正意义上的共享
假设不加-fPIC,则载入.so文件的代码段时,代码段引用的数据对象须要重定位,重定位会改动代码段的内容,这就造成每一个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每一个copy都不一样,取决于这个.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'

    Produce ashared object which can then be linked with other

    objects toform an executable.  Not allsystems support this

    option.  Forpredictable results, you must also specify the same

    set ofoptions that were used to generate code (`-fpic', `-fPIC',

    or modelsuboptions) when you specify this option.(1)





-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      If the GOTsize for the linked executable exceeds a machine-specific maximumsize, you get an error message from the linker indicating that-fpic does not work; in that case, recompile
with -fPIC instead.(These maximums are 8k on the SPARC and 32k on the m68k andRS/6000. The 386 has no such limit.)



-fPIC      Ifsupported for the target machine, emit position-independent code,suitable for dynamic linking and avoiding any limit on the size ofthe global offset table. This option makes a difference
on them68k, PowerPC and SPARC. Position-independent code requires specialsupport, and therefore works only on certainmachines.



关键在于GOT全局偏移量表里面的跳转项大小。

intel处理器应该是统一4字节,没有问题。

powerpc上因为汇编码或者机器码的特殊要求,所以跳转项分为短、长两种。

-fpic为了节约内存,在GOT里面预留了“短”长度。

而-fPIC则採用了更大的跳转项。

ppc_85xx-gcc -shared -fPIC liberr.c -o liberr.so的更多相关文章

  1. linux中[gcc -shared -fPIC]的含义

    linux在gcc编译时加上 -shared 参数时,目的是使源码编译成动态库 .so 文件: 而-fPIC的作用是 告知编译器 生成位置无关代码(编译产生的代码没有绝对位置,只有相对位置):从而可以 ...

  2. gcc编译参数-fPIC问题 `a local symbol' can not be used when making a shared object;

    gcc -shared -o hack.so hack.c/usr/bin/ld: /tmp/ccUZREwA.o: relocation R_X86_64_32 against `a local s ...

  3. gcc编译参数-fPIC的一些问题

    gcc编译参数-fPIC的一些问题 (2012-07-26 15:41:08) 转载▼ 标签: linux compiler gcc -fpic it 分类: NSN_BspDriver ppc_85 ...

  4. -shared -fPIC

    gcc -shared -fPIC -o 1.so 1.c   这里有一个-fPIC参数 PIC就是position independent code PIC使.so文件的代码段变为真正意义上的共享

  5. GCC中-fpic解惑(转载)

    参考: 1.<3.18 Options for Code Generation Conventions>2.<Options for Linking>3.<GCC -fP ...

  6. gcc shared object

    介绍一个生成动态链接库*.so的例子: 首先新建1个头文件test.h: #include <stdio.h> void first(); void second(); void thir ...

  7. Linux编译工具:gcc入门

    1. 什么是gcc gcc的全称是GNU Compiler Collection,它是一个能够编译多种语言的编译器.最开始gcc是作为C语言的编译器(GNU C Compiler),现在除了c语言,还 ...

  8. Linux下Gcc生成和使用静态库和动态库详解(转)

    一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...

  9. linux下的gcc编译器

    1. 编译单个文件成可执行文件 gcc hello.c 生成默认的可执行文件a.out 2. 编译单个文件为指定名字的可执行文件,使用-o选项指定文件名字 gcc -o test main.c 生成文 ...

随机推荐

  1. 结对项目--黄金点游戏(邓乐&曾亮)

    #include<stdio.h> #include<stdlib.h> #include<Windows.h> int result[100][1000000]; ...

  2. PHP自定义函数及内部函数考察点

    变量的作用域和静态变量 变量的作用域 变量的作用域也称变量的范围,变量的范围即它定义的上下文背景(也是它的生效范围).大部分的PHP变量只有一个单独的范围.这个单独的范围跨度同样包含了include和 ...

  3. nutz配置druid监控

    druid 提供了一个web端的监控页面, 搭建起来不算麻烦, 建议添加. 打开web.xml, 在nutz的filter之前, 加入Web监控的配置 <filter> <filte ...

  4. Laravel Mix编译前端资源

    目前项目是使用的vue+laravel来写的,其中laravel和vue分别放了一个目录,但是这样有个问题,那就是vue需要经常更新,不然运行项目会经常出现各种问题,这里就看了看laravel的文档, ...

  5. 浅谈JS之text/javascript和application/javascript

    问题描述: JS在IE8以下浏览器运行异常 代码: <script>标签是这样子写的: <script type="application/javascript" ...

  6. 题解 洛谷P1903/BZOJ2120【[国家集训队]数颜色 / 维护队列】

    对于不会树套树.主席树的本蒟蒻,还是老老实实的用莫队做吧.... 其实这题跟普通莫队差不了多远,无非就是有了一个时间,当我们按正常流程排完序后,按照基本的莫队来,做莫队时每次循环对于这一次操作,我们在 ...

  7. python 3 廖雪峰博客笔记(二) python解释器

    python 解释器用于理解 python代码,存在多种python解释器 CPython 官方版本python解释器,用C语言开发,使用最广泛 IPython 基于CPython,在交互方式上有所增 ...

  8. [Luogu] P4910 帕秋莉的手环

    题目背景 帕秋莉是蕾米莉亚很早结识的朋友,现在住在红魔馆地下的大图书馆里.不仅擅长许多魔法,还每天都会开发出新的魔法.只是身体比较弱,因为哮喘,会在咏唱符卡时遇到麻烦. 她所用的属性魔法,主要是生命和 ...

  9. Zabbix微信告警

    Zabbix微信告警 摘要 Zabbix可以通过多种方式把告警信息发送到指定人,常用的有邮件,短信报警方式,但是越来越多的企业开始使用zabbix结合微信作为主要的告警方式,这样可以及时有效的把告警信 ...

  10. MySQL-----增

    增 **创建用户** create user 'alex'@'192.168.1.1' identified by '123123'; create user 'alex'@'192.168.1.%' ...