about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-lookup.c7
-rw-r--r--elf/dl-reloc.c5
-rw-r--r--elf/dl-runtime.c31
-rw-r--r--elf/dlfcn.h18
-rw-r--r--elf/dlopen.c4
-rw-r--r--elf/do-rel.h25
-rw-r--r--elf/link.h7
-rw-r--r--elf/rtld.c2
8 files changed, 34 insertions, 65 deletions
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 90c9b6a18d..b72a6a27d5 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -23,13 +23,15 @@ Cambridge, MA 02139, USA.  */
 #include <assert.h>
 
 /* Search loaded objects' symbol tables for a definition of the symbol
-   UNDEF_NAME.  If NOPLT is nonzero, then a PLT entry cannot satisfy the
-   reference; some different binding must be found.  */
+   UNDEF_NAME.  The chosen value can't be RELOC_ADDR.  If NOPLT is nonzero,
+   then a PLT entry cannot satisfy the reference; some different binding
+   must be found.  */
 
 Elf32_Addr
 _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
 		   struct link_map *symbol_scope,
 		   const char *reference_name,
+		   Elf32_Addr reloc_addr,
 		   int noplt)
 {
   unsigned long int hash = elf_hash (undef_name);
@@ -59,6 +61,7 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
 	  const Elf32_Sym *sym = &symtab[symidx];
 
 	  if (sym->st_value == 0 || /* No value.  */
+	      reloc_addr == map->l_addr + sym->st_value || /* Self ref.  */
 	      (noplt && sym->st_shndx == SHN_UNDEF)) /* Unwanted PLT entry.  */
 	    continue;
 
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 46fc4c4def..424d303800 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -60,10 +60,11 @@ _dl_relocate_object (struct link_map *l, int lazy)
       = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
 
 
-    Elf32_Addr resolve (const Elf32_Sym **ref, int noplt)
+    Elf32_Addr resolve (const Elf32_Sym **ref,
+			Elf32_Addr reloc_addr, int noplt)
       {
 	return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope,
-				  l->l_name, noplt);
+				  l->l_name, reloc_addr, noplt);
       }
 
     real_next = l->l_next;
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 941a306df9..0beba769fa 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -67,34 +67,15 @@ fixup (
     = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
 		      reloc_offset);
 
-  const Elf32_Sym *definer;
-  Elf32_Addr loadbase;
-  struct link_map *scope, *real_next;
-
-  /* Look up the symbol's run-time value.  */
-
-  real_next = l->l_next;
-  if (l->l_info[DT_SYMBOLIC])
+  Elf32_Addr resolve (const Elf32_Sym **ref,
+		      Elf32_Addr reloc_addr, int noplt)
     {
-      l->l_next = _dl_loaded;
-      if (l->l_prev)
-	l->l_prev->l_next = real_next;
-      scope = l;
+      return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, _dl_loaded,
+				l->l_name, reloc_addr, noplt);
     }
-  else
-    scope = _dl_loaded;
-
-  definer = &symtab[ELF32_R_SYM (reloc->r_info)];
-  loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,
-				scope, l->l_name, 1);
-
-  /* Restore list frobnication done above for DT_SYMBOLIC.  */
-  l->l_next = real_next;
-  if (l->l_prev)
-    l->l_prev->l_next = l;
 
-  /* Apply the relocation with that value.  */
-  elf_machine_relplt (l, reloc, loadbase, definer);
+  /* Perform the specified relocation.  */
+  elf_machine_relplt (l, reloc, &symtab[ELF32_R_SYM (reloc->r_info)], resolve);
 
   return *(Elf32_Addr *) (l->l_addr + reloc->r_offset);
 }
diff --git a/elf/dlfcn.h b/elf/dlfcn.h
index e5d68f82be..a405baa473 100644
--- a/elf/dlfcn.h
+++ b/elf/dlfcn.h
@@ -1,5 +1,5 @@
 /* dlfcn.h -- User functions for run-time dynamic loading.
-Copyright (C) 1995 Free Software Foundation, Inc.
+Copyright (C) 1995, 1996 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
@@ -21,16 +21,18 @@ Cambridge, MA 02139, USA.  */
 #define	_DLFCN_H 1
 
 
-/* Type of the second argument to `dlopen'.  */
-typedef enum
-  {
-    RTLD_LAZY =       1,	/* Lazy function call binding.  */
-    RTLD_NOW =        2		/* Immediate function call binding.  */
-  } dl_open_mode;
+/* The MODE argument to `dlopen' contains one of the following: */
+#define RTLD_LAZY	0x001	/* Lazy function call binding.  */
+#define RTLD_NOW	0x002	/* Immediate function call binding.  */
+
+/* If the following bit is set in the MODE argument to `dlopen',
+   the symbols of the loaded object and its dependencies are made
+   visible as if the object were linked directly into the program.  */
+#define RTLD_GLOBAL	0x100
 
 /* Open the shared object FILE and map it in; return a handle that can be
    passed to `dlsym' to get symbol values from it.  */
-extern void *dlopen (const char *__file, dl_open_mode);
+extern void *dlopen (const char *__file, int __mode);
 
 /* Unmap and close a shared object opened by `dlopen'.
    The handle cannot be used again after calling `dlclose'.  */
diff --git a/elf/dlopen.c b/elf/dlopen.c
index de65a20d97..26ed35ace6 100644
--- a/elf/dlopen.c
+++ b/elf/dlopen.c
@@ -1,5 +1,5 @@
 /* dlopen -- Load a shared object at run time.
-Copyright (C) 1995 Free Software Foundation, Inc.
+Copyright (C) 1995, 1996 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
@@ -22,7 +22,7 @@ Cambridge, MA 02139, USA.  */
 #include <dlfcn.h>
 
 void *
-dlopen (const char *file, dl_open_mode mode)
+dlopen (const char *file, int mode)
 {
   struct link_map *new, *l;
 
diff --git a/elf/do-rel.h b/elf/do-rel.h
index a265550cae..438613a32d 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -38,7 +38,7 @@ static inline void
 elf_dynamic_do_rel (struct link_map *map,
 		    int reltag, int sztag,
 		    Elf32_Addr (*resolve) (const Elf32_Sym **symbol,
-					   int noplt),
+					   Elf32_Addr reloc_addr, int noplt),
 		    int lazy)
 {
   const Elf32_Sym *const symtab
@@ -53,28 +53,7 @@ elf_dynamic_do_rel (struct link_map *map,
       elf_machine_lazy_rel (map, r);
   else
     for (; r < end; ++r)
-      {
-	const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)];
-	Elf32_Addr loadbase;
-
-	if (ELF32_R_SYM (r->r_info) == STN_UNDEF)
-	  loadbase = 0;		/* This value will not be consulted.  */
-	else if (ELF32_ST_BIND (definer->st_info) == STB_LOCAL)
-	  /* Local symbols always refer to the containing object.  */
-	  loadbase = map->l_addr;
-	else
-	  {
-	    if (resolve)
-	      loadbase = (*resolve)
-		(&definer, elf_machine_pltrel_p (ELF32_R_TYPE (r->r_info)));
-	    else
-	      {
-		assert (definer->st_shndx != SHN_UNDEF);
-		loadbase = map->l_addr;
-	      }
-	  }
-	elf_machine_rel (map, r, loadbase, definer);
-      }
+      elf_machine_rel (map, r, &symtab[ELF32_R_SYM (r->r_info)], resolve);
 }
 
 #undef elf_dynamic_do_rel
diff --git a/elf/link.h b/elf/link.h
index cd75263e0a..a19a2ce0b3 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -185,12 +185,15 @@ extern void _dl_setup_hash (struct link_map *map);
    reference; it is replaced with the defining symbol, and the base load
    address of the defining object is returned.  SYMBOL_SCOPE is the head of
    the chain used for searching.  REFERENCE_NAME should name the object
-   containing the reference; it is used in error messages.  If NOPLT is
-   nonzero, then the reference must not be resolved to a PLT entry.  */
+   containing the reference; it is used in error messages.  RELOC_ADDR is
+   the address being fixed up and the chosen symbol cannot be one with this
+   value.  If NOPLT is nonzero, then the reference must not be resolved to
+   a PLT entry.  */
 extern Elf32_Addr _dl_lookup_symbol (const char *undef,
 				     const Elf32_Sym **sym,
 				     struct link_map *symbol_scope,
 				     const char *reference_name,
+				     Elf32_Addr reloc_addr,
 				     int noplt);
 
 
diff --git a/elf/rtld.c b/elf/rtld.c
index 157cde51d9..511d19cb15 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -318,7 +318,7 @@ of this helper program; chances are you did not intend to run this program.\n",
 	  const Elf32_Sym *ref = NULL;
 	  Elf32_Addr loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
 						   _dl_loaded, "argument",
-						   0);
+						   0, 0);
 	  char buf[20], *bp;
 	  buf[sizeof buf - 1] = '\0';
 	  bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);