在编译共享库必须加上-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的更多相关文章

  1. 转:linux下共享库的注意点之-fpic

    转: http://www.cnblogs.com/leo0000/p/5691483.html linux下共享库的注意点之-fpic 在编译共享库必须加上-fpic.这是为什么呢? 首先看一个简单 ...

  2. Linux下共享库嵌套依赖问题 (转载)

    转自:http://my.oschina.net/moooofly/blog/506466 问题场景: 动态库 librabbitmq_r.so 内部依赖动态库 libevent_core.so 和 ...

  3. Linux下的库操作工具-nm、ar、ldd、ldconfig和ld.so

    Linux下的库操作工具-nm.ar.ldd.ldconfig和ld.so .nm [options] file 列出file中的所有符号 [option] -c 将符号转化为用户级的名字 -s 当用 ...

  4. linux下静态库和动态库一些东西

    http://www.cnblogs.com/changefuture/archive/2011/12/22/2297460.html Linux  动态链接库和静态库示例 文件预览 文件目录树如下, ...

  5. 谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH

    谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH  PKG_CONFIG_PATH 转载自:http://blog.chinaunix.net/xmlrpc.ph ...

  6. Linux下动态库生成和使用

    Linux下动态库生成和使用 一.动态库的基本概念 1.动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序.动态链接库是目标文件的集合,目标文件在动态链接库中 ...

  7. Linux下静态库生成和使用

    Linux下静态库生成和使用 一.静态库概念 1.库是预编译的目标文件(object  files)的集合,它们可以被链接进程序.静态库以后缀为”.a”的特殊的存档(archive file)存储. ...

  8. 查看Linux下*.a库文件中文件、函数、变量

    查看Linux下*.a库文件中文件.函数.变量等情况在Linux 下经常需要链接一些 *.a的库文件,那怎么查看这些*.a 中包 含哪些文件.函数.变量: 1. 查看文件:ar -t xxx.a 2. ...

  9. 深入理解LINUX下动态库链接器/加载器ld-linux.so.2

    [ld-linux-x86-64.so.2] 最近在Linux 环境下开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境下 ld.so的文章了,google上搜 ...

随机推荐

  1. http 状态码含义

    HTTP状态码被分为五大类, 目前我们使用的HTTP协议版本是1.1, 支持以下的状态码.随着协议的发展,HTTP规范中会定义更多的状态码. 小技巧: 假如你看到一个状态码518, 你并不知道具体51 ...

  2. 【2016-11-2】【坚持学习】【Day17】【微软 推出的SQLHelper】

    从网络上找到 微软原版本的SQLHelper,很多行代码.认真看了,学习了.  代码:  using System; using System.Data; using System.Xml; usin ...

  3. 苹果iOS强制HTTPS迫在眉睫,距离2017年只剩1天,准备好了么?

    其实不久前苹果就发了通告,要求ios上的应用全部以HTTPS来进行接口调用以及数据访问,这样做是为了数据安全,一方面为了自己,另一方面也是对应用的要求更加严格,这么做很好,也加强了市场app的规范,虽 ...

  4. Django博客功能实现—文章评论的显示

    功能:在打开文章之后,能在文章下面是显示文章的评论,有父级评论.思路:在文章详情的视图里面,获取这个文章的全部评论,得到显示列表,然后用模板显示出来.步骤:一,在views.py的文章详情中获取评论: ...

  5. Vector3.forward

    这里我要说的就是Vector3.forward ,它等价与 new Vector3(0,0,1):它并不是一个坐标,它是一个标准向量,方向是沿着Z轴向前.这样平移一次的距离就是1米, 如果 Vecto ...

  6. java内部类

    1.内部类 2.内部类的名字不会单独存在,根据外部类名的存在而存在.内部类的名字可以和外部其他类的名字一样. 3.这个this.num打印的是inner类里面的num 4.在内部类访问外部类成员变量方 ...

  7. Linux 进程间通讯详解七

    上图的一台主机服务器架构的重大缺陷是容易死锁 因为客户端,服务器都往同一消息队列中发送接收消息,假设消息队列已经满了,此时客户端无法向队列中发送消息,阻塞了,而服务器接收完一条消息后,想向消息队列发送 ...

  8. java并发编程学习:如何等待多个线程执行完成后再继续后续处理(synchronized、join、FutureTask、CyclicBarrier)

    多线程应用中,经常会遇到这种场景:后面的处理,依赖前面的N个线程的处理结果,必须等前面的线程执行完毕后,后面的代码才允许执行. 在我不知道CyclicBarrier之前,最容易想到的就是放置一个公用的 ...

  9. 详解CSS中:nth-child的用法

    前端的哥们想必都接触过css中一个神奇的玩意,可以轻松选取你想要的标签并给与修改添加样式,是不是很给力,它就是“:nth-child”. 下面我将用几个典型的实例来给大家讲解:nth-child的实际 ...

  10. Javascript最简单的把html字符串编码的方法

    html字符串是指’<div id=”a”>aklsdjfklsjdfl</div>’这样的带html特殊符号的字符串,我们通常要对他进行处理再输出以免输出成了真正的html元 ...