about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-load.c4
-rw-r--r--elf/dl-lookup.c18
-rw-r--r--elf/dl-reloc.c4
-rw-r--r--elf/do-rel.h5
-rw-r--r--elf/link.h7
-rw-r--r--elf/rtld.c4
6 files changed, 22 insertions, 20 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index c48286f938..6cacd3e3b6 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -354,8 +354,8 @@ _dl_map_object (struct link_map *loader, const char *name,
 
 		if (zeroend > zeropage)
 		  /* Map the remaining zero pages in from the zero fill FD.  */
-		  mapat = mmap (zeropage, zeroend - zeropage,
-				prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
+		  mapat = mmap (zeropage, zeroend - zeropage, prot,
+				MAP_ANON|MAP_PRIVATE|MAP_FIXED|MAP_INHERIT,
 				_dl_zerofd, 0);
 	      }
 	  }
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 4d5d795ee5..ca0f03489d 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.  Don't use a PLT defn in UNDEF_MAP, since
-   that is the object making the reference.  */
+   the symbol UNDEF_NAME.  If NOSELF is nonzero, then *REF
+   cannot satisfy the reference itself; 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)
+		   const char *reference_name,
+		   int noself)
 {
   unsigned long int hash = elf_hash (undef_name);
   struct link_map *map;
@@ -57,7 +59,9 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
 	{
 	  const Elf32_Sym *sym = &symtab[symidx];
 
-	  if (sym->st_value == 0)
+	  if (sym->st_value == 0 || /* No value.  */
+	      sym->st_shndx == SHN_UNDEF || /* PLT entry.  */
+	      (noself && sym == *ref))	/* The reference can't define it.  */
 	    continue;
 
 	  switch (ELF32_ST_TYPE (sym->st_info))
@@ -71,12 +75,6 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
 	      continue;
 	    }
 
-	  if (sym->st_shndx == SHN_UNDEF)
-	    /* This is the same symbol we are looking for the value for.
-	       If it is a PLT entry, it will have a value of its own;
-	       but that is not what we are looking for.  */
-	      continue;
-
 	  if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
 	    /* Not the symbol we are looking for.  */
 	    continue;
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 7cbed389b8..7e4f4992a7 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -60,10 +60,10 @@ _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)
+    Elf32_Addr resolve (const Elf32_Sym **ref, Elf32_Addr r_offset)
       {
 	return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope,
-				  l->l_name);
+				  l->l_name, (*ref)->st_value == r_offset);
       }
 
     real_next = l->l_next;
diff --git a/elf/do-rel.h b/elf/do-rel.h
index acef25d3f8..9657bc2297 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -37,7 +37,8 @@ Cambridge, MA 02139, USA.  */
 static inline void
 elf_dynamic_do_rel (struct link_map *map,
 		    int reltag, int sztag, 
-		    Elf32_Addr (*resolve) (const Elf32_Sym **),
+		    Elf32_Addr (*resolve) (const Elf32_Sym **symbol,
+					   Elf32_Addr r_offset),
 		    int lazy)
 {
   const Elf32_Sym *const symtab
@@ -61,7 +62,7 @@ elf_dynamic_do_rel (struct link_map *map,
 	else
 	  {
 	    if (resolve)
-	      loadbase = (*resolve) (&definer);
+	      loadbase = (*resolve) (&definer, r->r_offset);
 	    else
 	      {
 		assert (definer->st_shndx != SHN_UNDEF);
diff --git a/elf/link.h b/elf/link.h
index 66de6d97d7..6f44a0cfdb 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -173,11 +173,14 @@ 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.  */
+   containing the reference; it is used in error messages.  If NOSELF is
+   nonzero, them *SYM itself cannot define the value; another binding must
+   be found.  */
 extern Elf32_Addr _dl_lookup_symbol (const char *undef,
 				     const Elf32_Sym **sym,
 				     struct link_map *symbol_scope,
-				     const char *reference_name);
+				     const char *reference_name,
+				     int noself);
 
 
 /* List of objects currently loaded.  */
diff --git a/elf/rtld.c b/elf/rtld.c
index 7855c59052..ac14c45a98 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -258,8 +258,8 @@ of this helper program; chances are you did not intend to run this program.\n",
     _dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
 		      ": error in loading shared libraries\n",
 		      errobj ?: "", errobj ? ": " : "",
-		      errstring, err ? ": " : NULL,
-		      err ? strerror (err) : NULL, NULL);
+		      errstring, err ? ": " : "",
+		      err ? strerror (err) : "", "\n", NULL);
 
   /* Once we return, _dl_sysdep_start will invoke
      the DT_INIT functions and then *USER_ENTRY.  */