aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-libc.c11
-rw-r--r--elf/dl-reloc.c32
-rw-r--r--elf/dl-runtime.c79
-rw-r--r--elf/dl-sym.c32
-rw-r--r--elf/do-lookup.h137
-rw-r--r--elf/rtld.c12
6 files changed, 142 insertions, 161 deletions
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index 2b8cb0e15d..a6c833a9e2 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -85,9 +85,9 @@ do_dlsym (void *ptr)
{
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
args->ref = NULL;
- args->loadbase = GLRO(dl_lookup_symbol) (args->name, args->map, &args->ref,
- args->map->l_local_scope, 0,
- DL_LOOKUP_RETURN_NEWEST);
+ args->loadbase = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
+ args->map->l_local_scope, NULL, 0,
+ DL_LOOKUP_RETURN_NEWEST, NULL);
}
static void
@@ -126,9 +126,8 @@ do_dlsym_private (void *ptr)
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
args->ref = NULL;
- l = GLRO(dl_lookup_versioned_symbol) (args->name, args->map,
- &args->ref, args->map->l_scope,
- &vers, 0, 0);
+ l = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
+ args->map->l_scope, &vers, 0, 0, NULL);
args->loadbase = l;
}
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 4349dc27fb..4004316c5a 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -213,13 +213,15 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int _tc = elf_machine_type_class (r_type); \
l->l_lookup_cache.type_class = _tc; \
l->l_lookup_cache.sym = (*ref); \
- _lr = ((version) != NULL && (version)->hash != 0 \
- ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \
- l, (ref), scope, (version),\
- _tc, 0) \
- : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \
- scope, _tc, \
- DL_LOOKUP_ADD_DEPENDENCY)); \
+ const struct r_found_version *v = NULL; \
+ int flags = DL_LOOKUP_ADD_DEPENDENCY; \
+ if ((version) != NULL && (version)->hash != 0) \
+ { \
+ v = (version); \
+ flags = 0; \
+ } \
+ _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
+ scope, v, _tc, flags, NULL); \
l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \
: l)
@@ -234,13 +236,15 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int _tc = elf_machine_type_class (r_type); \
l->l_lookup_cache.type_class = _tc; \
l->l_lookup_cache.sym = (*ref); \
- _lr = ((version) != NULL && (version)->hash != 0 \
- ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \
- l, (ref), scope, \
- (version), _tc, 0) \
- : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \
- scope, _tc, \
- DL_LOOKUP_ADD_DEPENDENCY)); \
+ const struct r_found_version *v = NULL; \
+ int flags = DL_LOOKUP_ADD_DEPENDENCY; \
+ if ((version) != NULL && (version)->hash != 0) \
+ { \
+ v = (version); \
+ flags = 0; \
+ } \
+ _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
+ scope, v, _tc, flags, NULL); \
l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \
: l->l_addr)
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index f89cc68de2..ca936d0052 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -73,30 +73,26 @@ fixup (
used don't look in the global scope. */
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
- switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+ const struct r_found_version *version = NULL;
+ // XXX Why exactly do we have the differentiation of the flags here?
+ int flags = DL_LOOKUP_ADD_DEPENDENCY;
+
+ if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
- default:
- {
- 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;
- const struct r_found_version *version = &l->l_versions[ndx];
-
- if (version->hash != 0)
- {
- result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
- l, &sym, l->l_scope,
- version,
- ELF_RTYPE_CLASS_PLT, 0);
- break;
- }
- }
- case 0:
- result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
- l->l_scope, ELF_RTYPE_CLASS_PLT,
- DL_LOOKUP_ADD_DEPENDENCY);
+ 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;
+ else
+ flags = 0;
}
+ result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
+ l->l_scope, version, ELF_RTYPE_CLASS_PLT,
+ DL_LOOKUP_ADD_DEPENDENCY, NULL);
+
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
@@ -161,32 +157,27 @@ profile_fixup (
don't look in the global scope. */
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
- switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+ const struct r_found_version *version = NULL;
+ // XXX Why exactly do we have the differentiation of the flags here?
+ int flags = DL_LOOKUP_ADD_DEPENDENCY;
+
+ if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
- default:
- {
- 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;
- const struct r_found_version *version = &l->l_versions[ndx];
-
- if (version->hash != 0)
- {
- result = _dl_lookup_versioned_symbol (strtab
- + sym->st_name,
- l, &sym, l->l_scope,
- version,
- ELF_RTYPE_CLASS_PLT,
- 0);
- break;
- }
- }
- case 0:
- result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
- l->l_scope, ELF_RTYPE_CLASS_PLT,
- DL_LOOKUP_ADD_DEPENDENCY);
+ 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;
+ else
+ flags = 0;
}
+ result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
+ l->l_scope, version,
+ ELF_RTYPE_CLASS_PLT,
+ DL_LOOKUP_ADD_DEPENDENCY, NULL);
+
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index bee49f1fda..27f79a29e5 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -82,9 +82,9 @@ _dl_sym (void *handle, const char *name, void *who)
if (handle == RTLD_DEFAULT)
/* Search the global scope as seen in the caller object. */
- result = GLRO(dl_lookup_symbol) (name, match, &ref, match->l_scope, 0,
- DL_LOOKUP_RETURN_NEWEST
- | DL_LOOKUP_ADD_DEPENDENCY);
+ result = GLRO(dl_lookup_symbol_x) (name, match, &ref, match->l_scope, NULL,
+ 0, (DL_LOOKUP_RETURN_NEWEST
+ | DL_LOOKUP_ADD_DEPENDENCY), NULL);
else
{
if (handle != RTLD_NEXT)
@@ -92,9 +92,9 @@ _dl_sym (void *handle, const char *name, void *who)
/* Search the scope of the given object. */
struct link_map *map = handle;
- result = GLRO(dl_lookup_symbol) (name, match, &ref,
- map->l_local_scope, 0,
- DL_LOOKUP_RETURN_NEWEST);
+ result = GLRO(dl_lookup_symbol_x) (name, match, &ref,
+ map->l_local_scope, NULL, 0,
+ DL_LOOKUP_RETURN_NEWEST, NULL);
}
else
{
@@ -111,8 +111,8 @@ RTLD_NEXT used in code not dynamically loaded"));
while (l->l_loader != NULL)
l = l->l_loader;
- result = GLRO(dl_lookup_symbol_skip) (name, l, &ref,
- l->l_local_scope, match);
+ result = GLRO(dl_lookup_symbol_x) (name, l, &ref, l->l_local_scope,
+ NULL, 0, 0, match);
}
}
@@ -165,9 +165,9 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
if (handle == RTLD_DEFAULT)
/* Search the global scope. */
- result = GLRO(dl_lookup_versioned_symbol) (name, match, &ref,
- match->l_scope, &vers, 0,
- DL_LOOKUP_ADD_DEPENDENCY);
+ result = GLRO(dl_lookup_symbol_x) (name, match, &ref, match->l_scope,
+ &vers, 0, DL_LOOKUP_ADD_DEPENDENCY,
+ NULL);
else if (handle == RTLD_NEXT)
{
if (__builtin_expect (match == GL(dl_loaded), 0))
@@ -183,17 +183,15 @@ RTLD_NEXT used in code not dynamically loaded"));
while (l->l_loader != NULL)
l = l->l_loader;
- result = GLRO(dl_lookup_versioned_symbol_skip) (name, l, &ref,
- l->l_local_scope,
- &vers, match);
+ result = GLRO(dl_lookup_symbol_x) (name, l, &ref, l->l_local_scope,
+ &vers, 0, 0, match);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = handle;
- result = GLRO(dl_lookup_versioned_symbol) (name, map, &ref,
- map->l_local_scope, &vers,
- 0, 0);
+ result = GLRO(dl_lookup_symbol_x) (name, map, &ref, map->l_local_scope,
+ &vers, 0, 0, NULL);
}
if (ref != NULL)
diff --git a/elf/do-lookup.h b/elf/do-lookup.h
index 014a06a5aa..9e78dbfa8d 100644
--- a/elf/do-lookup.h
+++ b/elf/do-lookup.h
@@ -17,21 +17,16 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#if VERSIONED
-# define FCT do_lookup_versioned
-# define ARG const struct r_found_version *const version
-#else
-# define FCT do_lookup
-# define ARG int flags
-#endif
-
/* Inner part of the lookup functions. We return a value > 0 if we
found the symbol, the value 0 if nothing is found and < 0 if
something bad happened. */
static 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 type_class)
+__attribute_noinline__
+do_lookup_x (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, int flags,
+ struct link_map *skip, int type_class)
{
struct link_map **list = scope->r_list;
size_t n = scope->r_nlist;
@@ -44,10 +39,8 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
const ElfW(Half) *verstab;
Elf_Symndx symidx;
const ElfW(Sym) *sym;
-#if ! VERSIONED
int num_versions = 0;
const ElfW(Sym) *versioned_sym = NULL;
-#endif
map = list[i];
@@ -100,67 +93,71 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
/* Not the symbol we are looking for. */
continue;
-#if VERSIONED
- if (__builtin_expect (verstab == NULL, 0))
+ if (version != NULL)
{
- /* We need a versioned symbol but haven't found any. If
- this is the object which is referenced in the verneed
- entry it is a bug in the library since a symbol must
- not simply disappear.
-
- It would also be a bug in the object since it means that
- the list of required versions is incomplete and so the
- tests in dl-version.c haven't found a problem.*/
- assert (version->filename == NULL
- || ! _dl_name_match_p (version->filename, map));
-
- /* Otherwise we accept the symbol. */
+ if (__builtin_expect (verstab == NULL, 0))
+ {
+ /* We need a versioned symbol but haven't found any. If
+ this is the object which is referenced in the verneed
+ entry it is a bug in the library since a symbol must
+ not simply disappear.
+
+ It would also be a bug in the object since it means that
+ the list of required versions is incomplete and so the
+ tests in dl-version.c haven't found a problem.*/
+ assert (version->filename == NULL
+ || ! _dl_name_match_p (version->filename, map));
+
+ /* Otherwise we accept the symbol. */
+ }
+ else
+ {
+ /* We can match the version information or use the
+ default one if it is not hidden. */
+ ElfW(Half) ndx = verstab[symidx] & 0x7fff;
+ if ((map->l_versions[ndx].hash != version->hash
+ || strcmp (map->l_versions[ndx].name, version->name))
+ && (version->hidden || map->l_versions[ndx].hash
+ || (verstab[symidx] & 0x8000)))
+ /* It's not the version we want. */
+ continue;
+ }
}
else
{
- /* We can match the version information or use the
- default one if it is not hidden. */
- ElfW(Half) ndx = verstab[symidx] & 0x7fff;
- if ((map->l_versions[ndx].hash != version->hash
- || strcmp (map->l_versions[ndx].name, version->name))
- && (version->hidden || map->l_versions[ndx].hash
- || (verstab[symidx] & 0x8000)))
- /* It's not the version we want. */
- continue;
- }
-#else
- /* No specific version is selected. There are two ways we
- can got here:
-
- - a binary which does not include versioning information
- is loaded
-
- - dlsym() instead of dlvsym() is used to get a symbol which
- might exist in more than one form
-
- If the library does not provide symbol version
- information there is no problem at at: we simply use the
- symbol if it is defined.
-
- These two lookups need to be handled differently if the
- library defines versions. In the case of the old
- unversioned application the oldest (default) version
- should be used. In case of a dlsym() call the latest and
- public interface should be returned. */
- if (verstab != NULL)
- {
- if ((verstab[symidx] & 0x7fff)
- >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
+ /* No specific version is selected. There are two ways we
+ can got here:
+
+ - a binary which does not include versioning information
+ is loaded
+
+ - dlsym() instead of dlvsym() is used to get a symbol which
+ might exist in more than one form
+
+ If the library does not provide symbol version
+ information there is no problem at at: we simply use the
+ symbol if it is defined.
+
+ These two lookups need to be handled differently if the
+ library defines versions. In the case of the old
+ unversioned application the oldest (default) version
+ should be used. In case of a dlsym() call the latest and
+ public interface should be returned. */
+ if (verstab != NULL)
{
- /* Don't accept hidden symbols. */
- if ((verstab[symidx] & 0x8000) == 0 && num_versions++ == 0)
- /* No version so far. */
- versioned_sym = sym;
+ if ((verstab[symidx] & 0x7fff)
+ >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
+ {
+ /* Don't accept hidden symbols. */
+ if ((verstab[symidx] & 0x8000) == 0
+ && num_versions++ == 0)
+ /* No version so far. */
+ versioned_sym = sym;
- continue;
+ continue;
+ }
}
}
-#endif
/* There cannot be another entry for this symbol so stop here. */
goto found_it;
@@ -170,11 +167,7 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
looking for an unversioned symbol and the version is not the
default version we still accept this symbol since there are
no possible ambiguities. */
-#if VERSIONED
- sym = NULL;
-#else
sym = num_versions == 1 ? versioned_sym : NULL;
-#endif
if (sym != NULL)
{
@@ -204,13 +197,11 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
}
}
-#if VERSIONED
/* If this current map is the one mentioned in the verneed entry
and we have not found a weak entry, it is a bug. */
- if (symidx == STN_UNDEF && version->filename != NULL
+ if (symidx == STN_UNDEF && version != NULL && version->filename != NULL
&& __builtin_expect (_dl_name_match_p (version->filename, map), 0))
return -1;
-#endif
}
while (++i < n);
diff --git a/elf/rtld.c b/elf/rtld.c
index e2d62b70dc..87d3958679 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -139,10 +139,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
._dl_signal_error = _dl_signal_error,
._dl_start_profile = _dl_start_profile,
._dl_mcount = _dl_mcount_internal,
- ._dl_lookup_symbol = _dl_lookup_symbol,
- ._dl_lookup_versioned_symbol = _dl_lookup_versioned_symbol,
- ._dl_lookup_symbol_skip = _dl_lookup_symbol_skip,
- ._dl_lookup_versioned_symbol_skip = _dl_lookup_versioned_symbol_skip,
+ ._dl_lookup_symbol_x = _dl_lookup_symbol_x,
};
/* If we would use strong_alias here the compiler would see a
non-hidden definition. This would undo the effect of the previous
@@ -1521,9 +1518,10 @@ cannot allocate TLS data structures for initial thread");
ElfW(Addr) loadbase;
lookup_t result;
- result = _dl_lookup_symbol (INTUSE(_dl_argv)[i], GL(dl_loaded),
- &ref, GL(dl_loaded)->l_scope,
- ELF_RTYPE_CLASS_PLT, 1);
+ result = _dl_lookup_symbol_x (INTUSE(_dl_argv)[i], GL(dl_loaded),
+ &ref, GL(dl_loaded)->l_scope, NULL,
+ ELF_RTYPE_CLASS_PLT,
+ DL_LOOKUP_ADD_DEPENDENCY, NULL);
loadbase = LOOKUP_VALUE_ADDRESS (result);