PATCH: Continue to search for protected symbols
H. J. Lu
hjl@lucon.org
Wed Apr 2 00:29:00 GMT 2003
When we resolve a reference to a protected symbol, we need to use the
definition within the map. We only need to continue the search from
where the original look stopped when the definition comes from
somewhere else. This patch does that and moves the lookup in
do-lookup.h to avoid code duplication. It also introduces a dummy
ELF_COPY_OBJECT for copy relocation.
H.J.
-------------- next part --------------
2003-04-01 H.J. Lu <hjl@gnu.org>
* sysdeps/generic/ldsodefs.h (ELF_COPY_OBJECT): New.
* elf/do-lookup.h (FCT [do_lookup_versioned, do_lookup]): Return
the next map to be searched on success.
(PROTECTED_FCT [do_protected_lookup_versioned,
do_protected_lookup]): New. Seach for the real definition of a
protected symbol, continuing from where it was stopped the last
time.
* elf/dl-lookup.c (_dl_do_lookup): Change return type to
size_t. Move the prototype before do-lookup.h.
(_dl_do_lookup_versioned): Likewise.
(_dl_lookup_symbol): Call do_protected_lookup for protected
symbol if necessary.
(_dl_lookup_symbol_skip): Likewise.
(_dl_lookup_versioned_symbol): Call do_protected_lookup_versioned
for protected symbol if necessary.
(_dl_lookup_versioned_symbol_skip): Likewise.
--- libc/elf/dl-lookup.c.protected-2 2003-03-26 08:22:01.000000000 -0800
+++ libc/elf/dl-lookup.c 2003-04-01 14:51:49.000000000 -0800
@@ -67,6 +67,19 @@ struct sym_val
# define bump_num_relocations() ((void) 0)
#endif
+static size_t
+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, int flags,
+ struct link_map *skip, int type_class);
+static size_t
+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 type_class);
/* We have two different situations when looking up a simple: with or
@@ -208,20 +221,6 @@ add_dependency (struct link_map *undef_m
return result;
}
-static int
-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, int flags,
- 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 type_class);
-
static void
internal_function
_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
@@ -243,14 +242,19 @@ _dl_lookup_symbol (const char *undef_nam
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
int protected;
+ size_t i;
bump_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, flags,
- NULL, type_class))
- break;
+ {
+ /* It returns the next map to be searched. */
+ i = do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0,
+ flags, NULL, type_class);
+ if (i)
+ break;
+ }
if (__builtin_expect (current_value.s == NULL, 0))
{
@@ -269,36 +273,11 @@ _dl_lookup_symbol (const char *undef_nam
}
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
- if (__builtin_expect (protected != 0, 0))
- {
- /* It is very tricky. We need to figure out what value to
- return for the protected symbol. */
- if (type_class == ELF_RTYPE_CLASS_PLT)
- {
- if (current_value.s != NULL && current_value.m != undef_map)
- {
- current_value.s = *ref;
- current_value.m = undef_map;
- }
- }
- else
- {
- struct sym_val protected_value = { NULL, NULL };
-
- for (scope = symbol_scope; *scope; ++scope)
- if (_dl_do_lookup (undef_name, hash, *ref,
- &protected_value, *scope, 0, flags,
- NULL, ELF_RTYPE_CLASS_PLT))
- break;
-
- if (protected_value.s != NULL
- && protected_value.m != undef_map)
- {
- current_value.s = *ref;
- current_value.m = undef_map;
- }
- }
- }
+ if (__builtin_expect (protected != 0, 0)
+ && current_value.m != undef_map)
+ do_protected_lookup (undef_name, undef_map, hash, *ref,
+ ¤t_value, scope, i, flags, NULL,
+ 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
@@ -351,12 +330,18 @@ _dl_lookup_symbol_skip (const char *unde
for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
assert (i < (*scope)->r_nlist);
- if (! _dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, i,
- DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
+ /* It returns the next map to be searched. */
+ i = _dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, i,
+ DL_LOOKUP_RETURN_NEWEST, skip_map, 0);
+ if (! i)
while (*++scope)
- if (_dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0,
- DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
- break;
+ {
+ i = _dl_do_lookup (undef_name, hash, *ref, ¤t_value,
+ *scope, 0, DL_LOOKUP_RETURN_NEWEST,
+ skip_map, 0);
+ if (i)
+ break;
+ }
if (__builtin_expect (current_value.s == NULL, 0))
{
@@ -366,28 +351,11 @@ _dl_lookup_symbol_skip (const char *unde
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
- if (__builtin_expect (protected != 0, 0))
- {
- /* It is very tricky. We need to figure out what value to
- return for the protected symbol. */
- struct sym_val protected_value = { NULL, NULL };
-
- if (i >= (*scope)->r_nlist
- || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
- i, DL_LOOKUP_RETURN_NEWEST, skip_map,
- ELF_RTYPE_CLASS_PLT))
- while (*++scope)
- if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
- 0, DL_LOOKUP_RETURN_NEWEST, skip_map,
- ELF_RTYPE_CLASS_PLT))
- break;
-
- if (protected_value.s != NULL && protected_value.m != undef_map)
- {
- current_value.s = *ref;
- current_value.m = undef_map;
- }
- }
+ if (__builtin_expect (protected != 0, 0)
+ && current_value.m != undef_map)
+ do_protected_lookup (undef_name, undef_map, hash, *ref,
+ ¤t_value, scope, i,
+ DL_LOOKUP_RETURN_NEWEST, skip_map, 0);
if (__builtin_expect (GL(dl_debug_mask)
& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
@@ -416,6 +384,7 @@ _dl_lookup_versioned_symbol (const char
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
int protected;
+ size_t i;
bump_num_relocations ();
@@ -425,12 +394,13 @@ _dl_lookup_versioned_symbol (const char
/* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope)
{
- int res = do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
- *scope, 0, version, NULL, type_class);
- if (res > 0)
+ /* It returns the next map to be searched. */
+ i = do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
+ *scope, 0, version, NULL, type_class);
+ if (i > 0)
break;
- if (__builtin_expect (res, 0) < 0)
+ if (__builtin_expect (i, 0) < 0)
{
/* Oh, oh. The file named in the relocation entry does not
contain the needed symbol. */
@@ -446,7 +416,7 @@ _dl_lookup_versioned_symbol (const char
" not defined in file ",
version->filename,
" with link time reference",
- res == -2
+ i == -2
? " (no version symbols)" : ""));
*ref = NULL;
return 0;
@@ -474,37 +444,11 @@ _dl_lookup_versioned_symbol (const char
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
- if (__builtin_expect (protected != 0, 0))
- {
- /* It is very tricky. We need to figure out what value to
- return for the protected symbol. */
- if (type_class == ELF_RTYPE_CLASS_PLT)
- {
- if (current_value.s != NULL && current_value.m != undef_map)
- {
- current_value.s = *ref;
- current_value.m = undef_map;
- }
- }
- else
- {
- struct sym_val protected_value = { NULL, NULL };
-
- for (scope = symbol_scope; *scope; ++scope)
- if (_dl_do_lookup_versioned (undef_name, hash, *ref,
- &protected_value,
- *scope, 0, version, NULL,
- ELF_RTYPE_CLASS_PLT))
- break;
-
- if (protected_value.s != NULL
- && protected_value.m != undef_map)
- {
- current_value.s = *ref;
- current_value.m = undef_map;
- }
- }
- }
+ if (__builtin_expect (protected != 0, 0)
+ && current_value.m != undef_map)
+ do_protected_lookup_versioned (undef_name, undef_map, hash, *ref,
+ ¤t_value, scope, i, version,
+ NULL, 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
@@ -558,12 +502,18 @@ _dl_lookup_versioned_symbol_skip (const
for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
assert (i < (*scope)->r_nlist);
- if (! _dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
- *scope, i, version, skip_map, 0))
+ /* It returns the next map to be searched. */
+ i = _dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
+ *scope, i, version, skip_map, 0);
+ if (! i)
while (*++scope)
- if (_dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
- *scope, 0, version, skip_map, 0))
- break;
+ {
+ i = _dl_do_lookup_versioned (undef_name, hash, *ref,
+ ¤t_value, *scope, 0,
+ version, skip_map, 0);
+ if (i)
+ break;
+ }
if (__builtin_expect (current_value.s == NULL, 0))
{
@@ -586,28 +536,11 @@ _dl_lookup_versioned_symbol_skip (const
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
- if (__builtin_expect (protected != 0, 0))
- {
- /* It is very tricky. We need to figure out what value to
- return for the protected symbol. */
- struct sym_val protected_value = { NULL, NULL };
-
- if (i >= (*scope)->r_nlist
- || !_dl_do_lookup_versioned (undef_name, hash, *ref,
- &protected_value, *scope, i, version,
- skip_map, ELF_RTYPE_CLASS_PLT))
- while (*++scope)
- if (_dl_do_lookup_versioned (undef_name, hash, *ref,
- &protected_value, *scope, 0, version,
- skip_map, ELF_RTYPE_CLASS_PLT))
- break;
-
- if (protected_value.s != NULL && protected_value.m != undef_map)
- {
- current_value.s = *ref;
- current_value.m = undef_map;
- }
- }
+ if (__builtin_expect (protected != 0, 0)
+ && current_value.m != undef_map)
+ do_protected_lookup_versioned (undef_name, undef_map, hash, *ref,
+ ¤t_value, scope, i, version,
+ skip_map, 0);
if (__builtin_expect (GL(dl_debug_mask)
& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
@@ -727,7 +660,7 @@ _dl_debug_bindings (const char *undef_na
/* These are here so that we only inline do_lookup{,_versioned} in the common
case, not everywhere. */
-static int __attribute_noinline__
+static size_t __attribute_noinline__
internal_function
_dl_do_lookup (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result,
@@ -738,7 +671,7 @@ _dl_do_lookup (const char *undef_name, u
type_class);
}
-static int __attribute_noinline__
+static size_t __attribute_noinline__
internal_function
_dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result,
--- libc/elf/do-lookup.h.protected-2 2002-04-13 00:51:47.000000000 -0700
+++ libc/elf/do-lookup.h 2003-03-28 11:18:40.000000000 -0800
@@ -20,15 +20,21 @@
#if VERSIONED
# define FCT do_lookup_versioned
# define ARG const struct r_found_version *const version
+# define PROTECTED_FCT do_protected_lookup_versioned
+# define DL_DO_LOOKUP _dl_do_lookup_versioned
+# define DL_DO_LOOKUP_PARAM version
#else
# define FCT do_lookup
# define ARG int flags
+# define PROTECTED_FCT do_protected_lookup
+# define DL_DO_LOOKUP _dl_do_lookup
+# define DL_DO_LOOKUP_PARAM 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 inline int
+static inline size_t
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)
@@ -197,7 +203,7 @@ FCT (const char *undef_name, unsigned lo
/* Global definition. Just what we need. */
result->s = sym;
result->m = map;
- return 1;
+ return i + 1;
default:
/* Local symbols are ignored. */
break;
@@ -218,6 +224,69 @@ FCT (const char *undef_name, unsigned lo
return 0;
}
+/* Seach for the real definition of a protected symbol. We restart from
+ where we stopped the last time. */
+static void
+PROTECTED_FCT (const char *undef_name, struct link_map *undef_map,
+ unsigned long int hash, const ElfW(Sym) *ref,
+ struct sym_val *current_value,
+ struct r_scope_elem **scope, size_t i, ARG,
+ struct link_map *skip, int type_class)
+{
+ /* When we get here, CURRENT_VALUE has the current value for the
+ protected symbol we are interested in and it is not defined in
+ UNDEF_MAP. There are 3 possibilities:
+
+ 1. CURRENT_VALUE has a real definition.
+ 2. CURRENT_VALUE has a definition from a copy relocation.
+ 3. CURRENT_VALUE doesn't have any definition, which may be the
+ case for an ELF_RTYPE_CLASS_PLT relocation.
+
+ For the protected symbol, we need to make sure that the definition
+ from UNDEF_MAP is used.
+
+ If CURRENT_VALUE is defined and not from a copy relocation, use the
+ definition from UNDEF_MAP instead. */
+
+ if (type_class == ELF_RTYPE_CLASS_PLT
+ || (current_value->s
+ && current_value->s->st_shndx != SHN_UNDEF
+ && ! ELF_COPY_OBJECT (current_value->s)))
+ {
+ current_value->s = ref;
+ current_value->m = undef_map;
+ }
+ else
+ {
+ struct sym_val protected_value = { NULL, NULL };
+
+ /* Now, CURRENT_VALUE is either undefined or from a copy
+ relocation. We continue the search for the real definition,
+ using ELF_RTYPE_CLASS_PLT to skip undefined symbols. No need
+ to check the definition from a copy relocation here. */
+ if (*scope
+ && (i >= (*scope)->r_nlist
+ || !DL_DO_LOOKUP (undef_name, hash, ref,
+ &protected_value, *scope, i,
+ DL_DO_LOOKUP_PARAM, skip,
+ ELF_RTYPE_CLASS_PLT)))
+ while (*++scope)
+ if (DL_DO_LOOKUP (undef_name, hash, ref, &protected_value,
+ *scope, 0, DL_DO_LOOKUP_PARAM, skip,
+ ELF_RTYPE_CLASS_PLT))
+ break;
+
+ if (protected_value.s != NULL && protected_value.m != undef_map)
+ {
+ current_value->s = ref;
+ current_value->m = undef_map;
+ }
+ }
+}
+
#undef FCT
#undef ARG
+#undef PROTECTED_FCT
+#undef DL_DO_LOOKUP
+#undef DL_DO_LOOKUP_PARAM
#undef VERSIONED
--- libc/sysdeps/generic/ldsodefs.h.protected-2 2003-03-27 08:06:19.000000000 -0800
+++ libc/sysdeps/generic/ldsodefs.h 2003-04-01 14:57:27.000000000 -0800
@@ -94,6 +94,14 @@ typedef ElfW(Addr) lookup_t;
# define DL_STATIC_INIT(map)
#endif
+/* We need to know if a definition comes from a copy relocation. */
+#ifdef DL_NO_COPY_RELOCS
+# define ELF_COPY_OBJECT(sym) (0)
+#else
+/* FIXME: How to tell if a definition comes from a copy relocation? */
+# define ELF_COPY_OBJECT(sym) (0)
+#endif
+
/* Reloc type classes as returned by elf_machine_type_class().
ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
More information about the Libc-alpha
mailing list