Linux下生成动态链接库是否必须使用 -fPIC 的问题[转]
在 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公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2011-06/37268.htm
Linux下生成动态链接库是否必须使用 -fPIC 的问题[转]的更多相关文章
- linux下添加动态链接库路径、动态库加载等方法
linux下添加动态链接库路径的方法 2017年01月20日 10:08:17 阅读数:5596 Linux共享库路径配置 Linux下找不到共享库文件的典型现象为明明已经安装某个软包(如libn ...
- linux下生成core dump文件方法及设置
linux下生成core dump文件方法及设置 from:http://www.cppblog.com/kongque/archive/2011/03/07/141262.html core ...
- 1.Linux下生成密钥
1.Linux下生成密钥 ssh-keygen的命令手册,通过”man ssh-keygen“命令: 通过命令”ssh-keygen -t rsa“ 生成之后会在用户的根目录生成一个 “.ssh”的文 ...
- linux下查看动态链接库依赖关系的命令 x86: ldd *.so arm: arm-linux-readelf -d *.so 实际例子: 以项目中用到的库librtsp.so分析: lijun@ubuntu:~/workspace$ arm-hisiv100nptl-linux-ld -d librtsp.so arm-hisiv100nptl-linux-ld:
linux下查看动态链接库依赖关系的命令 x86:ldd *.so arm:arm-linux-readelf -d *.so 实际例子:以项目中用到的库librtsp.so分析:l ...
- Linux下编写动态链接库
下面通过一个例子来介绍如何生成一个动态库.这里有一个头文件:so_test.h,三个.c文件:test_a.c.test_b.c.test_c.c,我们将这几个文件编译成一个动态库:libtest.s ...
- 如何在 Linux 下调试动态链接库
大家都知道在 Linux 可以用 gdb 来调试应用程序,当然前提是用 gcc 编译程序时要加上 -g 参数.我这篇文章里将讨论一下用 gdb 来调试动态链接库的问题. 首先,假设我们准备这样的一个动 ...
- linux下的动态链接库管理
LD_LIBRARY_PATH Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径.(该路径在默认路径之前查找) 移植程序时的经常碰到需要使用一些特定的动 ...
- random and password 在Linux下生成crypt加密密码的方法,shell 生成指定范围随机数与随机字符串
openssl rand -hex n (n is number of characters) LANG=c < /dev/urandom tr -dc _A-Z-a-z-0-9 | head ...
- linux下查看动态链接库so文件的依赖的相关组建
我们很多c程序在windows下是以dll形式展现的,在linux则是以so 形式展现的. windows一般不会因为编译dll文件的编译器版本不同而出先dll文件不能执行. 但是linux下,不同版 ...
随机推荐
- Swift语法
Swift语法 标签(空格分隔): Swift 1.打印输出语句 println("Hello, Swift!") 注意每行代码后面无需添加分号作为结束 2.简单值 let---常 ...
- jQuery Mobile 1.1八大新特性介绍
随着HTML 5时代的来临,移动开发开始进入了一个新的时代,现在只需要懂得HTML5,配合一定的开发框架,就可以开发出十分漂亮的HTML5的移动应用.在众多的 移动HTML5开发框架中,比较著名的是j ...
- Spring 框架概述
◆简介 目的:解决企业应用开发的复杂性 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能 范围:任何Java应用 Spring 框架是一个分层架构,由 7 个定义良好的模块组成. ...
- HEAD
Branches are just pointers to commits Every branch is simply a named pointer to a commit. A special ...
- delphi 中字符串与16进制、10进制转换函数
//字符串转成16进制代码function strToHexStr(str:string):string;varc:char;ss:string;i:integer;beginwhile str& ...
- C#(WinForm)实现软件注册
转自:http://www.cnblogs.com/ynbt/archive/2011/11/02/2233470.html 源码如下:下载
- 让IE6IE7IE8支持CSS3属性的8种方法介绍
我们都知道,IE浏览器暂不支持CSS3的一些属性.国外的工程师们,不安于此现状,他们总是尽量使用一些手段使IE浏览器也能支持CSS3属性,我觉得这些都是很有意义,很有价值的工作,可以推动整个技术领域的 ...
- ajax实现md5加密
一个asp.net ajax例子,使用jquery,实现md5加密..NET 4.0,Visual Studio 2010以上.效果体验:http://tool.keleyi.com/t/md5.ht ...
- java中的类实现comparable接口 用于排序
import java.util.Arrays; public class SortApp { public static void main(String[] args) { Student[] s ...
- anible包模块管理
ansible使用包管理模块 一般使用的包管理模块的RPM,和YUM 参数 必填 默认 选择 说明 Conf_file No YUM的配置文件 Disable_dbg_check No No Yes/ ...