about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--elf/dl-lookup.c82
-rw-r--r--elf/dl-reloc.c55
-rw-r--r--include/link.h16
-rw-r--r--sysdeps/generic/ldsodefs.h15
-rw-r--r--sysdeps/i386/dl-machine.h7
6 files changed, 83 insertions, 107 deletions
diff --git a/ChangeLog b/ChangeLog
index efa4644bcd..7ba5e667d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,24 @@
 2001-08-26  Ulrich Drepper  <drepper@redhat.com>
 
+	* include/link.h (struct link_map): Add l_lookup_cache element.
+	* elf/dl-reloc.c (RESOLVE): Add symbol caching here.
+	(RESOLVE_MAP): Likewise.
+	(_dl_relocate_object): Remove cache initialization.
+	* elf/dl-lookup.c: Rip out cache handling code.
+	* sysdeps/generic/ldsodefs.h: Remove lookup_cache struct and variable
+	declarations.
+
+	* elf/dl-lookup.c (_dl_lookup_symbol): Reorder some conditions and
+	remove some __builtin_expect.
+	(_dl_lookup_versioned_symbol): Likewise.
+
 	* config.h.in: Add HAVE_Z_COMBRELOC.
 	* configure.in: Add test for -z combreloc.
 
 	* sysdeps/i386/dl-machine.h (elf_machine_rel): Minor cleanups and
 	optimizations.  Use HAVE_Z_COMBRELOC to avoid generaton of
-	R_386_RELATIVE handling for ld.so startup.
+	R_386_RELATIVE handling for ld.so startup.  Reduce RTLD_BOOTSTRAP
+	case to almost no code.
 
 2001-08-25  Ulrich Drepper  <drepper@redhat.com>
 
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 047ce4be9f..71dda25aff 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -60,7 +60,6 @@ struct sym_val
 
 /* Statistics function.  */
 unsigned long int _dl_num_relocations;
-unsigned long int _dl_num_cache_relocations;
 
 
 /* We have two different situations when looking up a simple: with or
@@ -185,8 +184,6 @@ _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
 			 const struct r_found_version *const version,
 			 struct link_map *skip, int noexec, int noplt);
 
-struct lookup_cache _dl_lookup_cache;
-struct lookup_cache _dl_lookup_cache_versioned;
 
 /* Search loaded objects' symbol tables for a definition of the symbol
    UNDEF_NAME.  */
@@ -197,29 +194,15 @@ _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)
 {
-  unsigned long int hash;
-  struct sym_val current_value;
+  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);
 
-  /* First check if we can find it in the cache.  */
-  if (__builtin_expect (*ref == _dl_lookup_cache.sym, 0)
-      && _dl_lookup_cache.map == undef_map
-      && _dl_lookup_cache.noexec == noexec
-      && _dl_lookup_cache.noplt == noplt)
-    {
-      ++_dl_num_cache_relocations;
-      *ref = _dl_lookup_cache.ret;
-      return _dl_lookup_cache.value;
-    }
-
   ++_dl_num_relocations;
 
-  hash = _dl_elf_hash (undef_name);
-  current_value = ((struct sym_val) { NULL, NULL });
-
   /* 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,
@@ -229,13 +212,12 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 	   in the global scope which was dynamically loaded.  In this case
 	   we have to prevent the latter from being unloaded unless the
 	   UNDEF_MAP object is also unloaded.  */
-	if (__builtin_expect (current_value.m->l_global, 0)
-	    && (__builtin_expect (current_value.m->l_type, lt_library)
-		== lt_loaded)
+	if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
+	    && current_value.m->l_global
 	    && undef_map != current_value.m
 	    /* Don't do this for explicit lookups as opposed to implicit
 	       runtime lookups.  */
-	    && __builtin_expect (! explicit, 1)
+	    && ! explicit
 	    /* Add UNDEF_MAP to the dependencies.  */
 	    && add_dependency (undef_map, current_value.m) < 0)
 	  /* Something went wrong.  Perhaps the object we tried to reference
@@ -246,11 +228,6 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 	break;
       }
 
-  /* Update common information in the cache.  */
-  _dl_lookup_cache.sym = *ref;
-  _dl_lookup_cache.noexec = noexec;
-  _dl_lookup_cache.noplt = noplt;
-
   if (__builtin_expect (current_value.s == NULL, 0))
     {
       const char *reference_name = undef_map ? undef_map->l_name : NULL;
@@ -262,8 +239,6 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 			       ? reference_name
 			       : (_dl_argv[0] ?: "<main program>")),
 			   make_string (undefined_msg, undef_name));
-      _dl_lookup_cache.ret = NULL;
-      _dl_lookup_cache.value = 0;
       *ref = NULL;
       return 0;
     }
@@ -284,8 +259,6 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 
   if (__builtin_expect (protected == 0, 1))
     {
-      _dl_lookup_cache.ret = current_value.s;
-      _dl_lookup_cache.value = LOOKUP_VALUE (current_value.m);
       *ref = current_value.s;
       return LOOKUP_VALUE (current_value.m);
     }
@@ -302,13 +275,9 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 
       if (protected_value.s == NULL || protected_value.m == undef_map)
 	{
-	  _dl_lookup_cache.ret = current_value.s;
-	  _dl_lookup_cache.value = LOOKUP_VALUE (current_value.m);
 	  *ref = current_value.s;
 	  return LOOKUP_VALUE (current_value.m);
 	}
-      _dl_lookup_cache.ret = *ref;
-      _dl_lookup_cache.value = LOOKUP_VALUE (undef_map);
 
       return LOOKUP_VALUE (undef_map);
     }
@@ -407,30 +376,15 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 			     const struct r_found_version *version,
 			     int reloc_type, int explicit)
 {
-  unsigned long int hash;
-  struct sym_val current_value;
+  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);
 
-  /* First check if we can find it in the cache.  */
-  if (__builtin_expect (*ref == _dl_lookup_cache_versioned.sym, 0)
-      && _dl_lookup_cache_versioned.map == undef_map
-      && _dl_lookup_cache_versioned.noexec == noexec
-      && _dl_lookup_cache_versioned.noplt == noplt
-      && _dl_lookup_cache_versioned.version == version)
-    {
-      ++_dl_num_cache_relocations;
-      *ref = _dl_lookup_cache_versioned.ret;
-      return _dl_lookup_cache_versioned.value;
-    }
-
   ++_dl_num_relocations;
 
-  hash = _dl_elf_hash (undef_name);
-  current_value = ((struct sym_val) { NULL, NULL });
-
   /* Search the relevant loaded objects for a definition.  */
   for (scope = symbol_scope; *scope; ++scope)
     {
@@ -442,13 +396,12 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 	     in the global scope which was dynamically loaded.  In this case
 	     we have to prevent the latter from being unloaded unless the
 	     UNDEF_MAP object is also unloaded.  */
-	  if (__builtin_expect (current_value.m->l_global, 0)
-	      && (__builtin_expect (current_value.m->l_type, lt_library)
-		  == lt_loaded)
+	  if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
+	      && current_value.m->l_global
 	      && undef_map != current_value.m
 	      /* Don't do this for explicit lookups as opposed to implicit
 		 runtime lookups.  */
-	      && __builtin_expect (! explicit, 1)
+	      && ! explicit
 	      /* Add UNDEF_MAP to the dependencies.  */
 	      && add_dependency (undef_map, current_value.m) < 0)
 	    /* Something went wrong.  Perhaps the object we tried to reference
@@ -482,12 +435,6 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 	}
     }
 
-  /* Update common information in the cache.  */
-  _dl_lookup_cache_versioned.sym = *ref;
-  _dl_lookup_cache_versioned.noexec = noexec;
-  _dl_lookup_cache_versioned.noplt = noplt;
-  _dl_lookup_cache_versioned.version = version;
-
   if (__builtin_expect (current_value.s == NULL, 0))
     {
       if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
@@ -503,9 +450,6 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 					  ", version ",
 					  version->name ?: NULL));
 	}
-
-      _dl_lookup_cache_versioned.ret = NULL;
-      _dl_lookup_cache_versioned.value = 0;
       *ref = NULL;
       return 0;
     }
@@ -527,8 +471,6 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 
   if (__builtin_expect (protected == 0, 1))
     {
-      _dl_lookup_cache_versioned.ret = current_value.s;
-      _dl_lookup_cache_versioned.value = LOOKUP_VALUE (current_value.m);
       *ref = current_value.s;
       return LOOKUP_VALUE (current_value.m);
     }
@@ -545,14 +487,10 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 
       if (protected_value.s == NULL || protected_value.m == undef_map)
 	{
-	  _dl_lookup_cache_versioned.ret = current_value.s;
-	  _dl_lookup_cache_versioned.value = LOOKUP_VALUE (current_value.m);
 	  *ref = current_value.s;
 	  return LOOKUP_VALUE (current_value.m);
 	}
 
-      _dl_lookup_cache_versioned.ret = *ref;
-      _dl_lookup_cache_versioned.value = LOOKUP_VALUE (undef_map);
       return LOOKUP_VALUE (undef_map);
     }
 }
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 99cb18962d..276aea094b 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -27,6 +27,9 @@
 #include <sys/types.h>
 #include "dynamic-link.h"
 
+/* Statistics function.  */
+unsigned long int _dl_num_cache_relocations;
+
 
 void
 _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
@@ -74,31 +77,51 @@ cannot make segment writable for relocation"));
     /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
 #define RESOLVE_MAP(ref, version, flags) \
     (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL			      \
-     ? ((version) != NULL && (version)->hash != 0			      \
-	? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref),    \
-				       scope, (version), (flags), 0)	      \
-	: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope,	      \
-			     (flags), 0))				      \
+     ? ((__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)    \
+	? (++_dl_num_cache_relocations,					      \
+	   (*ref) = l->l_lookup_cache.ret,				      \
+	   l->l_lookup_cache.value)					      \
+	: ({ lookup_t _lr;						      \
+	     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)     \
+		    : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref),  \
+					 scope, (flags), 0));		      \
+	     l->l_lookup_cache.ret = (*ref);				      \
+	     l->l_lookup_cache.value = _lr; }))				      \
      : l)
 #define RESOLVE(ref, version, flags) \
     (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL			      \
-     ? ((version) != NULL && (version)->hash != 0			      \
-	? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref),    \
-				       scope, (version), (flags), 0)	      \
-	: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope,	      \
-			     (flags), 0))				      \
+     ? ((__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)    \
+	? (++_dl_num_cache_relocations,					      \
+	   (*ref) = l->l_lookup_cache.ret,				      \
+	   l->l_lookup_cache.value)					      \
+	: ({ lookup_t _lr;						      \
+	     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)     \
+		    : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref),  \
+					 scope, (flags), 0));		      \
+	     l->l_lookup_cache.ret = (*ref);				      \
+	     l->l_lookup_cache.value = _lr; }))				      \
      : l->l_addr)
 
 #include "dynamic-link.h"
-    /* Start symbol lookup caching for this object.  */
-    _dl_lookup_cache.map = l;
-    _dl_lookup_cache_versioned.map = l;
 
     ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
 
-    _dl_lookup_cache.map = NULL;
-    _dl_lookup_cache_versioned.map = NULL;
-
     if (__builtin_expect (consider_profiling, 0))
       {
 	/* Allocate the array which will contain the already found
diff --git a/include/link.h b/include/link.h
index 9345c928d7..5aba874927 100644
--- a/include/link.h
+++ b/include/link.h
@@ -1,6 +1,6 @@
 /* Data structure for communication from the run-time dynamic linker for
    loaded ELF shared objects.
-   Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -34,6 +34,7 @@
 
 #include <bits/elfclass.h>		/* Defines __ELF_NATIVE_CLASS.  */
 #include <bits/link.h>
+#include <dl-lookupcfg.h>
 
 /* Rendezvous structure used by the run-time dynamic linker to communicate
    details of shared object loading to the debugger.  If the executable's
@@ -231,6 +232,19 @@ struct link_map
     unsigned int l_idx;
 
     struct link_map_machine l_mach;
+
+    struct
+    {
+      const ElfW(Sym) *sym;
+      int noexec;
+      int noplt;
+#ifdef DL_LOOKUP_RETURNS_MAP
+      struct link_map *value;
+#else
+      ElfW(Addr) value;
+#endif
+      const ElfW(Sym) *ret;
+    } l_lookup_cache;
   };
 
 struct dl_phdr_info
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 5e093fcdd5..6d196c7379 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -327,21 +327,6 @@ extern void _dl_map_object_deps (struct link_map *map,
 /* Cache the locations of MAP's hash table.  */
 extern void _dl_setup_hash (struct link_map *map) internal_function;
 
-/* This holds symbol lookup cache.  */
-struct lookup_cache
-  {
-    const ElfW(Sym) *sym;
-    struct link_map *map;
-    const struct r_found_version *version;
-    int noexec;
-    int noplt;
-    lookup_t value;
-    const ElfW(Sym) *ret;
-  };
-
-extern struct lookup_cache _dl_lookup_cache;
-extern struct lookup_cache _dl_lookup_cache_versioned;
-
 
 /* Search loaded objects' symbol tables for a definition of the symbol
    referred to by UNDEF.  *SYM is the symbol table entry containing the
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 53d802203a..e7a1b104ef 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -334,13 +334,16 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
       if (sym)
 	value += sym->st_value;
 
+#ifdef RTLD_BOOTSTRAP
+      assert (r_type == R_386_GLOB_DAT || r_type == R_386_JMP_SLOT);
+      *reloc_addr = value;
+#else
       switch (r_type)
 	{
 	case R_386_GLOB_DAT:
 	case R_386_JMP_SLOT:
 	  *reloc_addr = value;
 	  break;
-#ifndef RTLD_BOOTSTRAP
 	case R_386_32:
 	  *reloc_addr += value;
 	  break;
@@ -372,8 +375,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	     if we are still debugging.  */
 	  _dl_reloc_bad_type (map, r_type, 0);
 	  break;
-#endif
 	}
+#endif
     }
 }