手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网站运营>建站经验>列表

Intel平台下linux中 ELF文档动态链接的加载、解析及实例分析(二): 函数解析和卸载

来源:互联网 作者:west263.com 时间:2008-04-16
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

719: e9 e2 fe ff ff jmp 600


变成一般的地址是这样的


movl %eip,陎
addl xfffffee2,陎
movl 陎,%eip

这里旁边的 719 就是这个 ELF 文档和起始地址相比的偏移量,而在里面的 e9 e2 fe ff ff 假如写成看的往后退 0x11e 因为这是 ff ff fe e2(intel 是 little endian 表示方法)所表示的 -0x11e 的数。假如把 719 加上 5 再减去 600 就是这个数了。这便是处理器的相对转移。

更有另一种转移方式,就是绝对转移。


2b6: ff d0 call *陎

这个假如用最简单的代码来表示是


addl ,%eip
pushl %eip
movl (陎),%eip

很明显,就是把 eip 的内容变成了eax 中的内容,假如用 jmp 也是相同的


ljmp *(韝)


上面的两种转移方式适应于不同的环境需要,假如是在一个ELF文档中的,采用相对转移可带来的好处有以下的几点:

1、能够不用再访问一次内存,在指令的执行时间上得到了大大的提高(这在PCI的总线结构中现在主流的最高主频是133MHZ,而随便一个INTEL CPU的主频都能超过他)。

2、能够适应在动态加载和动态定位的内存环境,而不用再对原来的代码修改便能实现(代码段也不能在运行的时候修改),因为整个动态链接库或可执行文档都是以连续的地址映射的。

但同样带来了几个问题:

1、这样的相对转移没有办法在运行的时候准确的转移到别的动态链接库中的函数地址(因为虽然大部分的动态链接库的加载地址是能够预计的,但从理论上来说是随机的)。

2、这样的代码在平台之间的移植性带来很大的问题,因为不同的机器没有办法知道这样的数字是代表一个地址,还是代表了一个二进制数。所以在对平台移植有高需要的体系中用的是c 的虚函数指针------相对地址转移的发展。如COM,corba体系中就是这样的。

上面的这两项缺点正好是绝对转移的优势。作一个对比,绝对转移就相当于内存寻址时的立即寻址,而相对转移相当于内存寻址的相对寻址。

在一般的动态链接库中实际运用更是用了一个聪明的办法。请看下一段的汇编语言片段:


2f7: e8 00 00 00 00 call 2fc
2fc: 5b pop 離
2fd: 81 c3 b0 10 00 00 add x10b0,離


这里的2f7中的call 2fc 是什么意思呢,从我们上面的方法来看,这里是什么呢?就是把函数运行到了2fc处,根据是我上面所说的,因为是个相对转移。e8 00 00 00 00。假如用一般的观点看这没有什么用处。但妙处就在这里,2fc处的pop 離,是把什么送到離中呢,假如每一次call 都会把下一条要执行的指令的地址压入栈中,那離中在这里的内容就是2d4这一条指令在内存中的地址了,回想动态链接库的绝对地址是没有办法在编译时得到,但这样却能够--------很巧妙,不对吗?

那后面的add x10b0,離又是什么用处?假如我们这里假定在内存中的地址是2fc,那加上10b0之后的值是0x13ac了,看在这里是什么呢?


Disassembly of section .got:

000013ac <.got>:
13ac: 34 13 xor x13,%al
...


这是个got节, 他的全称是global object table 就是全局对象表。他这里存储着要转移的地址。假如在动态链接库中,或是要调用一个在他之外的函数是怎样实现呢?我们往下看:


306: 8d 83 74 ef ff ff lea 0xffffef74(離),陎
30c: 50 push 陎
30d: e8 ce ff ff ff call 2e0



这里就要调用一个call 2e0 所在的函数。那在0x2e0处又是什么呢?


2e0: ff a3 0c 00 00 00 jmp *0xc(離)
2e6: 68 00 00 00 00 push x0
2eb: e9 e0 ff ff ff jmp 2d0


很明显,我们前面已说了離中所保存的就是.got节的起始地址,而这里就是转移到在.got起始地址偏移0xc处所存储的地址量。而0x2e0所在的地址是在.plt(procedure linkage table)的节中。正是plt got的互相配合,才达到了动态链接的效果。下面的_dl_relocate_object函数就是在把动态链接库加载之后将got中的内容初始化的作用,作好了以后函数解析的准备。

三、_dl_relocate_object函数分析

举个例子。同样来自上面的动态链接库文档中内容。假如我们在这里面调用了printf这个普通的函数,他的rel在文档中的位置是

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

Google