Linux下生成动态链接库是否必须使用 -fPIC 的问题
From: http://www.linuxidc.com/Linux/2011-06/37268.htm
在 Linux 下制作动态链接库,“标准” 的做法是编译成位置无关代码(Position Independent Code,PIC),然后链接成一个动态链接库。经常遇到的一个问题是 -fPIC 是不是必需,因为好像不加经常也能正常运行,只是创建 .so 的时候会有一个警告。
搜索、试验了一下,答案似乎是这样:
(1) 通常的建议是始终加上 -fPIC 生成位置无关代码;
(2) AMD64 下,必须使用位置无关代码,否则连接失败:
relocation R_X86_64_32S against `a local symbol' can not be used when making a shared object; recompile with -fPIC
(3) IA32 下,连接成功,但有警告:
warning: creating a DT_TEXTREL in object.
这样的 .so 文件可以完全正常工作。
可执行文件在链接时就知道每一行代码、每一个变量会被放到线性地址空间的什么位置,因此这些地址可以都作为常数写到代码里面。对动态库,这就不行了,这要等到加载时才知道。无非下面两种方法:
(1) 可重定位代码(relocatable code):Windows DLL 以及不使用 -fPIC 的 Linux SO。
生成动态库时假定它被加载在地址 0 处。加载时它会被加载到一个地址(base),这时要进行一次重定位(relocation),把代码、数据段中所有的地址加上这个 base 的值。这样代码运行时就能使用正确的地址了。
(2) 位置无关代码(position independent code):使用 -fPIC 的 Linux SO。
这样的代码本身就能被放到线性地址空间的任意位置,无需修改就能正确执行。通常的方法是获取指令指针(如 IA32 的 EIP 寄存器)的值,加上一个偏移得到全局变量/函数的地址。
PIC vs. relocatable:
(1) PIC 的缺点主要就是代码有可能长一些。例如 IA32,由于不能直接使用 [EIP+constant] 这样的寻址方式,甚至不能直接将 EIP 的值交给其他寄存器,要用到 GOT(global offset table)来定位全局变量和函数。这样导致代码的效率略低。
(2) PIC 的加载速度稍快,因为不需要做重定位。
(3) 多个进程引用同一个 PIC 动态库时,可以共用内存。这一个库在不同进程中的虚拟地址不同,但操作系统显然会把它们映射到同一块物理内存上。对于可重定位代码,则必须为每个库都在物理内存中复制一份副本,因为需要修改其中的地址。当然,主流现代操作系统都启用了分页内存机制,这使得重定位时可以使用 COW(copy on write)来节省内存(32 位 Windows 就是这样做的);然而,页面的粒度还是比较大的(例如 IA32 上是 4KiB),至少对于代码段来说能节省的相当有限。
注:对于 AMD64,由于 AMD64 实现了 [RIP+constant] 的寻址方式,第 (1) 点不成立。
这样,把动态库编译成 PIC 只有好处没有坏处,因而 Linux AMD64 要求用于生成动态库的目标文件必须使用 -fPIC 编译也合情合理了。
Linux下生成动态链接库是否必须使用 -fPIC 的问题相关推荐
- linux下生成静态库和动态库
linux下生成静态库和动态库 一.动态库.静态库简介 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常.本质上 ...
- 在linux下编写动态链接库的步骤: g++ -lc
引用自http://blog.csdn.net/lwhsyit/article/details/2828306 类似Windows系统中的动态链接库,Linux中也有相应的共享库用以支持代码的复用.W ...
- linux下生成key
linux下生成key 使用public/private key让putty(ssh)自动登录(以及linux上使用密钥做ssh自动登陆) 方法一:使用puttygen.exe 第一步:生成密匙 ...
- linux iphone文件,在linux下生成iphone所需要的视频和音频文件的方法总结
在linux下生成iphone所需要的视频和音频文件的方法总结 (2011-05-07 09:53:18) 标签: linux iphone mencoder ffmpeg mplayer 一.生成可 ...
- linux下生成uuid
linux下生成uuid [root@wz ~]# uuidgen | sed 's/-//g' 0fae9d2da50d4b65beba98260409f905 [root@wz ~]# cat / ...
- linux rsa密钥生成工具,linux下生成rsa密钥的方法
首先生成密钥,用命令ssh-keygen –t rsa 运行后可以一直空格,生成密钥,id_rsa和id_rsa.pub文件 ,默认放在/root/.ssh/下,.ssh文件是隐藏的,要显示隐藏文件才 ...
- C++(Qt)软件调试---linux下生成/调试Core文件(3)
#软件调试 C++(Qt)软件调试-linux下生成/调试Core文件(3) 文章目录 C++(Qt)软件调试---linux下生成/调试Core文件(3) 前言 1.C++生成Core和使用GDB调 ...
- Linux下生成HTTPS证书申请与颁发方法
Linux下生成HTTPS证书申请与颁发方法: (1)生成HTTPS证书,可以使用openssl生成服务器RSA密钥及证书,生成的命令如下: openssl genrsa -des3 -out ser ...
- C++文件如何在linux下生成动态库So,以及如何使用这个动态库
引用:http://blog.csdn.net/xuguang121/article/details/7457565 不同组件之间,如何提供一个动态库给其他Team使用,这样使用者也不需要关心和维护你 ...
最新文章
- zabbix 监控 elasticsearch
- js 正则或_ES6之正则扩展
- 织梦后台添加友链,前台不显示|修改友情链接的显示行数
- 用户与硬件之间的接口
- Java中length,length(),size()的区别
- 漫话:如何给女朋友解释华为鸿蒙OS是怎样实现跨平台的?
- [Python] L1-038. 新世界 团体程序设计天梯赛GPLT
- 美团猫眼电影Android模块化实战总结
- elasticsearch 数据类型_ElasticSearch学习笔记
- 【社交分享SDK】ShareSDK for Android 2.5.9已经公布
- 电脑博主fps测试软件,APP性能测试—帧率
- 配电网自动化课程复习总结
- SpringCloud-SpringCloud Bus服务总线的介绍(Day9)
- 【吴恩达】机器学习第16章异常检测以及ex8部分编程练习
- 详解百度大脑EdgeBoard出色的视频处理技术
- 【FPGA学习笔记】VHDL语言(五)语言风格描述:行为描述,数据流描述,结构化描述
- unity build报错Type has an extra field of type in the and thus can‘t be serialized error
- 【ArcGIS风暴】ArcGIS标注和注记的区别及用法案例详解
- Cadence Allegro 巧用直接打印功能得到PDF图纸图文教程及视频演示
- 自定义UI 简易图文混排
热门文章
- MOSS数据库服务器迁移步骤
- leetcode 1438. 绝对差不超过限制的最长连续子数组(滑动窗口+treemap)
- leetcode 127. 单词接龙(bfs)
- leetcode1046. 最后一块石头的重量(堆)
- vsc 搜索特定代码_特定问题的通用解决方案:何时编写代码以及何时编写代码...
- 客户行为模型 r语言建模_客户行为建模:汇总统计的问题
- 第一名数据科学工作冠状病毒医生
- js根据毫米/厘米算像素px
- Django 模型与 Mysql 数据类型对应
- 简单的方式优化mysql