转: http://www.cnblogs.com/leo0000/p/5691483.html

linux下共享库的注意点之-fpic

在编译共享库必须加上-fpic。这是为什么呢?

首先看一个简单的例子:

#include <stdio.h>

int fun1()
{
printf("fun1\n");
}

先不加-fpic的情况下生成库,反汇编查看fun1的机器码

0000044c <fun1>:
44c: 55 push %ebp
44d: 89 e5 mov %esp,%ebp
44f: 83 ec 18 sub $0x18,%esp
452: c7 04 24 b2 04 00 00 movl $0x4b2,(%esp)
459: e8 fc ff ff ff call 45a <fun1+0xe>
45e: c9 leave
45f: c3 ret

可以看出调用printf的位置是那个唯一的一个call,并不是跳转到plt表,有关plt表的内容可以查看我前面的博文。也就是说在该库被加载时需要修改代码段来达到重定位的效果。那么每一个加载这个共享库的程序都要有这个库的一份拷贝,这样实际上就没有达到共享库的效果。

看下运行时的机器码

   0xb771d44c <+0>:     55      push   %ebp
0xb771d44d <+1>: 89 e5 mov %esp,%ebp
0xb771d44f <+3>: 83 ec 18 sub $0x18,%esp
0xb771d452 <+6>: c7 04 24 b2 d4 71 b7 movl $0xb771d4b2,(%esp)
0xb771d459 <+13>: e8 42 b2 ea ff call 0xb75c86a0 <puts>
0xb771d45e <+18>: c9 leave
0xb771d45f <+19>: c3 ret

显然代码段被修改了。

再看一下再加了-fpic的情况下生成的库,反汇编看下fun1的机器码

0000045c <fun1>:
45c: 55 push %ebp
45d: 89 e5 mov %esp,%ebp
45f: 53 push %ebx
460: 83 ec 14 sub $0x14,%esp
463: e8 ef ff ff ff call 457 <__i686.get_pc_thunk.bx>
468: 81 c3 8c 1b 00 00 add $0x1b8c,%ebx
46e: 8d 83 ee e4 ff ff lea -0x1b12(%ebx),%eax
474: 89 04 24 mov %eax,(%esp)
477: e8 04 ff ff ff call 380 <puts@plt>
47c: 83 c4 14 add $0x14,%esp
47f: 5b pop %ebx
480: 5d pop %ebp
481: c3 ret
482: 90 nop
483: 90 nop
484: 90 nop
485: 90 nop
486: 90 nop
487: 90 nop
488: 90 nop

看过很多汇编代码的人知道printf有时候是puts,所以这段机器码中printf就对应第二个call,也就是跳转到plt表中去查找puts符号,那么这样就达到了共享库的效果,此时每一个需要该库的程序只是有一个plt表的拷贝,而代码段所有应用程序是共享的。

再看下运行时机器码

   0xb773045c <+0>:     55      push   %ebp
0xb773045d <+1>: 89 e5 mov %esp,%ebp
0xb773045f <+3>: 53 push %ebx
0xb7730460 <+4>: 83 ec 14 sub $0x14,%esp
0xb7730463 <+7>: e8 ef ff ff ff call 0xb7730457 <__i686.get_pc_thunk.bx>
0xb7730468 <+12>: 81 c3 8c 1b 00 00 add $0x1b8c,%ebx
0xb773046e <+18>: 8d 83 ee e4 ff ff lea -0x1b12(%ebx),%eax
0xb7730474 <+24>: 89 04 24 mov %eax,(%esp)
0xb7730477 <+27>: e8 04 ff ff ff call 0xb7730380 <puts@plt>
0xb773047c <+32>: 83 c4 14 add $0x14,%esp
0xb773047f <+35>: 5b pop %ebx
0xb7730480 <+36>: 5d pop %ebp
0xb7730481 <+37>: c3 ret

显然是一致的。

所以,在编译共享库时是必须加上-fpic的选项的,否则共享库剩(省?)下的仅仅是硬盘上的空间,而没有剩(省?)下内存。

最新文章

  1. JavaScript高级编程 (2) - HTML 与 JavaScript
  2. php 常见问题
  3. The next day to learn English
  4. ios 修改webView字体
  5. IT公司100题-7-判断两个链表是否相交
  6. 想调试,装了个Zend Server
  7. 2015年4月 非常干货之Python资源大全
  8. 创建维护计划时,提示“代理XP”组件已作为此服务器安全配置的一部分被关闭
  9. 如何写mysql的定时任务
  10. 【转】关于C#使用Excel的数据透视表的例子
  11. 如何通过友盟分析发布后App崩溃日志-b
  12. 配置基于NotePad++工具下的C#开发环境
  13. WinCE 5.0模拟器,在 win7 下安装后, VS2008里不显示
  14. 核心动画 CAAnimation 进阶
  15. 笨鸟先飞之ASP.NET MVC系列之过滤器(06异常过滤器)
  16. 初探React与D3的结合-或许是visualization的新突破?
  17. stark组件开发之组合搜索实现思路
  18. 解决普通用户登录ulimit 报错问题
  19. windows下svn钩子实现每次提交更新至web目录
  20. Python中如何获取类属性的列表

热门文章

  1. 【http】http协议的队首阻塞
  2. python 游戏(滑动拼图Slide_Puzzle)
  3. PAT Basic 1035
  4. lnmp环境运行laravel open_basedir restriction in effect 问题
  5. CodeForces 484B 数学 Maximum Value
  6. vim 第三章 插入模式
  7. NYOJ 722 数独
  8. POJ-2187 Beauty Contest,旋转卡壳求解平面最远点对!
  9. iOS知识列表
  10. PAT天梯赛练习题——L3-005. 垃圾箱分布(暴力SPFA)