structlink_map { /* Shared library's load address. */ ElfW(Addr) l_addr; /* Pointer to library's name in the string table. */char *l_name; /* Dynamic section of the shared object. Includes dynamic linking info etc. Not interesting to us. */ ElfW(Dyn) *l_ld; /* Pointer to previous and next link_map node. */ structlink_map *l_next, *l_prev; };
► f 0 0x7ffff7fdd80d _dl_relocate_object+3613 f 1 0x7ffff7fdd80d _dl_relocate_object+3613 f 2 0x7ffff7fd353a dl_main+8026 f 3 0x7ffff7febc4b _dl_sysdep_start+1355 f 4 0x7ffff7fd104c _dl_start+604 f 5 0x7ffff7fd104c _dl_start+604 f 6 0x7ffff7fd0108 _dl_start_user f 7 0x1
/* 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. If the normal lookup rules are not used don't look in the global scope. */ if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) { conststructr_found_version *version =NULL;
if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) { constElfW(Half) *vernum = (constvoid *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; version = &l->l_versions[ndx]; if (version->hash == 0) version = NULL; }
/* We need to keep the scope around so do some locking. This is not necessary for objects which cannot be unloaded or when we are not using any threads (yet). */ int flags = DL_LOOKUP_ADD_DEPENDENCY; if (!RTLD_SINGLE_THREAD_P) { THREAD_GSCOPE_SET_FLAG (); flags |= DL_LOOKUP_GSCOPE_LOCK; }
/* Currently result contains the base load address (or link map) of the object that defines sym. Now add in the symbol offset. */ value = DL_FIXUP_MAKE_VALUE (result, SYMBOL_ADDRESS (result, sym, false)); } else { /* We already found the symbol. The module (and therefore its load address) is also known. */ value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, sym, true)); result = l; }
/* And now perhaps the relocation addend. */ value = elf_machine_plt_value (l, reloc, value);
if (sym != NULL && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
#ifdef SHARED /* Auditing checkpoint: we have a new binding. Provide the auditing libraries the possibility to change the value and tell us whether further auditing is wanted. The l_reloc_result is only allocated if there is an audit module which provides a la_symbind. */ if (l->l_reloc_result != NULL) { /* This is the address in the array where we store the result of previous relocations. */ structreloc_result *reloc_result = &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; unsignedint init = atomic_load_acquire (&reloc_result->init); if (init == 0) { _dl_audit_symbind (l, reloc_result, reloc, sym, &value, result, true);
/* Store the result for later runs. */ if (__glibc_likely (! GLRO(dl_bind_not))) { reloc_result->addr = value; /* Guarantee all previous writes complete before init is updated. See CONCURRENCY NOTES below. */ atomic_store_release (&reloc_result->init, 1); } } else value = reloc_result->addr; } #endif
/* Finally, fix up the plt itself. */ if (__glibc_unlikely (GLRO(dl_bind_not))) return value;