0x4000a971 <_dl_runtime_resolve 17>: pop 靫
0x4000a972 <_dl_runtime_resolve 18>: xchg 陎,(%esp,1)
0x4000a975 <_dl_runtime_resolve 21>: ret x8 //跳到printf函数地址执行
0x4000a978 <_dl_runtime_resolve 24>: nop
0x4000a979 <_dl_runtime_resolve 25>: lea 0x0(%esi,1),%esi
End of assembler dump.
(gdb) b * 0x4000a972
Breakpoint 4 at 0x4000a972: file dl-runtime.c, line 182.
(gdb) c
Continuing.
Breakpoint 4, 0x4000a972 in _dl_runtime_resolve () at dl-runtime.c:182
182 in dl-runtime.c
(gdb) i reg $eax $esp
eax 0x4006804c 1074167884
esp 0xbffffb64 -1073743004
(gdb) b *0x4000a975
Breakpoint 5 at 0x4000a975: file dl-runtime.c, line 182.
(gdb) c
Continuing.
Breakpoint 5, 0x4000a975 in _dl_runtime_resolve () at dl-runtime.c:182
182 in dl-runtime.c
(gdb) si
printf (format=0x1 ) at printf.c:26
26 printf.c: No such file or directory.
(gdb) disass ④ ⑵
Dump of assembler code for function printf:
0x4006804c
0x4006804d
0x4006804f
0x40068050
0x40068055
0x40068056
0x4006805c
0x4006805f
0x40068060
0x40068063
0x40068069
0x4006806b
0x40068070
0x40068073
0x40068074
End of assembler dump.
(gdb) x/8x 0x8049470
0x8049470 <_GLOBAL_OFFSET_TABLE_>: 0x08049490 0x40013ed0 0x4000a960 0x400fa550
0x8049480 <_GLOBAL_OFFSET_TABLE_ 16>: 0x080482ee 0x400328cc 0x4006804c 0x00000000
GOT[6]已被修正为0x4006804c了
第一次调用printf()的时候需要经过①->②->③->④
以后调用printf()的时候就无需这么复杂了,只要经过⑴->⑵就能够了
link_map结构说明如下:
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
members form a chain of all the shared objects loaded at startup.
These data structures exist in space used by the run-time dynamic linker;
modifying them may have disastrous results.
This data structure might change in future, if necessary. User-level
programs must avoid defining objects of this type. */
★★ glibc中动态解析符号的源代码(glibc 2.1.3的实现)
.text
.globl _dl_runtime_resolve
.type _dl_runtime_resolve, @function
.align 16
_dl_runtime_resolve:
pushl 陎 # Preserve registers otherwise clobbered.
pushl 靫
pushl 韝
movl 16(%esp), 韝 # Copy args pushed by PLT in register. Note
movl 12(%esp), 陎 # that `fixup' takes its parameters in regs.
call fixup # Call resolver.
popl 韝 # Get register content back.
popl 靫
xchgl 陎, (%esp) # Get 陎 contents end store function address.
ret # Jump to function address.
static ElfW(Addr) __attribute__ ((unused))
fixup (
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
# endif
struct link_map *l, ElfW(Word) reloc_offset)
{
const ElfW(Sym) *const symtab
= (const void *) l->l_info[DT_SYMTAB]->d_un.d_ptr;
const char *strtab = (const void *) l->l_info[DT_STRTAB]->d_un.d_ptr;
const PLTREL *const reloc /*计算函数重定位人口*/
= (const void *) (l->l_info[DT_JMPREL]->d_un.d_ptr reloc_offset);
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];/*计算函数的符号表入口*/
void *const rel_addr = (void *)(l->l_addr reloc->r_offset);/*GOT[n]的地址*/
ElfW(Addr) value;
/* The use of `alloca' here looks ridiculous but it helps. The goal is
to prevent the function from being inlined and thus optimized out.
There is no official way to do this so we use this trick. gcc never
inlines functions which use `alloca'. */
alloca (sizeof (int));
/* Sanity check that we're really looking at a PLT relocation. */
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);/*健壮性检查*/
/* Look up the target symbol. */
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
default:
{
const ElfW(Half) *vernum =
(const void *) l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
const struct r_found_version *version = &l->l_versions[ndx];
if (version->hash != 0)
{
value = _dl_lookup_versioned_symbol(strtab sym->st_name,
&sym, l->l_scope, l->l_name,
version, ELF_MACHINE_JMP_SLOT);
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




