动态链接库函数是怎样调用到的?
本帖最后由 wwxbei 于 2011-07-16 14:00 编辑最近在看动态链接的实现,主要是GOT, PLT段的汇编。 理论上是加载器会修改GOT内容,填写动态库函数的真正地址。 但是从反汇编上却总是看不出来这一点。
就以最简单的printf为例:
main.c
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("Hello world %d.\n", argc);
return 0;
}
看main函数的反汇编,其实是直接跳转到 printf@plt 标号处。
00400470 <printf@plt>:
400470: 3c0f0041 lui t7,0x41
400474: 8df907c0 lwt9,1984(t7)
400478: 25f807c0 addiu t8,t7,1984
40047c: 03200008 jrt9
400480: 00000000 nop
流程是:t7=0x410000, t9=*(0x4107c0),t8=0x4107c0, jr t9
也就是寄存器t8的值是0x4107c0, 而t9的值是内存地址0x4107c0处存放的值。然后跳转到t9指示的地址处。所以,这里的关键就是内存地址0x4107c0处存放的值到底是什么。
Disassembly of section .got.plt:
004107b4 <.got.plt>:
...
4107bc: 00400440 0x400440
4107c0: 00400440 0x400440
可见,地址0x4107c0位于.got.plt段,存放的值为0x400440. 也就是说刚才程序的执行流程会跳转到0x400440地址处,这正是.plt段的位置。
Disassembly of section .plt:
00400440 <_PROCEDURE_LINKAGE_TABLE_>:
400440: 3c1c0041 lui gp,0x41
400444: 8f9907b4 lwt9,1972(gp)
400448: 279c07b4 addiu gp,gp,1972
40044c: 031cc023 subu t8,t8,gp
400450: 03e07821 move t7,ra
400454: 0018c082 srl t8,t8,0x2
400458: 0320f809 jalr t9
40045c: 2718fffe addiu t8,t8,-2
t9=*(0x4107b4),其实就是以0x4107b4处存放的值做目的地址去跳转。而从上面.got.plt段的汇编看,0x4107b4处存放的值应该是零。
Jalr跳到零地址????? 到这里就分析不下去了, 请高手指点一下迷津。
附上.rel.plt和.got段:
Disassembly of section .rel.plt:
004003c8 <.rel.plt>:
4003c8: 0041077c 0x41077c
4003cc: 0000027f 0x27f
4003d0: 00410780 0x410780
4003d4: 0000047f 0x47f
Disassembly of section .got:
004107d0 <_GLOBAL_OFFSET_TABLE_>:
4107d0: 00000000 nop
4107d4: 80000000 lbzero,0(zero)
4107d8: 00410784 0x410784
4107dc: 00000000 nop
4107e0: 004003d8 0x4003d8
4107e4: 00000000 nop 你看一本专著叫《连接器和加载器》,讲解的很详细,动态加载的时候实际启动了一个加载器,帮助程序去调用动态库,并修改程序里的符号表,然后去执行;当第二次运行的时候就不需要再去加载,直接跳到修改过的符号地址 回复 2# 吾爱夏日长
我就是看了书上的理论,才打算找个实际的代码来验证一下的。 但是分析下来实际跟理论结合不上,所以才来请求帮助。 使用GDB单步调试发现, 加载器会修改.got.plt段的内容,加载后(运行前).got.plt段的内容为:
004107b4 <.got.plt>:
4107b4:4081718c 0x4081718c
4107b8:40830a18 0x40830a18
4107bc:00400440 0x400440
4107c0:00400440 0x400440
所以不是跳到零地址,而是跳到0x4081718c处,这是ld-linux.so里面的_dl_runtime_pltresolve()函数所在处。 楼主搞清楚了写个总结出来吧 http://blogold.chinaunix.net/u/3038/showart_2278244.html 《链接器和加载器》大家都说好,其实我个人觉得有点言过其实,对完全不懂的人来说,不适合去看那本书,还是看看《程序员的自我修养-链接、加载和库》,讲得非常详细。你所想知道的都有讲 可以看看这里:
http://tocspblog.appspot.com/?p=40001
页:
[1]