代碼裏調用外部函數時,轉向去調用PLT部分的代碼。
2.GOT(global offset table)
保存外部函數的地址(當然也包括外部變量),初始加載時,每個函數的地址不是準確的地址,而是這個函數對應PLT項的Push指令的地址。第一次調用函數後填入真正的地址。
3.PLT
指令序列的集合,存放在虛擬內存空間的代碼區域。分兩大部分:PLT0, PLTn。PLT0的指令作用是壓模塊標誌進棧和調用__dll_runtime_resolve函數。
4.Rel.PLT
extern int f();
static int g(){
return f();
}
int function(void) {
int k = g();
int c = foo;
return (c+k);
}
gcc -fIPC -shared dynlib.so dynlib.c
6d0: 55 push %ebp
6d1: 89 e5 mov %esp,%ebp
6d3: 53 push %ebx
6d4: 83 ec 04 sub $0x4,%esp
6d7: e8 00 00 00 00 call 6dc <g+0xc>
6dc: 5b pop %ebx
6dd: 81 c3 a4 11 00 00 add $0x11a4,%ebx
6e3: e8 6c fe ff ff call 554 <_init+0x28>(運行PLT裏f函數對應項的指令去獲取f的地址)
6e8: 89 c0 mov %eax,%eax
6ea: 89 c0 mov %eax,%eax
6ec: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
6ef: c9 leave
6f0: c3 ret
6f1: 8d 76 00 lea 0x0(%esi),%esi
544: ff b3 04 00 00 00 pushl 0x4(%ebx) (push library ID)
54a: ff a3 08 00 00 00 jmp *0x8(%ebx) (jump to function _dll_runtime_resolve())
550: 00 00 add %al,(%eax)
552: 00 00 add %al,(%eax)
554: ff a3 0c 00 00 00 jmp *0xc(%ebx)
55a: 68 00 00 00 00 push $0x0
55f: e9 e0 ff ff ff jmp 544 <_init+0x18>
564: ff a3 10 00 00 00 jmp *0x10(%ebx)
56a: 68 08 00 00 00 push $0x8
56f: e9 d0 ff ff ff jmp 544 <_init+0x18>
574: ff a3 14 00 00 00 jmp *0x14(%ebx)
57a: 68 10 00 00 00 push $0x10
57f: e9 c0 ff ff ff jmp 544 <_init+0x18>
584: ff a3 18 00 00 00 jmp *0x18(%ebx)
58a: 68 18 00 00 00 push $0x18
58f: e9 b0 ff ff ff jmp 544 <_init+0x18>
接下來55f的指令就跳轉到PL0的指令地址去,544指令的目的是壓模塊ID入棧,就是這個動態庫是哪個動態庫。54a指令去調用函數_dll_runtime_resolve去解析函數f的地址,填入GOT中f對應的項中,並且執行f。
第二次執行函數f時,還會跳轉到指令554去,但這時 *0xc(%ebx)的值就是真正函數f的地址值了,這時554的效果就是轉到函數f的地址去執行f了。
Elf32_Addr r_offset;
Elf32_Word r_info;
}Elf32_Rel;
0x00001880 0000055a(加載時,初始值是PLT中函數f對應項的push指令地址,本例中就是55a;第一次運行函數f後就寫入函數f的地址)
0x000018a0 00000000 00000000 00000000 00000000 ................
Offset Info Type Symbol's Value Symbol's Name
0000188c 00001607 R_386_JUMP_SLOT 00000000 f
00001890 00001707 R_386_JUMP_SLOT 00000000 __register_frame_info
00001894 00001907 R_386_JUMP_SLOT 00000000 __deregister_frame_info
00001898 00001d07 R_386_JUMP_SLOT 00000000 __cxa_finalize