引用testso的应用程序文件test.c:
main()
{
printf("%d\n",test());
}
用gcc test.c testso.so -o test生成可执行文件的反汇编输出:
Disassembly of section .plt:
08048398 <.plt>:
8048398: ff 35 54 95 04 pushl 0x8049554 # GOT表的第2个指针
804839d: 08
804839e: ff 25 58 95 04 jmp *0x8049558 # GOT表的第3个指针,运行_dl_linux_resolver
80483a3: 08
80483a4: 00 00 addb %al,(%eax)
80483a6: 00 00 addb %al,(%eax)
80483a8: ff 25 5c 95 04 jmp *0x804955c # printf()在plt的入口
80483ad: 08
80483ae: 68 00 00 00 00 pushl $0x0
80483b3: e9 e0 ff ff ff jmp 8048398 <_init+0x8>
80483b8: ff 25 60 95 04 jmp *0x8049560
80483bd: 08
80483be: 68 08 00 00 00 pushl $0x8
80483c3: e9 d0 ff ff ff jmp 8048398 <_init+0x8>
80483c8: ff 25 64 95 04 jmp *0x8049564 # test()在plt段的调用点
80483cd: 08 # [0x8048564]初始时指向0x80483ce
80483ce: 68 10 00 00 00 pushl $0x10 # test()在GOT表重定位表.rel.got中的索引
80483d3: e9 c0 ff ff ff jmp 8048398 <_init+0x8> # 跳转到plt的第1槽位
80483d8: ff 25 68 95 04 jmp *0x8049568
80483dd: 08
80483de: 68 18 00 00 00 pushl $0x18
80483e3: e9 b0 ff ff ff jmp 8048398 <_init+0x8>
80483e8: ff 25 6c 95 04 jmp *0x804956c
80483ed: 08
80483ee: 68 20 00 00 00 pushl $0x20
80483f3: e9 a0 ff ff ff jmp 8048398 <_init+0x8>
80483f8: ff 25 70 95 04 jmp *0x8049570
80483fd: 08
80483fe: 68 28 00 00 00 pushl $0x28
8048403: e9 90 ff ff ff jmp 8048398 <_init+0x8>
Disassembly of section .text:
080484c8 :
80484c8: 55 pushl %ebp
80484c9: 89 e5 movl %esp,%ebp
80484cb: e8 f8 fe ff ff call 80483c8 <_init+0x38> #
80484d0: 89 c0 movl %eax,%eax
80484d2: 50 pushl %eax
80484d3: 68 38 85 04 08 pushl $0x8048538
80484d8: e8 cb fe ff ff call 80483a8 <_init+0x18>
80484dd: 83 c4 08 addl $0x8,%esp
80484e0: c9 leave
80484e1: c3 ret
ld.so-1.9.9/d-link/i386/resolve.S
#define ALIGN 4
#define RUN linux_run
#define RESOLVE _dl_linux_resolve
#define RESOLVER _dl_linux_resolver
#define EXIT _interpreter_exit
#define INIT __loader_bootstrap
.text
.align ALIGN
.align 16
.globl RESOLVE
.type RESOLVE,@function
RESOLVE:
pusha
lea 0x20(%esp),%eax /* eax = tpnt and reloc_entry params */
pushl 4(%eax) /* push copy of reloc_entry param */
pushl (%eax) /* push copy of tpnt param */
pushl %eax /* _dl_linux_resolver expects a dummy
* param - this could be removed */
#ifdef __PIC__
call .L24
.L24:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L24],%ebx
movl RESOLVER@GOT(%ebx),%ebx /* eax = resolved func */
call *%ebx
#else
call RESOLVER
#endif
movl %eax,0x2C(%esp) /* store func addr over original
* tpnt param */
addl $0xC,%esp /* remove copy parameters */
popa /* restore regs */
ret $4 /* jump to func removing original
* reloc_entry param from stack */
.LFE2:
.size RESOLVE,.LFE2-RESOLVE
d-link/i386/elfinterp.c:
unsigned int _dl_linux_resolver(int dummy, int i)
{
unsigned int * sp;
int reloc_entry;
int reloc_type;
struct elf32_rel * this_reloc;
char * strtab;
struct elf32_sym * symtab;
struct elf32_rel * rel_addr;
struct elf_resolve * tpnt;
int symtab_index;
char * new_addr;
char ** got_addr;
unsigned int instr_addr;
sp = &i;
reloc_entry = sp[1];
tpnt = (struct elf_resolve *) sp[0];
rel_addr = (struct elf32_rel *) (tpnt->dynamic_info[DT_JMPREL] +
tpnt->loadaddr); 取可执行程序的GOT重定位表
this_reloc = rel_addr + (reloc_entry >> 3);
reloc_type = ELF32_R_TYPE(this_reloc->r_info);
symtab_index = ELF32_R_SYM(this_reloc->r_info);
symtab = (struct elf32_sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
if (reloc_type != R_386_JMP_SLOT) {
_dl_fdprintf(2, "%s: Incorrect relocation type in jump relocations\n",
_dl_progname);
_dl_exit(1);
};
/* Address of jump instruction to fix up */
instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
got_addr = (char **) instr_addr;
#ifdef DEBUG
_dl_fdprintf(2, "Resolving symbol %s\n",
strtab + symtab[symtab_index].st_name);
#endif
/* Get the address of the GOT entry */
new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
tpnt->symbol_scope, (int) got_addr, tpnt, 0);
if(!new_addr) {
_dl_fdprintf(2, "%s: can‘t resolve symbol ‘%s‘\n",
_dl_progname, strtab + symtab[symtab_index].st_name);
_dl_exit(1);
};
/* #define DEBUG_LIBRARY */
#ifdef DEBUG_LIBRARY
if((unsigned int) got_addr < 0x40000000) {
_dl_fdprintf(2, "Calling library function: %s\n",
strtab + symtab[symtab_index].st_name);
} else {
*got_addr = new_addr;
}
#else
*got_addr = new_addr; 更新GOT函数指针
#endif
return (unsigned int) new_addr;
}
