diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-lookup.c | 51 | ||||
-rw-r--r-- | elf/dl-reloc.c | 26 | ||||
-rw-r--r-- | elf/do-lookup.h | 9 |
3 files changed, 42 insertions, 44 deletions
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 71dda25aff..5fa6b73b50 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -175,14 +175,14 @@ internal_function _dl_do_lookup (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result, struct r_scope_elem *scope, size_t i, - struct link_map *skip, int noexec, int noplt); + struct link_map *skip, int type_class); static int internal_function _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result, struct r_scope_elem *scope, size_t i, const struct r_found_version *const version, - struct link_map *skip, int noexec, int noplt); + struct link_map *skip, int type_class); /* Search loaded objects' symbol tables for a definition of the symbol @@ -192,21 +192,19 @@ lookup_t internal_function _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], - int reloc_type, int explicit) + int type_class, int explicit) { unsigned long int hash = _dl_elf_hash (undef_name); struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope; int protected; - int noexec = elf_machine_lookup_noexec_p (reloc_type); - int noplt = elf_machine_lookup_noplt_p (reloc_type); ++_dl_num_relocations; /* Search the relevant loaded objects for a definition. */ for (scope = symbol_scope; *scope; ++scope) if (do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0, NULL, - noexec, noplt)) + type_class)) { /* We have to check whether this would bind UNDEF_MAP to an object in the global scope which was dynamically loaded. In this case @@ -223,7 +221,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, /* Something went wrong. Perhaps the object we tried to reference was just removed. Try finding another definition. */ return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope, - reloc_type, 0); + type_class, 0); break; } @@ -270,7 +268,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, for (scope = symbol_scope; *scope; ++scope) if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope, - 0, NULL, 0, 1)) + 0, NULL, ELF_RTYPE_CLASS_PLT)) break; if (protected_value.s == NULL || protected_value.m == undef_map) @@ -311,10 +309,10 @@ _dl_lookup_symbol_skip (const char *undef_name, assert (i < (*scope)->r_nlist); if (! _dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, i, - skip_map, 0, 0)) + skip_map, 0)) while (*++scope) if (_dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0, - skip_map, 0, 0)) + skip_map, 0)) break; if (__builtin_expect (current_value.s == NULL, 0)) @@ -346,10 +344,10 @@ _dl_lookup_symbol_skip (const char *undef_name, if (i >= (*scope)->r_nlist || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope, - i, skip_map, 0, 1)) + i, skip_map, ELF_RTYPE_CLASS_PLT)) while (*++scope) if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope, - 0, skip_map, 0, 1)) + 0, skip_map, ELF_RTYPE_CLASS_PLT)) break; if (protected_value.s == NULL || protected_value.m == undef_map) @@ -374,14 +372,12 @@ _dl_lookup_versioned_symbol (const char *undef_name, struct link_map *undef_map, const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], const struct r_found_version *version, - int reloc_type, int explicit) + int type_class, int explicit) { unsigned long int hash = _dl_elf_hash (undef_name); struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope; int protected; - int noexec = elf_machine_lookup_noexec_p (reloc_type); - int noplt = elf_machine_lookup_noplt_p (reloc_type); ++_dl_num_relocations; @@ -389,7 +385,7 @@ _dl_lookup_versioned_symbol (const char *undef_name, for (scope = symbol_scope; *scope; ++scope) { int res = do_lookup_versioned (undef_name, hash, *ref, ¤t_value, - *scope, 0, version, NULL, noexec, noplt); + *scope, 0, version, NULL, type_class); if (res > 0) { /* We have to check whether this would bind UNDEF_MAP to an object @@ -408,7 +404,7 @@ _dl_lookup_versioned_symbol (const char *undef_name, was just removed. Try finding another definition. */ return _dl_lookup_versioned_symbol (undef_name, undef_map, ref, symbol_scope, version, - reloc_type, 0); + type_class, 0); break; } @@ -482,7 +478,8 @@ _dl_lookup_versioned_symbol (const char *undef_name, for (scope = symbol_scope; *scope; ++scope) if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value, - *scope, 0, version, NULL, 0, 1)) + *scope, 0, version, NULL, + ELF_RTYPE_CLASS_PLT)) break; if (protected_value.s == NULL || protected_value.m == undef_map) @@ -522,10 +519,10 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, assert (i < (*scope)->r_nlist); if (! _dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value, - *scope, i, version, skip_map, 0, 0)) + *scope, i, version, skip_map, 0)) while (*++scope) if (_dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value, - *scope, 0, version, skip_map, 0, 0)) + *scope, 0, version, skip_map, 0)) break; if (__builtin_expect (current_value.s == NULL, 0)) @@ -571,11 +568,11 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, if (i >= (*scope)->r_nlist || !_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value, *scope, i, version, - skip_map, 0, 1)) + skip_map, ELF_RTYPE_CLASS_PLT)) while (*++scope) if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value, *scope, 0, version, - skip_map, 0, 1)) + skip_map, ELF_RTYPE_CLASS_PLT)) break; if (protected_value.s == NULL || protected_value.m == undef_map) @@ -616,10 +613,10 @@ internal_function _dl_do_lookup (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result, struct r_scope_elem *scope, size_t i, - struct link_map *skip, int noexec, int noplt) + struct link_map *skip, int type_class) { - return do_lookup (undef_name, hash, ref, result, scope, i, skip, noexec, - noplt); + return do_lookup (undef_name, hash, ref, result, scope, i, skip, + type_class); } static int @@ -628,8 +625,8 @@ _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result, struct r_scope_elem *scope, size_t i, const struct r_found_version *const version, - struct link_map *skip, int noexec, int noplt) + struct link_map *skip, int type_class) { return do_lookup_versioned (undef_name, hash, ref, result, scope, i, - version, skip, noexec, noplt); + version, skip, type_class); } diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 276aea094b..6e38648d88 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -75,45 +75,43 @@ cannot make segment writable for relocation")); const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ -#define RESOLVE_MAP(ref, version, flags) \ +#define RESOLVE_MAP(ref, version, r_type) \ (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \ - && elf_machine_lookup_noexec_p (flags) == l->l_lookup_cache.noexec \ - && elf_machine_lookup_noplt_p (flags) == l->l_lookup_cache.noplt) \ + && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \ ? (++_dl_num_cache_relocations, \ (*ref) = l->l_lookup_cache.ret, \ l->l_lookup_cache.value) \ : ({ lookup_t _lr; \ + int _tc = elf_machine_type_class (r_type); \ + l->l_lookup_cache.type_class = _tc; \ l->l_lookup_cache.sym = (*ref); \ - l->l_lookup_cache.noexec = elf_machine_lookup_noexec_p (flags); \ - l->l_lookup_cache.noplt = elf_machine_lookup_noplt_p (flags); \ _lr = ((version) != NULL && (version)->hash != 0 \ ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \ l, (ref), scope, \ - (version), (flags), 0) \ + (version), _tc, 0) \ : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \ - scope, (flags), 0)); \ + scope, _tc, 0)); \ l->l_lookup_cache.ret = (*ref); \ l->l_lookup_cache.value = _lr; })) \ : l) -#define RESOLVE(ref, version, flags) \ +#define RESOLVE(ref, version, r_type) \ (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \ - && elf_machine_lookup_noexec_p (flags) == l->l_lookup_cache.noexec \ - && elf_machine_lookup_noplt_p (flags) == l->l_lookup_cache.noplt) \ + && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \ ? (++_dl_num_cache_relocations, \ (*ref) = l->l_lookup_cache.ret, \ l->l_lookup_cache.value) \ : ({ lookup_t _lr; \ + int _tc = elf_machine_type_class (r_type); \ + l->l_lookup_cache.type_class = _tc; \ l->l_lookup_cache.sym = (*ref); \ - l->l_lookup_cache.noexec = elf_machine_lookup_noexec_p (flags); \ - l->l_lookup_cache.noplt = elf_machine_lookup_noplt_p (flags); \ _lr = ((version) != NULL && (version)->hash != 0 \ ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \ l, (ref), scope, \ - (version), (flags), 0) \ + (version), _tc, 0) \ : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \ - scope, (flags), 0)); \ + scope, _tc, 0)); \ l->l_lookup_cache.ret = (*ref); \ l->l_lookup_cache.value = _lr; })) \ : l->l_addr) diff --git a/elf/do-lookup.h b/elf/do-lookup.h index e60e227fcd..b9364b95d1 100644 --- a/elf/do-lookup.h +++ b/elf/do-lookup.h @@ -31,7 +31,7 @@ static inline int FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result, struct r_scope_elem *scope, size_t i, ARG - struct link_map *skip, int noexec, int noplt) + struct link_map *skip, int type_class) { struct link_map **list = scope->r_list; size_t n = scope->r_nlist; @@ -56,7 +56,7 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, continue; /* Don't search the executable when resolving a copy reloc. */ - if (noexec && map->l_type == lt_executable) + if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable) continue; /* Print some debugging info if wanted. */ @@ -76,8 +76,11 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, { sym = &symtab[symidx]; + assert (ELF_RTYPE_CLASS_PLT == 1); if (sym->st_value == 0 || /* No value. */ - (noplt && sym->st_shndx == SHN_UNDEF)) + /* ((type_class & ELF_RTYPE_CLASS_PLT) + && (sym->st_shndx == SHN_UNDEF)) */ + (type_class & (sym->st_shndx == SHN_UNDEF))) continue; if (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC) |