linux下共享库的注意点之-fpic
在编译共享库必须加上-fpic。这是为什么呢?
首先看一个简单的例子:
#include <stdio.h> int fun1()
{
printf("fun1\n");
}
先不加-fpic的情况下生成库,反汇编查看fun1的机器码
0000044c <fun1>:
44c: push %ebp
44d: e5 mov %esp,%ebp
44f: ec sub $0x18,%esp
: c7 b2 movl $0x4b2,(%esp)
: e8 fc ff ff ff call 45a <fun1+0xe>
45e: c9 leave
45f: c3 ret
可以看出调用printf的位置是那个唯一的一个call,并不是跳转到plt表,有关plt表的内容可以查看我前面的博文。也就是说在该库被加载时需要修改代码段来达到重定位的效果。那么每一个加载这个共享库的程序都要有这个库的一份拷贝,这样实际上就没有达到共享库的效果。
看下运行时的机器码
0xb771d44c <+>: push %ebp
0xb771d44d <+>: e5 mov %esp,%ebp
0xb771d44f <+>: ec sub $0x18,%esp
0xb771d452 <+>: c7 b2 d4 b7 movl $0xb771d4b2,(%esp)
0xb771d459 <+>: e8 b2 ea ff call 0xb75c86a0 <puts>
0xb771d45e <+>: c9 leave
0xb771d45f <+>: c3 ret
显然代码段被修改了。
再看一下再加了-fpic的情况下生成的库,反汇编看下fun1的机器码
0000045c <fun1>:
45c: push %ebp
45d: e5 mov %esp,%ebp
45f: push %ebx
: ec sub $0x14,%esp
: e8 ef ff ff ff call <__i686.get_pc_thunk.bx>
: c3 8c 1b add $0x1b8c,%ebx
46e: 8d ee e4 ff ff lea -0x1b12(%ebx),%eax
: mov %eax,(%esp)
: e8 ff ff ff call <puts@plt>
47c: c4 add $0x14,%esp
47f: 5b pop %ebx
: 5d pop %ebp
: c3 ret
: nop
: nop
: nop
: nop
: nop
: nop
: nop
看过很多汇编代码的人知道printf有时候是puts,所以这段机器码中printf就对应第二个call,也就是跳转到plt表中去查找puts符号,那么这样就达到了共享库的效果,此时每一个需要该库的程序只是有一个plt表的拷贝,而代码段所有应用程序是共享的。
再看下运行时机器码
0xb773045c <+>: push %ebp
0xb773045d <+>: e5 mov %esp,%ebp
0xb773045f <+>: push %ebx
0xb7730460 <+>: ec sub $0x14,%esp
0xb7730463 <+>: e8 ef ff ff ff call 0xb7730457 <__i686.get_pc_thunk.bx>
0xb7730468 <+>: c3 8c 1b add $0x1b8c,%ebx
0xb773046e <+>: 8d ee e4 ff ff lea -0x1b12(%ebx),%eax
0xb7730474 <+>: mov %eax,(%esp)
0xb7730477 <+>: e8 ff ff ff call 0xb7730380 <puts@plt>
0xb773047c <+>: c4 add $0x14,%esp
0xb773047f <+>: 5b pop %ebx
0xb7730480 <+>: 5d pop %ebp
0xb7730481 <+>: c3 ret
显然是一致的。
所以,在编译共享库时是必须加上-fpic的选项的,否则共享库省下的仅仅是硬盘上的空间,而没有省下内存。
linux下共享库的注意点之-fpic的更多相关文章
- 转:linux下共享库的注意点之-fpic
转: http://www.cnblogs.com/leo0000/p/5691483.html linux下共享库的注意点之-fpic 在编译共享库必须加上-fpic.这是为什么呢? 首先看一个简单 ...
- Linux下共享库嵌套依赖问题 (转载)
转自:http://my.oschina.net/moooofly/blog/506466 问题场景: 动态库 librabbitmq_r.so 内部依赖动态库 libevent_core.so 和 ...
- Linux下的库操作工具-nm、ar、ldd、ldconfig和ld.so
Linux下的库操作工具-nm.ar.ldd.ldconfig和ld.so .nm [options] file 列出file中的所有符号 [option] -c 将符号转化为用户级的名字 -s 当用 ...
- linux下静态库和动态库一些东西
http://www.cnblogs.com/changefuture/archive/2011/12/22/2297460.html Linux 动态链接库和静态库示例 文件预览 文件目录树如下, ...
- 谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH
谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH 转载自:http://blog.chinaunix.net/xmlrpc.ph ...
- Linux下动态库生成和使用
Linux下动态库生成和使用 一.动态库的基本概念 1.动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序.动态链接库是目标文件的集合,目标文件在动态链接库中 ...
- Linux下静态库生成和使用
Linux下静态库生成和使用 一.静态库概念 1.库是预编译的目标文件(object files)的集合,它们可以被链接进程序.静态库以后缀为”.a”的特殊的存档(archive file)存储. ...
- 查看Linux下*.a库文件中文件、函数、变量
查看Linux下*.a库文件中文件.函数.变量等情况在Linux 下经常需要链接一些 *.a的库文件,那怎么查看这些*.a 中包 含哪些文件.函数.变量: 1. 查看文件:ar -t xxx.a 2. ...
- 深入理解LINUX下动态库链接器/加载器ld-linux.so.2
[ld-linux-x86-64.so.2] 最近在Linux 环境下开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境下 ld.so的文章了,google上搜 ...
随机推荐
- 浅谈Linux中的信号处理机制(三)
一晃眼,已经到9月底了,都来不及去感慨时间匆匆.最近常常会想明年的今天我将会在那里干着什么样的工作?对未来又是憧憬又是担忧,压力山大.无论如何现在还是踏踏实实的学习吧,能这样安安静静学习的日子也不多了 ...
- Hibernate核心技术简介
Hibernate核心技术简介 1.Hibernate映射文件开发 Hibernate映射文件就是项目中*.hbm.xml文件,其主要是完成各元素的配置,包括根元素.类元素.定义主键.设置主键 ...
- 深入理解C++对象模型
C++对象模型是比较重要的一个知识点,学习C++对象的内存模型,就可以明白C++中的多态原理.类的初始化顺序问题.类的大小问题等. 1 C++对象模型基础 1.1 C++对象中都有哪些东东 C++对象 ...
- IO(六)--- 编码和解码
编码: 把看得懂的字符变成看不懂码值这个过程我们称作为编码. 解码: 把码值查找对应的字符,我们把这个过程称作为解码. 注意: 以后编码与解码一般我们都使用统一的码表.否则非常容易出乱码. 常用码表: ...
- 编写、部署、应用JavaBean
编写javabean 编写javabean实质上就是编写一个java类.设计javabean类就是要设计这个javabean的属性和方法,类的方法的命名遵循以下规则: 1)如果成员变量的名字是xx ...
- LintCode-Longest Increasing Subsequence
Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return ...
- 跨域的另一种解决方案——CORS(Cross-Origin Resource Sharing)跨域资源共享
在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求.浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片 ...
- JavaScript类库---JQuery(一)
1.基础: Jquery类库定义了一个全局函数:JQuery(); 别名$.是JQuery在全局命名空间中定义的唯一两个变量.返回一个新创建的JQuery对象: 另:JQuery中定义的许多方法返回值 ...
- Ubuntu 14.04.1 建立 Android M, Android N 開發環境 與 問題
# Modify /etc/apt/sources.list# add below 3 lines to /etc/apt/sources.listdeb http://archive.ubuntu. ...
- C/C++的编译过程
预处理(Preprocess). 使用Preprocessor Directives将一些代码替换成另一些代码. 例如将include替换成它指向的文件包含的代码. 编译成目标文件(Compiatio ...