about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-03-07 05:26:02 +0000
committerUlrich Drepper <drepper@redhat.com>2004-03-07 05:26:02 +0000
commit021723ab784461de9eac57398ea16a47d4ab9366 (patch)
tree9fef57d701b88d5729e3150ea197f86957727998
parentbdf4a4f1eabb2e085b0610b53bb37b5263f4728d (diff)
downloadglibc-021723ab784461de9eac57398ea16a47d4ab9366.tar.gz
glibc-021723ab784461de9eac57398ea16a47d4ab9366.tar.xz
glibc-021723ab784461de9eac57398ea16a47d4ab9366.zip
Update.
2004-03-06  Ulrich Drepper  <drepper@redhat.com>

	* elf/dl-lookup.c: We don't need for specialized lookup functions.
	Combining the functionality does not slow down relocation processing,
	it might even speed it up a little.
	* sysdeps/generic/ldsodefs.h: Adjust prototypes for lookup function.
	Add only one function pointer to rtlf_global_ro.
	* elf/do-lookup.h: Replace #ifs with ifs.
	* elf/dl-libc.c: Adjust _dl_lookup_* callers.
	* elf/dl-reloc.c: Likewise.
	* elf/dl-runtime.c: Likewise.
	* elf/dl-sym.c: Likewise.
	* elf/rtld.c: Likewise.  Adjust _rtld_global_ro initialization.

	* sysdeps/generic/ldsodefs.h (__rtld_local_attribute__,
	__rtld_global_attribute__): Undef after use.
	(_rtld_local_ro): Define __rtld_local_attribute__ with just hidden
	if available.

	* sysdeps/alpha/Subdirs: New file.
	* sysdeps/alpha/soft-fp/Makefile: New file.
	* sysdeps/alpha/soft-fp/Versions: New file.
	* sysdeps/alpha/soft-fp/local-soft-fp.h: New file.
	* sysdeps/alpha/soft-fp/ots_add.c: New file.
	* sysdeps/alpha/soft-fp/ots_cmp.c: new file.
	* sysdeps/alpha/soft-fp/ots_cmpe.c: New file.
	* sysdeps/alpha/soft-fp/ots_cvtqux.c: New file.
	* sysdeps/alpha/soft-fp/ots_cvtqx.c: New file.
	* sysdeps/alpha/soft-fp/ots_cvttx.c: New file.
	* sysdeps/alpha/soft-fp/ots_cvtxq.c: New file.
	* sysdeps/alpha/soft-fp/ots_cvtxt.c: New file.
	* sysdeps/alpha/soft-fp/ots_div.c: New file.
	* sysdeps/alpha/soft-fp/ots_mul.c: New file.
	* sysdeps/alpha/soft-fp/ots_nintxq.c: New file.
	* sysdeps/alpha/soft-fp/ots_sub.c: New file.
-rw-r--r--ChangeLog44
-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
-rw-r--r--sysdeps/generic/ldsodefs.h75
8 files changed, 200 insertions, 222 deletions
diff --git a/ChangeLog b/ChangeLog
index b88511e844..83d57ccb80 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,17 +1,43 @@
+2004-03-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf/dl-lookup.c: We don't need for specialized lookup functions.
+	Combining the functionality does not slow down relocation processing,
+	it might even speed it up a little.
+	* sysdeps/generic/ldsodefs.h: Adjust prototypes for lookup function.
+	Add only one function pointer to rtlf_global_ro.
+	* elf/do-lookup.h: Replace #ifs with ifs.
+	* elf/dl-libc.c: Adjust _dl_lookup_* callers.
+	* elf/dl-reloc.c: Likewise.
+	* elf/dl-runtime.c: Likewise.
+	* elf/dl-sym.c: Likewise.
+	* elf/rtld.c: Likewise.  Adjust _rtld_global_ro initialization.
+
 2004-03-06  Richard Henderson  <rth@redhat.com>
 
+	* sysdeps/generic/ldsodefs.h (__rtld_local_attribute__,
+	__rtld_global_attribute__): Undef after use.
+	(_rtld_local_ro): Define __rtld_local_attribute__ with just hidden
+	if available.
+
 	* soft-fp/quad.h (union _FP_UNION_Q): Add longs structure.
 	* sysdeps/alpha/Implies: Add alpha/soft-fp.
 	* sysdeps/alpha/soft-fp/sfp-machine.h: Rewrite for GEM interface.
-	* sysdeps/alpha/Subdirs, sysdeps/alpha/soft-fp/Makefile,
-	sysdeps/alpha/soft-fp/Versions, sysdeps/alpha/soft-fp/local-soft-fp.h,
-	sysdeps/alpha/soft-fp/ots_add.c, sysdeps/alpha/soft-fp/ots_cmp.c,
-	sysdeps/alpha/soft-fp/ots_cmpe.c, sysdeps/alpha/soft-fp/ots_cvtqux.c,
-	sysdeps/alpha/soft-fp/ots_cvtqx.c, sysdeps/alpha/soft-fp/ots_cvttx.c,
-	sysdeps/alpha/soft-fp/ots_cvtxq.c, sysdeps/alpha/soft-fp/ots_cvtxt.c,
-	sysdeps/alpha/soft-fp/ots_div.c, sysdeps/alpha/soft-fp/ots_mul.c,
-	sysdeps/alpha/soft-fp/ots_nintxq.c, sysdeps/alpha/soft-fp/ots_sub.c:
-	New files.
+	* sysdeps/alpha/Subdirs: New file.
+	* sysdeps/alpha/soft-fp/Makefile: New file.
+	* sysdeps/alpha/soft-fp/Versions: New file.
+	* sysdeps/alpha/soft-fp/local-soft-fp.h: New file.
+	* sysdeps/alpha/soft-fp/ots_add.c: New file.
+	* sysdeps/alpha/soft-fp/ots_cmp.c: new file.
+	* sysdeps/alpha/soft-fp/ots_cmpe.c: New file.
+	* sysdeps/alpha/soft-fp/ots_cvtqux.c: New file.
+	* sysdeps/alpha/soft-fp/ots_cvtqx.c: New file.
+	* sysdeps/alpha/soft-fp/ots_cvttx.c: New file.
+	* sysdeps/alpha/soft-fp/ots_cvtxq.c: New file.
+	* sysdeps/alpha/soft-fp/ots_cvtxt.c: New file.
+	* sysdeps/alpha/soft-fp/ots_div.c: New file.
+	* sysdeps/alpha/soft-fp/ots_mul.c: New file.
+	* sysdeps/alpha/soft-fp/ots_nintxq.c: New file.
+	* sysdeps/alpha/soft-fp/ots_sub.c: New file.
 
 2004-03-06  Ulrich Drepper  <drepper@redhat.com>
 
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);
 
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index cdb0735d49..b5247ad3ec 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -347,8 +347,10 @@ struct rtld_global
 #   define __rtld_local_attribute__
 #  endif
 extern struct rtld_global _rtld_local __rtld_local_attribute__;
+#  undef __rtld_local_attribute__
 # endif
 extern struct rtld_global _rtld_global __rtld_global_attribute__;
+# undef __rtld_global_attribute__
 #endif
 
 #ifndef SHARED
@@ -478,42 +480,34 @@ struct rtld_global_ro
 					      const char *);
   void (internal_function *_dl_start_profile) (void);
   void (*_dl_mcount) (ElfW(Addr) frompc, ElfW(Addr) selfpc);
-  lookup_t (internal_function *_dl_lookup_symbol) (const char *,
-						   struct link_map *,
-						   const ElfW(Sym) **,
-						   struct r_scope_elem *[],
-						   int, int);
-  lookup_t (internal_function *_dl_lookup_versioned_symbol) (const char *,
-							     struct link_map *,
-							     const ElfW(Sym) **,
-							     struct r_scope_elem *[],
-							     const struct r_found_version *,
-							     int, int);
-  lookup_t (internal_function *_dl_lookup_symbol_skip) (const char *,
-							struct link_map *,
-							const ElfW(Sym) **,
-							struct r_scope_elem *[],
-							struct link_map *);
-  lookup_t (internal_function *_dl_lookup_versioned_symbol_skip) (const char *,
-								  struct link_map *,
-								  const ElfW(Sym) **,
-								  struct r_scope_elem *[],
-								  const struct r_found_version *,
-								  struct link_map *);
+  lookup_t (internal_function *_dl_lookup_symbol_x) (const char *,
+						     struct link_map *,
+						     const ElfW(Sym) **,
+						     struct r_scope_elem *[],
+						     const struct r_found_version *,
+						     int, int,
+						     struct link_map *);
 
 };
 # define __rtld_global_attribute__
 # ifdef IS_IN_rtld
+#  ifdef HAVE_VISIBILITY_ATTRIBUTE
+#   define __rtld_local_attribute__ __attribute__ ((visibility ("hidden")))
+#  else
+#   define __rtld_local_attribute__
+#  endif
 extern struct rtld_global_ro _rtld_local_ro
     attribute_relro __rtld_local_attribute__;
 extern struct rtld_global_ro _rtld_global_ro
     attribute_relro __rtld_global_attribute__;
+#  undef __rtld_local_attribute__
 # else
 /* We cheat a bit here.  We declare the variable as as const even
    though it is at startup.  */
 extern const struct rtld_global_ro _rtld_global_ro
     attribute_relro __rtld_global_attribute__;
 # endif
+# undef __rtld_global_attribute__
 #endif
 #undef EXTERN
 
@@ -681,13 +675,6 @@ extern void _dl_rtld_di_serinfo (struct link_map *loader,
    object) is searched in turn.  REFERENCE_NAME should name the object
    containing the reference; it is used in error messages.
    TYPE_CLASS describes the type of symbol we are looking for.  */
-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 flags)
-     internal_function attribute_hidden;
-
 enum
   {
     /* If necessary add dependency between user and provider object.  */
@@ -698,31 +685,15 @@ enum
   };
 
 /* Lookup versioned symbol.  */
-extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
-					     struct link_map *undef_map,
-					     const ElfW(Sym) **sym,
-					     struct r_scope_elem *symbol_scope[],
-					     const struct r_found_version *version,
-					     int type_class, int explicit)
+extern lookup_t _dl_lookup_symbol_x (const char *undef,
+				     struct link_map *undef_map,
+				     const ElfW(Sym) **sym,
+				     struct r_scope_elem *symbol_scope[],
+				     const struct r_found_version *version,
+				     int type_class, int explicit,
+				     struct link_map *skip_map)
      internal_function attribute_hidden;
 
-/* For handling RTLD_NEXT we must be able to skip shared objects.  */
-extern lookup_t _dl_lookup_symbol_skip (const char *undef,
-					struct link_map *undef_map,
-					const ElfW(Sym) **sym,
-					struct r_scope_elem *symbol_scope[],
-					struct link_map *skip_this)
-     internal_function;
-
-/* For handling RTLD_NEXT with versioned symbols we must be able to
-   skip shared objects.  */
-extern lookup_t _dl_lookup_versioned_symbol_skip (const char *undef,
-						  struct link_map *undef_map,
-						  const ElfW(Sym) **sym,
-						  struct r_scope_elem *symbol_scope[],
-						  const struct r_found_version *version,
-						  struct link_map *skip_this)
-     internal_function;
 
 /* Look up symbol NAME in MAP's scope and return its run-time address.  */
 extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name)