ppc_85xx-gcc -shared -fPIC liberr.c -o liberr.so

-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 a shared object which canthen be linked with other
     objects to form an executable.  Not all systems support this
     option.  For predictable results, you must also specify thesame
     set of options that were used togenerate code (`-fpic', `-fPIC',
     or model suboptions) when youspecify 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 的形势是:jump printf ,意思是调用printf。
PIC 的形式则是:jump printf-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 和动态链接技术是计算机发展史上非常重要的一个里程碑。

gcc manul上面有说
-fpic        If the GOT size for the linkedexecutable exceeds a machine-specific maximum size, you get an error messagefrom the linker indicating that -fpic does not work; in that case, recompilewith -fPIC instead. (These maximums are 8k on the SPARC and 32k on the m68k andRS/6000. The 386 has no such limit.)

-fPIC       If supported for the targetmachine, emit position-independent code, suitable for dynamic linking andavoiding any limit on the size of the global offset table. This option makes adifference on the m68k, PowerPC and SPARC. Position-independent code requiresspecial support, and therefore works only on certain machines.

关键在于GOT全局偏移量表里面的跳转项大小。
intel处理器应该是统一4字节,没有问题。
powerpc上由于汇编码或者机器码的特殊要求,所以跳转项分为短、长两种。

-fpic为了节约内存,在GOT里面预留了“短”长度。
而-fPIC则采用了更大的跳转项。

(原文来自: http://blog.sina.com.cn/s/blog_54f82cc201011op1.html)

gcc 编译参数 -fPIC 的详解和一些问题相关推荐

  1. STM32CubeMX GCC工程Makefile内容详解

    STM32CubeMX GCC工程Makefile内容详解 基础介绍 因为项目原因,需要对编译系统进行一些比较复杂的使用,但是我对于编译系统这一块并不是非常精通了解,所以需要进行一下学习.正巧,众所周 ...

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

    -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置 ...

  3. GCC 命令选项使用详解

    GCC 命令行详解[转帖] 1.gcc包含的c/c++编译器 gcc.cc.c++.g++ gcc和cc是一样的,c++和g++是一样的,一般c程序就用gcc编译,c++程序就用g++编译 2.gcc ...

  4. GCC常用选项使用详解

    通常所说的GCC是GUN Compiler Collection的简称,除了编译程序之外,它还含其他相关工具,所以它能把易于人类使用的高级语言编写的源代码构建成计算机能够直接执行的二进制代码.GCC是 ...

  5. gcc 编译参数 -fPIC 作用

    在生成动态库时,常常习惯性的加上 fPIC 选项,fPIC 有什么作用和意义,加不加有什么区别,这里做下小结. fPIC 的全称是 Position Independent Code, 用于生成位置无 ...

  6. gcc编译器命令使用详解

    1.gcc包含的c/c++编译器 gcc,cc,c++,g++,gcc和cc是一样的,c++和g++是一样的,(没有看太明白前面这半句是什 么意思:))一般c程序就用gcc编译,c++程序就用g++编 ...

  7. php怎么配置configure,PHP编译参数configure配置详解(持续更新中)

    编译参数-使用 ./configure -h 在源代码目录中,该命令可以查看所有编译参数以及对应的英文解释 编译参数-说明 --prefix=/opt/php //指定 php 安装目录 --with ...

  8. php7 configure 参数,PHP编译参数configure配置详解

    编译参数-使用 ./configure -h 在源代码目录中,该命令可以查看所有编译参数以及对应的英文解释 编译参数-说明 --prefix=/opt/php //指定 php 安装目录 --with ...

  9. linux下gcc的编译过程详解

    Linux系统下的Gcc(GNU C Compiler)是GNU推出的功能强大.性能优越的多平台编译器,是GNU的代表作品之一.gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一 ...

最新文章

  1. Windows和Linux的编译理解
  2. 史上最全排序算法总结!建议收藏
  3. 22、Power Query-文本字符的精确提取
  4. mongodb系列01--基础篇
  5. VISTA三步共享文件夹
  6. android通过点击播放视频,Android通过MediaPlayer实现播放视频实例
  7. 自学python能干什么-普通人学Python能干什么?老男孩Python入门
  8. 【2(2N+1)魔方阵 】
  9. linux IPC socket(2)
  10. php中常见的错误类型有,php中的错误类型有哪些
  11. 给大家分享10个值得关注的C语言开源项目
  12. 7个免费的服务器监控工具
  13. 简易ElementUi+Vue模板
  14. python快速搭建服务器方法
  15. python以写模式打开的文件无法进读操作_以写模式打开的文件无法进行读操作。...
  16. 将Flutter添加到现有应用——过程中遇到的问题
  17. 英文写作盲点-less than 和 fewer than 、only
  18. [转]计算机经典书籍
  19. 高斯消去法解线性方程组C++实现
  20. R语言之循环(解决老虎机钻石匹配所有符号问题)

热门文章

  1. 适合中小企业的9大项目管理系统
  2. linux程序提示killed的原因
  3. 利用Python爬虫获取招聘网站职位信息
  4. Linux环境下安装部署redis
  5. nginx实现路由转发
  6. Python自动化测试系列[v1.0.0][Win32模拟键盘]
  7. 详解spring用到的九种设计模式
  8. 数据结构排序-7-1 统计工龄 (20 分)
  9. C++:应用有限差分法求解 稳平流扩散方程 v*ux-k*uxx=0 in 一个空间维度,具有恒定的速度 v 和扩散系数 k(附完整源码)
  10. [Unity 学习] Unity 入门学习及第一个游戏