Update.
authorUlrich Drepper <drepper@redhat.com>
Sat, 13 Apr 2002 07:55:02 +0000 (07:55 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 13 Apr 2002 07:55:02 +0000 (07:55 +0000)
2002-04-13  Ulrich Drepper  <drepper@redhat.com>

* elf/do-lookup.h [!VERSIONED]: Add new parameter flags.  Use it to
check whether the caller prefers getting the most recent version of
a symbol of the earliest version.
* elf/dl-lookup.c: Adjust all callers of do_lookup.  Change
_dl_do_lookup to also take the new parameter and pass it on.
Change 'explicit' parameter of _dl_lookup_symbol and
_dl_lookup_versioned_symbol to flags.  Adjust tests.
* sysdeps/generic/ldsodefs.h: Adjust prototypes.
* elf/dl-libc.c: Adjust all callers of _dl_lookup_symbol and
_dl_lookup_versioned_symbol.
* elf/dl-reloc.c: Likewise.
* elf/dl-runtime.c: Likewise.
* elf/dl-sym.c: Likewise.
* sysdeps/mips/dl-machine.h: Likewise.

ChangeLog
elf/dl-libc.c
elf/dl-lookup.c
elf/dl-reloc.c
elf/dl-runtime.c
elf/dl-sym.c
elf/do-lookup.h
sysdeps/generic/ldsodefs.h
sysdeps/mips/dl-machine.h

index 8d296f7..539d1a4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2002-04-13  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf/do-lookup.h [!VERSIONED]: Add new parameter flags.  Use it to
+       check whether the caller prefers getting the most recent version of
+       a symbol of the earliest version.
+       * elf/dl-lookup.c: Adjust all callers of do_lookup.  Change
+       _dl_do_lookup to also take the new parameter and pass it on.
+       Change 'explicit' parameter of _dl_lookup_symbol and
+       _dl_lookup_versioned_symbol to flags.  Adjust tests.
+       * sysdeps/generic/ldsodefs.h: Adjust prototypes.
+       * elf/dl-libc.c: Adjust all callers of _dl_lookup_symbol and
+       _dl_lookup_versioned_symbol.
+       * elf/dl-reloc.c: Likewise.
+       * elf/dl-runtime.c: Likewise.
+       * elf/dl-sym.c: Likewise.
+       * sysdeps/mips/dl-machine.h: Likewise.
+
 2002-04-11  Jakub Jelinek  <jakub@redhat.com>
 
        * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h (LOC): Don't paste
index bb32f69..938b5d7 100644 (file)
@@ -84,7 +84,8 @@ do_dlsym (void *ptr)
   struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
   args->ref = NULL;
   args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref,
-                                     args->map->l_local_scope, 0, 1);
+                                     args->map->l_local_scope, 0,
+                                     DL_LOOKUP_RETURN_NEWEST);
 }
 
 static void
index f9a229d..9d1e1f6 100644 (file)
@@ -190,7 +190,7 @@ 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,
+              struct r_scope_elem *scope, size_t i, int flags,
               struct link_map *skip, int type_class);
 static int
 internal_function
@@ -215,7 +215,7 @@ 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 type_class, int explicit)
+                  int type_class, int flags)
 {
   const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { NULL, NULL };
@@ -226,8 +226,8 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 
   /* Search the relevant loaded objects for a definition.  */
   for (scope = symbol_scope; *scope; ++scope)
-    if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
-                  type_class))
+    if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, 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
@@ -236,7 +236,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
        if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
            /* Don't do this for explicit lookups as opposed to implicit
               runtime lookups.  */
-           && ! explicit
+           && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
            /* Add UNDEF_MAP to the dependencies.  */
            && add_dependency (undef_map, current_value.m) < 0)
          /* Something went wrong.  Perhaps the object we tried to reference
@@ -272,7 +272,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, ELF_RTYPE_CLASS_PLT))
+                          0, flags, NULL, ELF_RTYPE_CLASS_PLT))
          break;
 
       if (protected_value.s != NULL && protected_value.m != undef_map)
@@ -319,10 +319,10 @@ _dl_lookup_symbol_skip (const char *undef_name,
     assert (i < (*scope)->r_nlist);
 
   if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
-                      skip_map, 0))
+                      DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
     while (*++scope)
       if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
-                        skip_map, 0))
+                        DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
        break;
 
   if (__builtin_expect (current_value.s == NULL, 0))
@@ -341,10 +341,12 @@ _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, ELF_RTYPE_CLASS_PLT))
+                            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, skip_map, ELF_RTYPE_CLASS_PLT))
+                            0, DL_LOOKUP_RETURN_NEWEST, skip_map,
+                            ELF_RTYPE_CLASS_PLT))
            break;
 
       if (protected_value.s != NULL && protected_value.m != undef_map)
@@ -375,7 +377,7 @@ _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 type_class, int explicit)
+                            int type_class, int flags)
 {
   const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { NULL, NULL };
@@ -384,6 +386,9 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 
   bump_num_relocations ();
 
+  /* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed.  */
+  assert (flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
+
   /* Search the relevant loaded objects for a definition.  */
   for (scope = symbol_scope; *scope; ++scope)
     {
@@ -398,14 +403,15 @@ _dl_lookup_versioned_symbol (const char *undef_name,
          if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
              /* Don't do this for explicit lookups as opposed to implicit
                 runtime lookups.  */
-             && ! explicit
+             && flags != 0
              /* Add UNDEF_MAP to the dependencies.  */
              && add_dependency (undef_map, current_value.m) < 0)
            /* Something went wrong.  Perhaps the object we tried to reference
               was just removed.  Try finding another definition.  */
            return INTUSE(_dl_lookup_versioned_symbol) (undef_name, undef_map,
                                                        ref, symbol_scope,
-                                                       version, type_class, 0);
+                                                       version, type_class,
+                                                       0);
 
          break;
        }
@@ -590,12 +596,14 @@ _dl_setup_hash (struct link_map *map)
   map->l_chain = hash;
 }
 
+
 static void
 internal_function
 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
                    const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
-                   struct sym_val *value, const struct r_found_version *version,
-                   int type_class, int protected)
+                   struct sym_val *value,
+                   const struct r_found_version *version, int type_class,
+                   int protected)
 {
   const char *reference_name = undef_map->l_name;
 
@@ -628,7 +636,8 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
 
          if (version == 0)
            _dl_do_lookup (undef_name, hash, *ref, &val,
-                          undef_map->l_local_scope[0], 0, NULL, type_class);
+                          undef_map->l_local_scope[0], 0, 0, NULL,
+                          type_class);
          else
            _dl_do_lookup_versioned (undef_name, hash, *ref, &val,
                                     undef_map->l_local_scope[0], 0, version,
@@ -671,10 +680,10 @@ static int __attribute_noinline__
 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 r_scope_elem *scope, size_t i, int flags,
               struct link_map *skip, int type_class)
 {
-  return do_lookup (undef_name, hash, ref, result, scope, i, skip,
+  return do_lookup (undef_name, hash, ref, result, scope, i, flags, skip,
                    type_class);
 }
 
index 88bd3b6..e5fbb44 100644 (file)
@@ -131,7 +131,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
                                                           l, (ref), scope,   \
                                                           (version), _tc, 0) \
                    : INTUSE(_dl_lookup_symbol) (strtab + (*ref)->st_name, l, \
-                                                (ref), scope, _tc, 0));      \
+                                                (ref), scope, _tc,           \
+                                                DL_LOOKUP_ADD_DEPENDENCY));  \
             l->l_lookup_cache.ret = (*ref);                                  \
             l->l_lookup_cache.value = _lr; }))                               \
      : l)
@@ -152,7 +153,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
                                                           l, (ref), scope,   \
                                                           (version), _tc, 0) \
                    : INTUSE(_dl_lookup_symbol) (strtab + (*ref)->st_name, l, \
-                                                (ref), scope, _tc, 0));      \
+                                                (ref), scope, _tc,           \
+                                                DL_LOOKUP_ADD_DEPENDENCY));  \
             l->l_lookup_cache.ret = (*ref);                                  \
             l->l_lookup_cache.value = _lr; }))                               \
      : l->l_addr)
index 3cc8325..ed1c337 100644 (file)
@@ -98,7 +98,8 @@ fixup (
          }
        case 0:
          result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l, &sym,
-                                             l->l_scope, ELF_RTYPE_CLASS_PLT, 0);
+                                             l->l_scope, ELF_RTYPE_CLASS_PLT,
+                                             DL_LOOKUP_ADD_DEPENDENCY);
        }
 
       /* Currently result contains the base load address (or link map)
@@ -192,9 +193,10 @@ profile_fixup (
                  }
              }
            case 0:
-             result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l, &sym,
-                                                 l->l_scope, ELF_RTYPE_CLASS_PLT,
-                                                 0);
+             result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l,
+                                                 &sym, l->l_scope,
+                                                 ELF_RTYPE_CLASS_PLT,
+                                                 DL_LOOKUP_ADD_DEPENDENCY);
            }
 
          /* Currently result contains the base load address (or link map)
index 8cb5d2f..3bf8104 100644 (file)
@@ -51,7 +51,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 = _dl_lookup_symbol (name, match, &ref, match->l_scope, 0, 0);
+    result = _dl_lookup_symbol (name, match, &ref, match->l_scope, 0,
+                               DL_LOOKUP_RETURN_NEWEST
+                               | DL_LOOKUP_ADD_DEPENDENCY);
   else
     {
       if (handle != RTLD_NEXT)
@@ -60,7 +62,7 @@ _dl_sym (void *handle, const char *name, void *who)
          struct link_map *map = handle;
 
          result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
-                                     0, 1);
+                                     0, DL_LOOKUP_RETURN_NEWEST);
        }
       else
        {
@@ -132,7 +134,7 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
   if (handle == RTLD_DEFAULT)
     /* Search the global scope.  */
     result = _dl_lookup_versioned_symbol (name, match, &ref, match->l_scope,
-                                         &vers, 0, 0);
+                                         &vers, 0, DL_LOOKUP_ADD_DEPENDENCY);
   else if (handle == RTLD_NEXT)
     {
       if (__builtin_expect (match == GL(dl_loaded), 0))
@@ -157,7 +159,7 @@ RTLD_NEXT used in code not dynamically loaded"));
       /* Search the scope of the given object.  */
       struct link_map *map = handle;
       result = _dl_lookup_versioned_symbol (name, map, &ref,
-                                           map->l_local_scope, &vers, 0, 1);
+                                           map->l_local_scope, &vers, 0, 0);
     }
 
   if (ref != NULL)
index bebdb0c..be75fb7 100644 (file)
 
 #if VERSIONED
 # define FCT do_lookup_versioned
-# define ARG const struct r_found_version *const version,
+# define ARG const struct r_found_version *const version
 #else
 # define FCT do_lookup
-# define ARG
+# define ARG int flags
 #endif
 
 /* Inner part of the lookup functions.  We return a value > 0 if we
@@ -30,7 +30,7 @@
    something bad happened.  */
 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 sym_val *result, struct r_scope_elem *scope, size_t i, ARG,
      struct link_map *skip, int type_class)
 {
   struct link_map **list = scope->r_list;
@@ -129,19 +129,34 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
                continue;
            }
 #else
-         /* No specific version is selected.  When the object file
-            also does not define a version we have a match.
-            Otherwise we accept the default version, or in case there
-            is only one version defined, this one version.  */
+         /* 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)
            {
-             ElfW(Half) ndx = verstab[symidx] & 0x7fff;
-             if (ndx >= 2) /* map->l_versions[ndx].hash != 0) */
+             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;
                }
            }
index 0113918..5f586f2 100644 (file)
@@ -532,15 +532,24 @@ extern lookup_t _dl_lookup_symbol (const char *undef,
                                   struct link_map *undef_map,
                                   const ElfW(Sym) **sym,
                                   struct r_scope_elem *symbol_scope[],
-                                  int type_class, int explicit)
+                                  int type_class, int flags)
      internal_function;
 extern lookup_t _dl_lookup_symbol_internal (const char *undef,
                                            struct link_map *undef_map,
                                            const ElfW(Sym) **sym,
                                            struct r_scope_elem *symbol_scope[],
-                                           int type_class, int explicit)
+                                           int type_class, int flags)
      internal_function;
 
+enum
+  {
+    /* If necessary add dependency between user and provider object.  */
+    DL_LOOKUP_ADD_DEPENDENCY = 1,
+    /* Return most recent version instead of default version for
+       unversioned lookup.  */
+    DL_LOOKUP_RETURN_NEWEST = 2
+  };
+
 /* Lookup versioned symbol.  */
 extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
                                             struct link_map *undef_map,
index fcf37f6..bc5e84f 100644 (file)
@@ -307,7 +307,8 @@ __dl_runtime_resolve (ElfW(Word) sym_index,                               \
          }                                                                   \
        case 0:                                                               \
          value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,          \
-                                    l->l_scope, ELF_RTYPE_CLASS_PLT, 0);     \
+                                    l->l_scope, ELF_RTYPE_CLASS_PLT,         \
+                                    DL_LOOKUP_ADD_DEPENDENCY);               \
        }                                                                     \
                                                                              \
       /* Currently value contains the base load address of the object        \