gcc编译参数-fPIC的一些问题
gcc编译参数-fPIC的一些问题
(2012-07-26 15:41:08)
标签: linux
compiler
gcc
-fpic
it
分类: NSN_BspDriver
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 can then be linked with other
objects to
form an executable. Not all
systems support this
option. For
predictable results, you must also specify the same
set of
options that were used to generate code (`-fpic', `-fPIC',
or model
suboptions) 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,,意思是从 GOT 表的 index 为 var1-offset
的地方处
指示的地址处装载一个值,即处的4个 byte 其实就是 var1
的地址。这个地址只有在运行的时候才知道,是由 dynamic-loader(ld-linux.so)
填进去的。
再比如 jump label
指令
non-PIC 的形势是:jump
printf ,意思是调用 printf。
PIC 的形式则是:jump,
意思是跳到 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 linked executable exceeds a machine-specific maximum
size, 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 and
RS/6000. The 386 has no such limit.)
-fPIC
If
supported for the target machine, emit position-independent code,
suitable for dynamic linking and avoiding any limit on the size of
the global offset table. This option makes a difference on the
m68k, PowerPC and SPARC. Position-independent code requires special
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的一些问题的更多相关文章
- 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 ...
- c语言的编译过程和GCC 编译参数
原文: http://www.cnblogs.com/zhangShanGui/p/4912135.html C语言的编译过程和GCC编译参数 C语言的编译一般有三个步骤: 预编译: gcc -E - ...
- Linux gcc编译参数
最近编译一份开源代码,一编译就直接报错.我看了下报错信息,有点诧异.这些信息,放平常顶多就是个warnning而已啊,他这里怎么变成了error呢?我看了下Makefile,发现编译参数多了个-Wer ...
- GCC中-fpic解惑(转载)
参考: 1.<3.18 Options for Code Generation Conventions>2.<Options for Linking>3.<GCC -fP ...
- linux中[gcc -shared -fPIC]的含义
linux在gcc编译时加上 -shared 参数时,目的是使源码编译成动态库 .so 文件: 而-fPIC的作用是 告知编译器 生成位置无关代码(编译产生的代码没有绝对位置,只有相对位置):从而可以 ...
- Linux共享对象之编译参数fPIC
最近在看Linux编程的基础知识,打算对一些比较有趣的知识做一些汇总备忘,本文围绕fPIC展开,学习参考见文末. 在Linux系统中,动态链接文件称为动态共享对象(DSO,Dynamic Shared ...
- C语言的编译过程和GCC编译参数
C语言的编译一般有三个步骤: 预编译: gcc -E -o a.e a.c 预编译a.c文件,生成的目标文件名为a.e 预编译就是将include包含的头文件内容替换到C文件中,同时删除代码中没用的注 ...
- gcc编译参数详解概述
gcc 编译器是经常使用的,可是,自己却没有针对它做过专门的研究,当遇到问题了,总结一下,算是对未来有个积累吧. 一 关于编译告警: 1 -w : 关闭所有警告,不建议使用 2 -W 开启素有gcc ...
- gcc编译参数详解一(-ffunction-sections -fdata-sections)
背景 有时我们的程序会定义一些暂时使用不上的功能和函数,虽然我们不使用这些功能和函数,但它们往往会浪费我们的ROM和RAM的空间.这在使用静态库时,体现的更为严重.有时,我们只使用了静态库仅有的几个功 ...
随机推荐
- 高性能 Windows Socket 组件 HP-Socket v2.3.1-beta-2 发布
HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP ...
- GJM : Unity3D - NetWork - Hight Level API ( HLAPI) [转载]
介绍在本系列教程中,我们将使用的网络高级API(HLAPI)来构建一个小型的多人网络案例.即使我们的例子很简单,但也会涵盖以下关键概念,这应该可以帮助大家使用HLAPI构建大型游戏项目. 在第一部分, ...
- css知多少(7)——盒子模型
1. 引言 从这一节开始,我们就进入本系列的第三部分——css呈现.本部分将描述css在页面的几种布局和呈现的特性.包括两类:文字.块. 第一类——文字.这部分相对比较简单一些,例如设置字号.字体.颜 ...
- MixItUp:超炫!基于 CSS3 & jQuery 的过滤和排序插件
MixItUp 是一款轻量,但功能强大的 jQuery 插件,提供了对分类和有序内容的美丽的动画过滤和排序功能.特别适合用于作品集网站,画廊,图片博客以及任何的分类或有序内容. 它是如何工作的? Mi ...
- HTML5 Maker – 在线轻松制作 HTML5 动画效果
HTML5 Maker 是一个在线动画制作工具,帮助你使用 HTML,CSS 和 JavaScript 创建动态,互动的内容.它非常容易使用,同时可以帮你实现非常好的效果.它可以制作跨浏览器的动画内容 ...
- jQuery的document ready与 onload事件——你真的思考过吗?
在进行实验和资料查询时,我遇到了几个关键问题: 1. window.onload到底是什么加载完触发? 2. body为什么会有onload事件? 3. 为什么是window.onload,而不是do ...
- js一些代码方法
概要 1.替换json对象中属性值(包括子对象) 2.兼容多个$库写法(zepto与jquery) 3.闭包保持变量的做法 详情 1.替换json对象中属性值(包括子对象) //替换json对象属性值 ...
- jQuery原型属性和方法总结
从大四下学期开始了解jquery源码相关的东西,在回校参加毕业典礼(准确的说是参加补考挂科太多)期间便开始借着<jQuery>内幕学习jquery源码,然后在博客园写笔记也已经两个月了,也 ...
- EXCEL经纬度转化
=LEFT(A1,FIND("°",A1)-1)+MID(A1,FIND("°",A1)+1,FIND(CHAR(39),A1)-1-FIND("°& ...
- Android 开源框架Universal-Image-Loader完全解析(三)---源代码解读
转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/39057201),请尊重他人的辛勤劳动成果,谢谢! 本篇文章 ...