热门关键字:  ubuntu  分区  函数  Fedora  linux系统进程

当前位置 :| 主页>Linux教程>编程开发>

Linux动态链接技术

来源: 作者: 时间:2007-04-11 Tag: 点击:
Linux动态链接技术

引自:http://qiuker.spaces.live.com/blog/cns!7B9B144C8022E90D!111.entry?_c11_blogpart_blogpart=blogview&_c=blogpart



Linux动态链接技术(zz)
  在动态链接的应用程序或共享库中,ELF的程序头描述表具有一个PT_DYNAMIC类型的描述符,它指出了.dynamic段的位置,dynamic段用来描述动态链接过程。当应用程序调用的共享库函数时,要通过.plt段进行跳转。plt段又称为过程连接表,它是连接器ld所生成的一组静态的 trampline,是只读的可执行的段,包含在.text段一起映射到内存。plt每16个字节为一个槽位,plt的第1个槽位保留给动态解析器使用,其余的槽位表示对不同共享库函数的调用。plt依赖于全局偏移量表(.got段),GOT表是一可写的数据段,包含在.data段中一起映射到内存,用来存放共享符号的绝对地址。应用程序调用共享库函数就是通过plt槽位上的一条jmp指令跳转到GOT表所指的一个共享函数指针。这样,共享库的重定位就化为对GOT表项的重定位。GOT表的第1个指针指向.dynamic段,第2、3个指针与plt段的第1个槽位对应,用来安装动态解析器。为了少做无用功,Linux采用了动态解析技术,就是说在加载共享库时,并不进行函数的解析,而是安装动态解析器,让共享库调用指向解析器,只有当函数调用发生时才进行解析。为此,在ld在生成可执行程序时,让其GOT共享函数指针指向各自plt槽位上的两条指令,一条是pushl指令,将该函数所对应GOT重定位表的索引作为参数压入堆栈,然后通过另一条jmp指令跳转到plt槽位1,它再跳转到GOT表第3个指针所表示的动态解析器入口。这样当发生并成功解析目标函数在共享库中的地址时,该函数在程序GOT表中的指针就被实际的地址刷新。


下面是基于动态解释器ld.so-1.9.9版本的简单分析

简单的测试文件testso.c:

int x = 0;

int test()
{
 return x;
}

用gcc -S -fPIC testso.c编绎成的汇编代码:

.globl x
.data
 .align 4
 .type  x,@object
 .size  x,4
x:
 .long 0
.text
 .align 4
.globl test
 .type  test,@function
test:
 pushl %ebp
 movl %esp,%ebp
 pushl %ebx
 call .L2
.L2:
 popl %ebx # 取标号.L2所在的地址
 addl $_GLOBAL_OFFSET_TABLE_+[.-.L2],%ebx # _GLOBAL_OFFSET_TABLE_为当前地址到GOT表的偏移
 movl x@GOT(%ebx),%eax # ebx在-fPIC编绎的函数中用于指向本模块的GOT表
 movl (%eax),%eax # x@GOT表示符号x在GOT表中的索引
 movl -4(%ebp),%ebx
 leave
 ret
.Lfe1:
 .size  test,.Lfe1-test

用gcc -shared testso.s -o testso.so生成共享库的反汇编的有关输出:

Disassembly of section .plt:

00000258 <.plt>:
 258: ff b3 04 00 00  pushl  0x4(%ebx) # GOT表的第2个指针,对-fPIC编绎的函数,ebx总是指向GOT表
 25d: 00
 25e: ff a3 08 00 00  jmp    *0x8(%ebx) # 跳转到GOT表的第3个指针,调用__dl_linux_resolover
 263: 00
 264: 00 00           addb   %al,(%eax)
 266: 00 00           addb   %al,(%eax)
 268: ff a3 0c 00 00  jmp    *0xc(%ebx) # 跳转到共享函数test()所在的GOT的指针
 26d: 00
 26e: 68 00 00 00 00  pushl  $0x0  # test()所在GOT指针的初始入口
 273: e9 e0 ff ff ff  jmp    258 <_init+0x8> # 跳转到plt槽位1

Disassembly of section .text:

000002d8 :
 2d8: 55              pushl  %ebp
 2d9: 89 e5           movl   %esp,%ebp
 2db: 53              pushl  %ebx
 2dc: e8 00 00 00 00  call   2e1
 2e1: 5b              popl   %ebx
 2e2: 81 c3 ab 10 00  addl   $0x10ab,%ebx # 取GOT表指针
 2e7: 00
 2e8: 8b 83 10 00 00  movl   0x10(%ebx),%eax  # 从GOT表中取变量x的地址
 2ed: 00
 2ee: 8b 00           movl   (%eax),%eax
 2f0: 8b 5d fc        movl   0xfffffffc(%ebp),%ebx
 2f3: c9              leave  
 2f4: c3              ret    


最新评论共有 4 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册