ELF动态链接
为什么要使用动态链接?
在现代的linux系统中,假设一个普通的程序会使用到c语言静态库至少1MB以上,那么,如果我们的机器运行100个这样的程序,就用浪费近100MB的内存;如果磁盘有2000个这样的程序,就要浪费2GB的内存。
静态链接对程序的更新、发布等也会带来问题。比如程序program1使用由第三方厂家提供的库lib.o,当厂家更新lib.o时,程序program1的厂商必须先得到lib.o,那后将program1重新链接,并将整个新的program1发布给客户。可以想象,如果一个这个程序很大,这是多么耗费时间的事。
动态链接正是为了解决静态链接而出现的一种技术。它的优点是:共享的目标文件在磁盘中只有一个副本,在内存中的代码段只有一个副本(通过文件内存映射来实现),这样不仅节约了内存空间,还可以减少物理页面的换进换出;可以动态更换某个模块而不需要重新编译整个程序,不过要重新启动程序才行。这样使得程序升级很方便。
动态链接的基本思想
动态链接的基本思想就是把程序模块拆分成几个相对独立的部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不像静态链接把所有程序模块都链接成一个单独的可执行文件。Linux系统中,ELF动态链接文件被为动态共享对象(DSO,Dynamic Shared Objects),简称共享对象,一般以.so为扩展名。
由于共享对象是可以同时被很多进程共享的,所以我们不应该在编译共享对象的时候就把共享对象中的地址确定下来。如果确定下来了,由于每个进程的虚拟地址空间都不同,这样很难避免共享对象的地址空间和进程的其它地址空间冲突。
如果不能在编译共享对象时确定共享对象的地址,能否在共享对象装载时确定呢?装载时重定位看起来好像是可以解决共享对象装载到任意虚拟地址空间的问题,都是在编译时目标地址不确定而需要在装载是将模块重定位。但是装载时重定位还是不适合用来解决共享对象所存在的问题。想象下,动态链接模块被装载到内存且被映射到虚拟地址空间后,指令部分是在多个进程之间共享的,由于装载时重定位的方法是需要修改指令的,所以没有办法做到同一份指令被多个进程所共享。当然,动态链接库中的可修改数据部分对于不同的进程来说有多个副本,所以它们可以采用装载时重定位的方法来解决。
我们的目的很简单,就是希望程序模块中共享的指令在装载时不需要因为装载地址的改变而改变,所以实现的基本思想就是把指令中需要修改的部分分离出来,跟数据部分存放在一起,这样指令部分就可以保持不变了,而数据部分可以每个进程一个副本。这种技术就是PIC技术(Position-Independent Code)。ELF的具体做法是在数据段中建立一个指向其它模块变量地址的指针数组,称为全局偏移表(Global Offset Table,GOT),而代码中引用全局变量的代码都改成引用GOT。当代码中需要引用该全局变量时,就可以通过GOT相应项间接引用。
动态链接下,程序模块之间包含了大量的函数引用(全局变量往往比较少,因为大量的全局变量引用会导致模块之间的耦合很大),所以在程序开始运行时,会消耗大量的时间来解决模块间函数引用的符号查找和重定位。实际上有很多的函数是不会调用的,如错误处理函数和用户很少使用的功能模块,一开始绑定就浪费资源和时间了。所以ELF采用了一种叫做延迟绑定的做法,基本思想就是当函数第一次被用到时才进行绑定,如果没用到就不绑定。ELF使用PLT(Procedure linkage table)的方法来实现延迟绑定。编译器将GOT分成GOT和GOT.PLT表,GOT用来保存全局变量的地址,GOT.PLT用来保存函数引用的地址。为了实现延迟绑定,我们就不能直接访问GOT表来获取目标函数的地址,必须又添加一层中间跳转表,这个中间跳转表叫做PLT表,由PLT表来真正完成绑定的工作。
ELF动态链接的更多相关文章
- ELF 动态链接 - so 的 .dynamic 段
动态链接文件中最重要的段就是 .dynamic段 这个段里保存了动态链接器需要的最基本的信息 比如:1. 依赖于哪些共享对象, d_tag = DT_NEED, d_ptr 表示共享对象文件名 2 ...
- ELF 动态链接 - so 的 重定位表
动态链接下,无论时可执行文件还是共享对象,一旦对其他共享对象有依赖,也就是所有导入的符号时,那么代码或数据中就会有对于导入符号的引用.而在编译时期这些导入符号的确切地址时未知的.只有在运行期才能确定真 ...
- ELF 动态链接 so的动态符号表(.dynsym)
静态链接中有一个专门的段叫符号表 -- ".symtab"(Symbol Table), 里面保存了所有关于该目标文件的符号的定义和引用. 动态链接中同样有一个段叫 动态符号表 - ...
- ELF 文件 动态链接 - 地址无关代码(GOT)
Linux 系统中,ELF动态链接文件被称为 动态共享对象(DSO,Dynamic Shared Object),简称共享对象 文件拓展名为".so" 动态链接下 一个程序可以被分 ...
- 实例分析ELF文件动态链接
参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第6章 可执行文件的装载与进程 第7章 动态链接 <Linux GOT与PLT> 开发平台 ...
- ELF文件加载与动态链接(一)
关于ELF文件的详细介绍,推荐阅读: ELF文件格式分析 —— 滕启明.ELF文件由ELF头部.程序头部表.节区头部表以及节区4部分组成. 通过objdump工具和readelf工具,可以观察ELF文 ...
- ELF文件加载与动态链接(二)
GOT应该保存的是puts函数的绝对虚地址,这里为什么保存的却是puts@plt的第二条指令呢? 原来“解释器”将动态库载入内存后,并没有直接将函数地址更新到GOT表中,而是在函数第一次被调用时,才会 ...
- (九)ELF和动态链接
前言: 我们都知道我们所写的程序是被编译为一条条的CPU指令去执行的,但是在linux系统下能够运行的程序在windows环境下却运行不起来,但是我们使用的CPU明明是一样的,这又是为什么呢? 一.程 ...
- [CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口
1 平台 转http://blog.csdn.net/misskissc/article/details/43063419 1.1 硬件 Table 1. 硬件(lscpu) Architecture ...
随机推荐
- 利用浏览器LocalStorage缓存图片,视频文件
文章路径:https://hacks.mozilla.org/2012/02/saving-images-and-files-in-localstorage/
- 通过监听键盘,实现对UITextView的内容移动
视图出现时,增加观察 - (void)viewWillAppear:(BOOL)animated { // 增加对键盘的监听 [[NSNotificationCenter defaultCenter] ...
- webform 组合查询
界面: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx ...
- Metaio在Unity3D中报错 Start: failed to load tracking configuration: TrackingConfigGenerated.xml 解决方法
报错:Start: failed to load tracking configuration: TrackingConfigGenerated.xml Start: failed to load t ...
- Unity - Apk包的代码与资源提取
最近在研究如何给Unity游戏进行加密,让别人不能轻易破解你的apk包,不过网上的加密方法都是有对应的破解方法~_~!!结果加密方法没找到好的,逆向工程倒会了不少.今天就来讲解如何提取一个没做任何保护 ...
- POI
一.简介 POI(Point of Interest),中文可以翻译为“兴趣点”.在地理信息系统中,一个POI可以是一栋房子.一个商铺.一个邮筒.一个公交站等. 1.POI检索 百度地图SDK提供三种 ...
- Sql Server 2012新特性 Online添加非空栏位.
我们都知道,Sql Server在一个数据量巨大的表中添加一个非空栏位是比较费心的,缺乏经验的DBA或是开发人员甚至可能鲁莽地直接添加导致阻塞相应业务,甚至可能因为资源欠缺造成实例的全局问题.当然这都 ...
- FLEX布局的一些问题和解决方法
前言 露珠最近研究了一下flex的布局方式,发现项w3c推出的这套布局解决方案对于日益复杂的前端开发布局来说是确实是一利器,并且在不同的屏幕上实现了真正的响应式布局:不再单纯地依赖百分比和float的 ...
- JSON and Microsoft Technologies(翻译)
本文翻译CodeProject(链接)上的一篇文章,文章对JSON的概念以及它在微软一些技术中的应用起到了非常好的扫盲作用,总结得非常好,适合初学者. 目录 介绍 什么是JavaScript对象? 实 ...
- AngularJS 中的Promise --- $q服务详解
先说说什么是Promise,什么是$q吧.Promise是一种异步处理模式,有很多的实现方式,比如著名的Kris Kwal's Q还有JQuery的Deffered. 什么是Promise 以前了解过 ...