- 论坛徽章:
- 0
|
本帖最后由 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 lw t9,1984(t7)
- 400478: 25f807c0 addiu t8,t7,1984
- 40047c: 03200008 jr t9
- 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 lw t9,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 lb zero,0(zero)
- 4107d8: 00410784 0x410784
- 4107dc: 00000000 nop
- 4107e0: 004003d8 0x4003d8
- 4107e4: 00000000 nop
复制代码 |
|