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 的问题相关推荐

  1. linux下生成静态库和动态库

    linux下生成静态库和动态库 一.动态库.静态库简介 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常.本质上 ...

  2. 在linux下编写动态链接库的步骤: g++ -lc

    引用自http://blog.csdn.net/lwhsyit/article/details/2828306 类似Windows系统中的动态链接库,Linux中也有相应的共享库用以支持代码的复用.W ...

  3. linux下生成key

    linux下生成key 使用public/private key让putty(ssh)自动登录(以及linux上使用密钥做ssh自动登陆)  方法一:使用puttygen.exe  第一步:生成密匙  ...

  4. linux iphone文件,在linux下生成iphone所需要的视频和音频文件的方法总结

    在linux下生成iphone所需要的视频和音频文件的方法总结 (2011-05-07 09:53:18) 标签: linux iphone mencoder ffmpeg mplayer 一.生成可 ...

  5. linux下生成uuid

    linux下生成uuid [root@wz ~]# uuidgen | sed 's/-//g' 0fae9d2da50d4b65beba98260409f905 [root@wz ~]# cat / ...

  6. linux rsa密钥生成工具,linux下生成rsa密钥的方法

    首先生成密钥,用命令ssh-keygen –t rsa 运行后可以一直空格,生成密钥,id_rsa和id_rsa.pub文件 ,默认放在/root/.ssh/下,.ssh文件是隐藏的,要显示隐藏文件才 ...

  7. C++(Qt)软件调试---linux下生成/调试Core文件(3)

    #软件调试 C++(Qt)软件调试-linux下生成/调试Core文件(3) 文章目录 C++(Qt)软件调试---linux下生成/调试Core文件(3) 前言 1.C++生成Core和使用GDB调 ...

  8. Linux下生成HTTPS证书申请与颁发方法

    Linux下生成HTTPS证书申请与颁发方法: (1)生成HTTPS证书,可以使用openssl生成服务器RSA密钥及证书,生成的命令如下: openssl genrsa -des3 -out ser ...

  9. C++文件如何在linux下生成动态库So,以及如何使用这个动态库

    引用:http://blog.csdn.net/xuguang121/article/details/7457565 不同组件之间,如何提供一个动态库给其他Team使用,这样使用者也不需要关心和维护你 ...

最新文章

  1. zabbix 监控 elasticsearch
  2. js 正则或_ES6之正则扩展
  3. 织梦后台添加友链,前台不显示|修改友情链接的显示行数
  4. 用户与硬件之间的接口
  5. Java中length,length(),size()的区别
  6. 漫话:如何给女朋友解释华为鸿蒙OS是怎样实现跨平台的?
  7. [Python] L1-038. 新世界 团体程序设计天梯赛GPLT
  8. 美团猫眼电影Android模块化实战总结
  9. elasticsearch 数据类型_ElasticSearch学习笔记
  10. 【社交分享SDK】ShareSDK for Android 2.5.9已经公布
  11. 电脑博主fps测试软件,APP性能测试—帧率
  12. 配电网自动化课程复习总结
  13. SpringCloud-SpringCloud Bus服务总线的介绍(Day9)
  14. 【吴恩达】机器学习第16章异常检测以及ex8部分编程练习
  15. 详解百度大脑EdgeBoard出色的视频处理技术
  16. 【FPGA学习笔记】VHDL语言(五)语言风格描述:行为描述,数据流描述,结构化描述
  17. unity build报错Type has an extra field of type in the and thus can‘t be serialized error
  18. 【ArcGIS风暴】ArcGIS标注和注记的区别及用法案例详解
  19. Cadence Allegro 巧用直接打印功能得到PDF图纸图文教程及视频演示
  20. 自定义UI 简易图文混排

热门文章

  1. MOSS数据库服务器迁移步骤
  2. leetcode 1438. 绝对差不超过限制的最长连续子数组(滑动窗口+treemap)
  3. leetcode 127. 单词接龙(bfs)
  4. leetcode1046. 最后一块石头的重量(堆)
  5. vsc 搜索特定代码_特定问题的通用解决方案:何时编写代码以及何时编写代码...
  6. 客户行为模型 r语言建模_客户行为建模:汇总统计的问题
  7. 第一名数据科学工作冠状病毒医生
  8. js根据毫米/厘米算像素px
  9. Django 模型与 Mysql 数据类型对应
  10. 简单的方式优化mysql