about summary refs log tree commit diff
path: root/elf/dl-lookup.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2001-12-12 00:21:26 +0000
committerUlrich Drepper <drepper@redhat.com>2001-12-12 00:21:26 +0000
commit32e6df3621edc5067dfd6e87a387e1751f67f708 (patch)
tree957300a92ed16417fb46ce240d19f965fe773181 /elf/dl-lookup.c
parent4be601a15e63d03adf55c48c19dda2d2e7377d8a (diff)
downloadglibc-32e6df3621edc5067dfd6e87a387e1751f67f708.tar.gz
glibc-32e6df3621edc5067dfd6e87a387e1751f67f708.tar.xz
glibc-32e6df3621edc5067dfd6e87a387e1751f67f708.zip
Update.
2001-12-11  Jakub Jelinek  <jakub@redhat.com>

	* elf/Makefile (dl-routines): Add conflict.
	(rtld-ldscript-in, rtld-ldscript, rtld-parms): Remove.
	(ld.so): Add _begin local symbol.
	* elf/elf.h (DT_VALTAGIDX, DT_VALNUM, DT_ADDRTAGIDX, DT_ADDRNUM):
	Define.
	* elf/dl-deps.c (_dl_build_local_scope): New.
	(_dl_map_object_deps): If LD_TRACE_PRELINKING, compute local scopes
	of all libraries.
	* elf/do-rel.h (VALIDX): Define.
	(elf_dynamic_do_rel): If ELF_MACHINE_PLT_REL is defined, don't do
	lazy binding for RELA.  If DT_GNU_PRELINKED, DT_RELACOUNT relocations
	can be skipped.
	* elf/dl-conflict.c: New file.
	* elf/dl-lookup.c (_dl_debug_bindings): New.
	(_dl_lookup_symbol): Use _dl_debug_bindings.  Reference_name is always
	non-NULL.
	(_dl_lookup_symbol_skip): Likewise.
	(_dl_lookup_versioned_symbol): Likewise.
	(_dl_lookup_versioned_symbol_skip): Likewise.
	* elf/dl-runtime.c (PLTREL): If ELF_MACHINE_PLT_REL is defined,
	define to ElfW(Rel).
	* elf/dynamic-link.h (elf_get_dynamic_info): Record selected dynamic
	tags in the DT_VALRNGLO..DT_VALRNGHI and DT_ADDRRNGLO..DT_ADDRRNGHI
	ranges.
	Don't adjust address dynamic tags if l_addr is 0.
	* elf/rtld.c (_dl_trace_prelink, _dl_trace_prelink_map): New variables.
	(_dl_start): Skip ELF_DYNAMIC_RELOCATE if ld.so is prelinked.
	(VALIDX, ADDRIDX): Define.
	(_dl_start_final): Initialize _dl_rtld_map's l_map_start and l_map_end.
	(dl_main): Print library list for LD_TRACE_PRELINKING.
	If prelinking information can be used, skip relocating libraries and
	call _dl_resolve_conflicts instead.
	(process_envvars): Handle LD_TRACE_PRELINKING envvar.
	* elf/dl-load.c (_dl_map_object): Don't create fake libs
	if LD_TRACE_PRELINKING.
	* include/link.h (struct link_map) [l_info]: Add DT_VALNUM
	+ DT_ADDRNUM.
	* sysdeps/generic/ldsodefs.h (_dl_trace_prelink_map): New declaration.
	(DL_DEBUG_PRELINK): Define.
	(_dl_resolve_conflicts): Add prototype.

	* sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Reinitialize
	.plt for prelinked libraries where prelinking info cannot be used.
	(elf_machine_rela): If relocating R_ALPHA_JMP_SLOT in .gnu.conflict
	section, use RESOLVE_CONFLICT_FIND_MAP to find out reloc's link_map.
	* sysdeps/arm/bits/link.h: New file.
	* sysdeps/arm/dl-machine.h (elf_machine_runtime_setup): Save original
	content of .got[1].
	(ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP.
	(ELF_MACHINE_PLT_REL): Define.
	(elf_machine_rela, elf_machine_rela_relative): New.
	(elf_machine_lazy_rel): Reinitialize R_ARM_JUMP_SLOT address instead
	of adjusting it if prelinked and prelinking cannot be used.
	* sysdeps/i386/bits/link.h: New file.
	* sysdeps/i386/dl-machine.h (elf_machine_runtime_setup): Save original
	content of .got[1].
	(ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP.
	(ELF_MACHINE_PLT_REL): Define.
	(elf_machine_rela, elf_machine_rela_relative): New.
	(elf_machine_lazy_rel): Reinitialize R_386_JUMP_SLOT address instead
	of adjusting it if prelinked and prelinking cannot be used.
	* sysdeps/powerpc/dl-machine.h (elf_machine_rela): If relocating
	conflicts, skip finaladdr computation.  Use RESOLVE_CONFLICT_FIND_MAP
	to find out map for R_PPC_JMP_SLOT relocs.
	* sysdeps/sparc/sparc32/dl-machine.h (VALIDX): Define.
	(OPCODE_BA): Define.
	(elf_machine_runtime_setup): Reinitialize .plt for prelinked
	libraries where prelinking info cannot be used.
	(sparc_fixup_plt): Renamed from elf_machine_fixup_plt.
	(elf_machine_fixup_plt): Call sparc_fixup_plt.
	(elf_machine_rela): Set value to 0 if relocating conflicts.
	Call sparc_fixup_plt for R_SPARC_JMP_SLOT.
	* sysdeps/sparc/sparc64/dl-machine.h (VALIDX): Define.
	(sparc64_fixup_plt): Fix a typo.
	(elf_machine_rela): Set value to 0 if relocating conflicts.
	Handle R_SPARC_JMP_SLOT relocs when relocating conflicts.
	(elf_machine_runtime_setup): Reinitialize .plt for prelinked
	libraries where prelinking info cannot be used.
	* sysdeps/sh/bits/link.h: New file.
	* sysdeps/sh/dl-machine.h (elf_machine_runtime_setup): Save original
	content of .got[1].
	(elf_machine_lazy_rel): Reinitialize R_SH_JMP_SLOT address instead
	of adjusting it if prelinked and prelinking cannot be used.
	* sysdeps/s390/s390-32/bits/link.h: New file.
	* sysdeps/s390/s390-32/dl-machine.h (elf_machine_runtime_setup):
	Save original content of .got[1].
	(elf_machine_lazy_rel): Reinitialize R_390_JMP_SLOT address instead
	of adjusting it if prelinked and prelinking cannot be used.
	* sysdeps/s390/s390-64/bits/link.h: New file.
	* sysdeps/s390/s390-64/dl-machine.h (elf_machine_runtime_setup):
	Save original content of .got[1].
	(elf_machine_lazy_rel): Reinitialize R_390_JMP_SLOT address instead
	of adjusting it if prelinked and prelinking cannot be used.
	* sysdeps/x86_64/bits/link.h: New file.
	* sysdeps/x86_64/dl-machine.h (elf_machine_runtime_setup):
	Save original content of .got[1].
	(elf_machine_lazy_rel): Reinitialize R_X86_64_JMP_SLOT address instead
	of adjusting it if prelinked and prelinking cannot be used.
Diffstat (limited to 'elf/dl-lookup.c')
-rw-r--r--elf/dl-lookup.c229
1 files changed, 134 insertions, 95 deletions
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 5fa50fc457..ae3f0b1e34 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -194,6 +194,12 @@ _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
 			 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,
+		    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);
 
 /* Search loaded objects' symbol tables for a definition of the symbol
    UNDEF_NAME.  */
@@ -204,7 +210,7 @@ _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)
 {
-  unsigned long int hash = _dl_elf_hash (undef_name);
+  const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { NULL, NULL };
   struct r_scope_elem **scope;
   int protected;
@@ -241,7 +247,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
       if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
 	/* We could find no value for a strong reference.  */
 	/* XXX We cannot translate the messages.  */
-	_dl_signal_cerror (0, (reference_name && reference_name[0]
+	_dl_signal_cerror (0, (reference_name[0]
 			       ? reference_name
 			       : (_dl_argv[0] ?: "<main program>")),
 			   N_("relocation error"),
@@ -251,25 +257,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
     }
 
   protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
-
-  if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
-    {
-      const char *reference_name = undef_map ? undef_map->l_name : NULL;
-
-      _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
-			(reference_name && reference_name[0]
-			 ? reference_name : (_dl_argv[0] ?: "<main program>")),
-			current_value.m->l_name[0]
-			? current_value.m->l_name : _dl_argv[0],
-			protected ? "protected" : "normal", undef_name);
-    }
-
-  if (__builtin_expect (protected == 0, 1))
-    {
-      *ref = current_value.s;
-      return LOOKUP_VALUE (current_value.m);
-    }
-  else
+  if (__builtin_expect (protected != 0, 0))
     {
       /* It is very tricky. We need to figure out what value to
          return for the protected symbol */
@@ -280,14 +268,20 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 			   0, NULL, ELF_RTYPE_CLASS_PLT))
 	  break;
 
-      if (protected_value.s == NULL || protected_value.m == undef_map)
+      if (protected_value.s != NULL && protected_value.m != undef_map)
 	{
-	  *ref = current_value.s;
-	  return LOOKUP_VALUE (current_value.m);
+	  current_value.s = *ref;
+	  current_value.m = undef_map;
 	}
-
-      return LOOKUP_VALUE (undef_map);
     }
+
+  if (__builtin_expect (_dl_debug_mask
+			& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
+    _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
+			&current_value, NULL, type_class, protected);
+
+  *ref = current_value.s;
+  return LOOKUP_VALUE (current_value.m);
 }
 
 
@@ -303,7 +297,6 @@ _dl_lookup_symbol_skip (const char *undef_name,
 			struct r_scope_elem *symbol_scope[],
 			struct link_map *skip_map)
 {
-  const char *reference_name = undef_map ? undef_map->l_name : NULL;
   const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { NULL, NULL };
   struct r_scope_elem **scope;
@@ -332,20 +325,7 @@ _dl_lookup_symbol_skip (const char *undef_name,
 
   protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
 
-  if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
-    _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
-		       (reference_name && reference_name[0]
-			? reference_name : (_dl_argv[0] ?: "<main program>")),
-		       current_value.m->l_name[0]
-		       ? current_value.m->l_name : _dl_argv[0],
-		       protected ? "protected" : "normal", undef_name);
-
-  if (__builtin_expect (protected == 0, 1))
-    {
-      *ref = current_value.s;
-      return LOOKUP_VALUE (current_value.m);
-    }
-  else
+  if (__builtin_expect (protected != 0, 0))
     {
       /* It is very tricky.  We need to figure out what value to
          return for the protected symbol.  */
@@ -359,14 +339,20 @@ _dl_lookup_symbol_skip (const char *undef_name,
 			     0, skip_map, ELF_RTYPE_CLASS_PLT))
 	    break;
 
-      if (protected_value.s == NULL || protected_value.m == undef_map)
+      if (protected_value.s != NULL && protected_value.m != undef_map)
 	{
-	  *ref = current_value.s;
-	  return LOOKUP_VALUE (current_value.m);
+	  current_value.s = *ref;
+	  current_value.m = undef_map;
 	}
-
-      return LOOKUP_VALUE (undef_map);
     }
+
+  if (__builtin_expect (_dl_debug_mask
+			& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
+    _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
+			&current_value, NULL, 0, protected);
+
+  *ref = current_value.s;
+  return LOOKUP_VALUE (current_value.m);
 }
 
 
@@ -383,7 +369,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 			     const struct r_found_version *version,
 			     int type_class, int explicit)
 {
-  unsigned long int hash = _dl_elf_hash (undef_name);
+  const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { NULL, NULL };
   struct r_scope_elem **scope;
   int protected;
@@ -423,7 +409,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 	  const char *reference_name = undef_map ? undef_map->l_name : NULL;
 
 	  /* XXX We cannot translate the message.  */
-	  _dl_signal_cerror (0, (reference_name && reference_name[0]
+	  _dl_signal_cerror (0, (reference_name[0]
 				 ? reference_name
 				 : (_dl_argv[0] ?: "<main program>")),
 			     N_("relocation error"),
@@ -447,7 +433,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 	  const char *reference_name = undef_map ? undef_map->l_name : NULL;
 
 	  /* XXX We cannot translate the message.  */
-	  _dl_signal_cerror (0, (reference_name && reference_name[0]
+	  _dl_signal_cerror (0, (reference_name[0]
 				 ? reference_name
 				 : (_dl_argv[0] ?: "<main program>")), NULL,
 			     make_string (undefined_msg, undef_name,
@@ -460,25 +446,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 
   protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
 
-  if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
-    {
-      const char *reference_name = undef_map ? undef_map->l_name : NULL;
-
-      _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
-			(reference_name && reference_name[0]
-			 ? reference_name : (_dl_argv[0] ?: "<main program>")),
-			current_value.m->l_name[0]
-			? current_value.m->l_name : _dl_argv[0],
-			protected ? "protected" : "normal",
-			undef_name, version->name);
-    }
-
-  if (__builtin_expect (protected == 0, 1))
-    {
-      *ref = current_value.s;
-      return LOOKUP_VALUE (current_value.m);
-    }
-  else
+  if (__builtin_expect (protected != 0, 0))
     {
       /* It is very tricky. We need to figure out what value to
          return for the protected symbol */
@@ -490,14 +458,20 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 				     ELF_RTYPE_CLASS_PLT))
 	  break;
 
-      if (protected_value.s == NULL || protected_value.m == undef_map)
+      if (protected_value.s != NULL && protected_value.m != undef_map)
 	{
-	  *ref = current_value.s;
-	  return LOOKUP_VALUE (current_value.m);
+	  current_value.s = *ref;
+	  current_value.m = undef_map;
 	}
-
-      return LOOKUP_VALUE (undef_map);
     }
+
+  if (__builtin_expect (_dl_debug_mask
+			& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
+    _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
+			&current_value, version, type_class, protected);
+
+  *ref = current_value.s;
+  return LOOKUP_VALUE (current_value.m);
 }
 
 
@@ -512,7 +486,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
 				  const struct r_found_version *version,
 				  struct link_map *skip_map)
 {
-  const char *reference_name = undef_map ? undef_map->l_name : NULL;
+  const char *reference_name = undef_map->l_name;
   const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { NULL, NULL };
   struct r_scope_elem **scope;
@@ -543,7 +517,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
 	  __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
 		     undef_name, len + 1);
 	  /* XXX We cannot translate the messages.  */
-	  _dl_signal_cerror (0, (reference_name && reference_name[0]
+	  _dl_signal_cerror (0, (reference_name[0]
 				 ? reference_name
 				 : (_dl_argv[0] ?: "<main program>")),
 			     NULL, buf);
@@ -554,21 +528,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
 
   protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
 
-  if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
-    _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
-		      (reference_name && reference_name[0]
-		       ? reference_name : (_dl_argv[0] ?: "<main program>")),
-		      current_value.m->l_name[0]
-		      ? current_value.m->l_name : _dl_argv[0],
-		      protected ? "protected" : "normal",
-		      undef_name, version->name);
-
-  if (__builtin_expect (protected == 0, 1))
-    {
-      *ref = current_value.s;
-      return LOOKUP_VALUE (current_value.m);
-    }
-  else
+  if (__builtin_expect (protected != 0, 0))
     {
       /* It is very tricky. We need to figure out what value to
          return for the protected symbol */
@@ -584,14 +544,20 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
 				       skip_map, ELF_RTYPE_CLASS_PLT))
 	    break;
 
-      if (protected_value.s == NULL || protected_value.m == undef_map)
+      if (protected_value.s != NULL && protected_value.m != undef_map)
 	{
-	  *ref = current_value.s;
-	  return LOOKUP_VALUE (current_value.m);
+	  current_value.s = *ref;
+	  current_value.m = undef_map;
 	}
-
-      return LOOKUP_VALUE (undef_map);
     }
+
+  if (__builtin_expect (_dl_debug_mask
+			& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
+    _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
+			&current_value, version, 0, protected);
+
+  *ref = current_value.s;
+  return LOOKUP_VALUE (current_value.m);
 }
 
 
@@ -615,6 +581,79 @@ _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)
+{
+  const char *reference_name = undef_map->l_name;
+
+  if (_dl_debug_mask & DL_DEBUG_BINDINGS)
+    {
+      _dl_debug_printf ("binding file %s to %s: %s symbol `%s'",
+			(reference_name[0]
+			 ? reference_name : (_dl_argv[0] ?: "<main program>")),
+			value->m->l_name[0] ? value->m->l_name : _dl_argv[0],
+			protected ? "protected" : "normal",
+			undef_name);
+      if (version)
+	_dl_debug_printf_c (" [%s]\n", version->name);
+      else
+	_dl_debug_printf_c ("\n");
+    }
+#ifdef SHARED
+  if (_dl_debug_mask & DL_DEBUG_PRELINK)
+    {
+      int conflict = 0;
+      struct sym_val val = { NULL, NULL };
+
+      if ((_dl_trace_prelink_map == NULL
+	   || _dl_trace_prelink_map == _dl_loaded)
+	  && undef_map != _dl_loaded)
+	{
+	  const unsigned long int hash = _dl_elf_hash (undef_name);
+
+	  if (version == 0)
+	    _dl_do_lookup (undef_name, hash, *ref, &val,
+			   undef_map->l_local_scope[0], 0, NULL, type_class);
+	  else
+	    _dl_do_lookup_versioned (undef_name, hash, *ref, &val,
+				     undef_map->l_local_scope[0], 0, version,
+				     NULL, type_class);
+
+	  if (val.s != value->s || val.m != value->m)
+	    conflict = 1;
+	}
+
+      if (conflict
+	  || _dl_trace_prelink_map == undef_map
+	  || _dl_trace_prelink_map == NULL)
+	{
+	  _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
+		      conflict ? "conflict" : "lookup",
+		      (int) sizeof (ElfW(Addr)) * 2, undef_map->l_map_start,
+		      (int) sizeof (ElfW(Addr)) * 2,
+		      ((ElfW(Addr)) *ref) - undef_map->l_map_start,
+		      (int) sizeof (ElfW(Addr)) * 2,
+		      (ElfW(Addr)) (value->s ? value->m->l_map_start : 0),
+		      (int) sizeof (ElfW(Addr)) * 2,
+		      (ElfW(Addr)) (value->s ? value->s->st_value : 0));
+
+	  if (conflict)
+	    _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
+			(int) sizeof (ElfW(Addr)) * 2,
+			(ElfW(Addr)) (val.s ? val.m->l_map_start : 0),
+			(int) sizeof (ElfW(Addr)) * 2,
+			(ElfW(Addr)) (val.s ? val.s->st_value : 0));
+
+	  _dl_printf ("/%x %s\n", type_class, undef_name);
+	}
+    }
+#endif
+}
+
 /* These are here so that we only inline do_lookup{,_versioned} in the common
    case, not everywhere.  */
 static int