void _dl_static_init (struct link_map *l) { struct link_map *rtld_map = l; struct r_scope_elem **scope; const ElfW(Sym) *ref = NULL; lookup_t loadbase; void (*f) (void *[]); size_t i; loadbase = _dl_lookup_symbol_x ("_dl_var_init", l, &ref, l->l_local_scope, NULL, 0, 1, NULL); for (scope = l->l_local_scope; *scope != NULL; scope++) for (i = 0; i < (*scope)->r_nlist; i++) if ((*scope)->r_list[i] == loadbase) { rtld_map = (*scope)->r_list[i]; break; } if (ref != NULL) { f = (void (*) (void *[])) DL_SYMBOL_ADDRESS (loadbase, ref); _dl_unprotect_relro (rtld_map); f (variables); _dl_protect_relro (rtld_map); } }
void attribute_hidden _dl_tlsdesc_lazy_resolver_fixup (struct tlsdesc volatile *td, Elf32_Addr *got) { struct link_map *l = (struct link_map *)got[1]; lookup_t result; unsigned long value; if (_dl_tlsdesc_resolve_early_return_p (td, (void*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + l->l_addr))) return; if (td->argument.value & 0x80000000) { /* A global symbol, this is the symbol index. */ /* The code below was borrowed from _dl_fixup(). */ const Elf_Symndx symndx = td->argument.value ^ 0x80000000; const ElfW(Sym) *const symtab = (const void *) D_PTR (l, l_info[DT_SYMTAB]); const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); const ElfW(Sym) *sym = &symtab[symndx]; /* Look up the target symbol. If the normal lookup rules are not used don't look in the global scope. */ if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) { const struct r_found_version *version = NULL; if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) { const ElfW(Half) *vernum = (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); ElfW(Half) ndx = vernum[symndx] & 0x7fff; version = &l->l_versions[ndx]; if (version->hash == 0) version = NULL; } result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, version, ELF_RTYPE_CLASS_PLT, DL_LOOKUP_ADD_DEPENDENCY, NULL); if (sym) value = sym->st_value; else { td->entry = _dl_tlsdesc_undefweak; goto done; } } else { /* We already found the symbol. The module (and therefore its load address) is also known. */ result = l; value = sym->st_value; } }
void _dl_static_init (struct link_map *map) { const ElfW(Sym) *ref = NULL; lookup_t loadbase; void (*f) (void *[]); loadbase = _dl_lookup_symbol_x ("_dl_var_init", map, &ref, map->l_local_scope, NULL, 0, 1, NULL); if (ref != NULL) { f = (void (*) (void *[])) DL_SYMBOL_ADDRESS (loadbase, ref); f (variables); } }
void attribute_hidden _dl_tlsdesc_resolve_rela_fixup (struct tlsdesc *td, struct link_map *l) { const ElfW(Rela) *reloc = atomic_load_relaxed (&td->arg); /* After GL(dl_load_lock) is grabbed only one caller can see td->entry in initial state in _dl_tlsdesc_resolve_early_return_p, other concurrent callers will return and retry calling td->entry. The updated td->entry synchronizes with the single writer so all read accesses here can use relaxed order. */ if (_dl_tlsdesc_resolve_early_return_p (td, (void*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + l->l_addr))) return; /* The code below was borrowed from _dl_fixup(), except for checking for STB_LOCAL. */ const ElfW(Sym) *const symtab = (const void *) D_PTR (l, l_info[DT_SYMTAB]); const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)]; lookup_t result; /* Look up the target symbol. If the normal lookup rules are not used don't look in the global scope. */ if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) { const struct r_found_version *version = NULL; if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) { const ElfW(Half) *vernum = (const void *) 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; } result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, version, ELF_RTYPE_CLASS_PLT, DL_LOOKUP_ADD_DEPENDENCY, NULL); } else {
void internal_hidden_function _dl_tlsdesc_resolve_rel_fixup (struct tlsdesc volatile *td, struct link_map *l, ptrdiff_t entry_check_offset) { const ElfW(Rel) *reloc = td->arg; if (_dl_tlsdesc_resolve_early_return_p (td, __builtin_return_address (0) - entry_check_offset)) return; /* The code below was borrowed from _dl_fixup(), except for checking for STB_LOCAL. */ const ElfW(Sym) *const symtab = (const void *) D_PTR (l, l_info[DT_SYMTAB]); const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)]; lookup_t result; /* Look up the target symbol. If the normal lookup rules are not used don't look in the global scope. */ if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) { const struct r_found_version *version = NULL; if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) { const ElfW(Half) *vernum = (const void *) 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; } result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, version, ELF_RTYPE_CLASS_PLT, DL_LOOKUP_ADD_DEPENDENCY, NULL); } else {