summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog48
-rw-r--r--elf/dl-addr.c6
-rw-r--r--elf/dl-deps.c3
-rw-r--r--elf/dl-load.c14
-rw-r--r--elf/dl-lookup.c4
-rw-r--r--elf/dl-reloc.c4
-rw-r--r--elf/dl-runtime.c26
-rw-r--r--elf/dl-version.c23
-rw-r--r--elf/do-rel.h11
-rw-r--r--elf/dynamic-link.h113
-rw-r--r--elf/rtld.c14
-rw-r--r--grp/initgroups.c5
-rw-r--r--sysdeps/alpha/dl-machine.h8
-rw-r--r--sysdeps/arm/dl-machine.h9
-rw-r--r--sysdeps/i386/dl-machine.h7
-rw-r--r--sysdeps/m68k/dl-machine.h5
-rw-r--r--sysdeps/mips/dl-machine.h12
-rw-r--r--sysdeps/powerpc/dl-machine.c5
-rw-r--r--sysdeps/sparc/sparc32/dl-machine.h5
-rw-r--r--sysdeps/sparc/sparc64/dl-machine.h5
20 files changed, 198 insertions, 129 deletions
diff --git a/ChangeLog b/ChangeLog
index cc94e947cf..dfc4d0da81 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,53 @@
 1999-02-20  Ulrich Drepper  <drepper@cygnus.com>
 
+	* elf/dynamic-link.h (elf_get_dynamic_info): Take new argument with
+	load address.  Relocate d_ptr in DT_DTRTAB, DT_SYMTAB, DT_RELA, DT_REL,
+	DT_JMPREL, DT_PLTGOT, and DT_VERSYM l_info entry.
+	(_ELF_DYNAMIC_DO_RELOC): Take extra argument which specifies whether
+	rel and rela relocations can both happen and skip one test if this
+	is not possible.
+	(ELF_DYNAMIC_DO_RELA, ELF_DYNAMIC_DO_REL): Call _ELF_DYNAMIC_DO_RELOC
+	appropriately.
+	* elf/dl-addr.c (_dl_addr): DT_SYMTAB and DT_STRTAB entries are
+	already relocated.
+	* elf/dl-deps.c (_dl_map_object_deps): DT_STRTAB entry is already
+	relocated.
+	* elf/dl-load.c (_dl_init_paths): DT_STRTAB entry is already relocated.
+	(_dl_map_object_from_fd): Call elf_get_dynamic_info with new argument.
+	(_dl_map_object): DT_STRTAB entry is already relocated.
+	* elf/dl-lookup.c (do_lookup): DT_STRTAB and DT_SYMTAB entries are
+	already relocated.
+	* elf/dl-reloc.c (_dl_relocate_object): DT_STRTAB entry is already
+	relocated.
+	* elf/dl-runtime.c (fixup): DT_SYMTAB, DT_STRTAB, DT_JMPREL, and
+	DT_VERSYM entries are already relocated.
+	(profile_fixup): Likewise.
+	* elf/dl-version.c: Rename VERSTAG macro into VERSYMIDX.  Replace
+	all users.
+	(match_symbol): DT_STRTAB entry is already relocated.
+	(_dl_check_map_versions): Likewise.  Also fo DT_VERSYM.
+	* elf/do-rel.h (elf_dynamic_do_rel): reladdr is now assumed to be
+	relocated already.  DT_SYMTAB and DT_VERSYM entries are also relocated.
+	* elf/rtld.c (_dl_start): Pass extra argument to elf_get_dynamic_info.
+	(find_needed): DT_STRTAB entry is already relocated.
+	(dl_main): Pass extra argument to elf_get_dynamic_info.
+	DT_STRTAB entry is already relocated.
+	* sysdeps/alpha/dl-machine.h (elf_machine_fixup_plt): DT_JMPREL and
+	DT_PLTGOT entries are already relocated.
+	(elf_machine_rela): Likewise for DT_SYMTAB.
+	* sysdeps/arm/dl-machine.h (elf_machine_rel): DT_STRTAB is already
+	relocated.
+	* sysdeps/i386/dl-machine.h (elf_machine_rel): Likewise.
+	* sysdeps/m68k/dl-machine.h (elf_machine_rela): Likewise.
+	* sysdeps/sparc/sparc32/dl-machine.h (elf_machine_rela): Likewise.
+	* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_rela): Likewise.
+	* sysdeps/powerpc/dl-machine.c (__process_machine_rela): Likewise.
+	* sysdeps/mips/dl-machine.h (elf_machine_got_rel): Likewise.
+	(elf_machine_got_rel): Likewise for DT_SYMTAB and DT_STRTAB.
+
+	* grp/initgroups.c (initgroups): If function in current module was
+	successful don't stop but continue to process to get all the groups.
+
 	* elf/dl-load.c (_dl_map_object_from_fd): Use global
 	_dl_pf_to_proot array to convert p_flags value.
 	* elf/dl-reloc.c (_dl_relocate_object): Likewise.
diff --git a/elf/dl-addr.c b/elf/dl-addr.c
index 2c9a9dd84e..14bff06f13 100644
--- a/elf/dl-addr.c
+++ b/elf/dl-addr.c
@@ -1,5 +1,5 @@
 /* Locate the shared object symbol nearest a given address.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999 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
@@ -62,8 +62,8 @@ _dl_addr (const void *address, Dl_info *info)
   info->dli_fname = match->l_name;
   info->dli_fbase = (void *) match->l_addr;
 
-  symtab = ((void *) match->l_addr + match->l_info[DT_SYMTAB]->d_un.d_ptr);
-  strtab = ((void *) match->l_addr + match->l_info[DT_STRTAB]->d_un.d_ptr);
+  symtab = (const void *) match->l_info[DT_SYMTAB]->d_un.d_ptr;
+  strtab = (const void *) match->l_info[DT_STRTAB]->d_un.d_ptr;
 
   /* We assume that the string table follows the symbol table, because
      there is no way in ELF to know the size of the dynamic symbol table!!  */
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 355618ad1c..ca0d9322ba 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -149,8 +149,7 @@ _dl_map_object_deps (struct link_map *map,
 
       if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
 	{
-	  const char *strtab = ((void *) l->l_addr
-				+ l->l_info[DT_STRTAB]->d_un.d_ptr);
+	  const char *strtab = (const void *) l->l_info[DT_STRTAB]->d_un.d_ptr;
 	  struct openaux_args args;
 	  struct list *orig;
 	  const ElfW(Dyn) *d;
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 3de1dca573..345b97f099 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -531,9 +531,9 @@ _dl_init_paths (const char *llp)
 	/* Allocate room for the search path and fill in information
 	   from RPATH.  */
 	l->l_rpath_dirs =
-	  decompose_rpath ((const char *)
-			   (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr
-			    + l->l_info[DT_RPATH]->d_un.d_val), l);
+	  decompose_rpath ((const void *) (l->l_info[DT_STRTAB]->d_un.d_ptr
+					   + l->l_info[DT_RPATH]->d_un.d_val),
+			   l);
       else
 	l->l_rpath_dirs = NULL;
     }
@@ -983,7 +983,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
 			 "  phnum:   ", buf3, "\n\n", NULL);
     }
 
-  elf_get_dynamic_info (l->l_ld, l->l_info);
+  elf_get_dynamic_info (l->l_ld, l->l_addr, l->l_info);
   if (l->l_info[DT_HASH])
     _dl_setup_hash (l);
 
@@ -1208,8 +1208,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 	  if (l->l_info[DT_SONAME] == NULL)
 	    continue;
 
-	  soname = (const char *) (l->l_addr
-				   + l->l_info[DT_STRTAB]->d_un.d_ptr
+	  soname = (const void *) (l->l_info[DT_STRTAB]->d_un.d_ptr
 				   + l->l_info[DT_SONAME]->d_un.d_val);
 	  if (strcmp (name, soname) != 0)
 	    continue;
@@ -1248,8 +1247,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 	    /* Make sure the cache information is available.  */
 	    if (l->l_rpath_dirs == NULL)
 	      {
-		size_t ptrval = (l->l_addr
-				 + l->l_info[DT_STRTAB]->d_un.d_ptr
+		size_t ptrval = (l->l_info[DT_STRTAB]->d_un.d_ptr
 				 + l->l_info[DT_RPATH]->d_un.d_val);
 		l->l_rpath_dirs =
 		  decompose_rpath ((const char *) ptrval, l);
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index ef953c5475..de5ecf5d62 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -110,8 +110,8 @@ do_lookup (const char *undef_name, unsigned long int hash,
 			   map->l_name[0] ? map->l_name : _dl_argv[0],
 			   "\n", NULL);
 
-      symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
-      strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
+      symtab = (const void *) map->l_info[DT_SYMTAB]->d_un.d_ptr;
+      strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
       verstab = map->l_versyms;
 
       /* Search the appropriate hash bucket in this object's symbol table
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index be860af940..54a2acc065 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -66,8 +66,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
   {
     /* Do the actual relocation of the object's GOT and other data.  */
 
-    const char *strtab		/* String table object symbols.  */
-      = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
+    /* String table object symbols.  */
+    const char *strtab = (const void *) l->l_info[DT_STRTAB]->d_un.d_ptr;
 
     /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
 #define RESOLVE(ref, version, flags) \
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 91700c2764..a0f54bd3fc 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -1,5 +1,5 @@
 /* On-demand PLT fixup for shared objects.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -48,13 +48,11 @@ fixup (
        struct link_map *l, ElfW(Word) reloc_offset)
 {
   const ElfW(Sym) *const symtab
-    = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
-  const char *strtab =
-    (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
+    = (const void *) l->l_info[DT_SYMTAB]->d_un.d_ptr;
+  const char *strtab = (const void *) l->l_info[DT_STRTAB]->d_un.d_ptr;
 
   const PLTREL *const reloc
-    = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
-		      reloc_offset);
+    = (const void *) (l->l_info[DT_JMPREL]->d_un.d_ptr + reloc_offset);
   const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
   void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
   ElfW(Addr) value;
@@ -67,8 +65,8 @@ fixup (
     {
     default:
       {
-	const ElfW(Half) *vernum = (const ElfW(Half) *)
-	  (l->l_addr + l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
+	const ElfW(Half) *vernum =
+	  (const void *) l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
 	ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
 	const struct r_found_version *version = &l->l_versions[ndx];
 
@@ -121,13 +119,11 @@ profile_fixup (
     {
       /* This is the first time we have to relocate this object.  */
       const ElfW(Sym) *const symtab
-	= (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
-      const char *strtab =
-	(const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
+	= (const void *) l->l_info[DT_SYMTAB]->d_un.d_ptr;
+      const char *strtab = (const void *) l->l_info[DT_STRTAB]->d_un.d_ptr;
 
       const PLTREL *const reloc
-	= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
-			  reloc_offset);
+	= (const void *) (l->l_info[DT_JMPREL]->d_un.d_ptr + reloc_offset);
       const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
 
       /* Sanity check that we're really looking at a PLT relocation.  */
@@ -138,8 +134,8 @@ profile_fixup (
 	{
 	default:
 	  {
-	    const ElfW(Half) *vernum = (const ElfW(Half) *)
-	      (l->l_addr + l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
+	    const ElfW(Half) *vernum =
+	      (const void *) l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
 	    ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
 	    const struct r_found_version *version = &l->l_versions[ndx];
 
diff --git a/elf/dl-version.c b/elf/dl-version.c
index 4ba7f1ab3a..fbc41654ef 100644
--- a/elf/dl-version.c
+++ b/elf/dl-version.c
@@ -1,5 +1,5 @@
 /* Handle symbol and library versioning.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -28,7 +28,9 @@
 #include <assert.h>
 
 
-#define VERSTAG(tag)	(DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
+#ifndef VERSYMIDX
+# define VERSYMIDX(tag)	(DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
+#endif
 
 
 #define make_string(string, rest...) \
@@ -75,8 +77,7 @@ internal_function
 match_symbol (const char *name, ElfW(Word) hash, const char *string,
 	      struct link_map *map, int verbose, int weak)
 {
-  const char *strtab = (const char *) (map->l_addr
-				       + map->l_info[DT_STRTAB]->d_un.d_ptr);
+  const char *strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
   ElfW(Addr) def_offset;
   ElfW(Verdef) *def;
 
@@ -86,7 +87,7 @@ match_symbol (const char *name, ElfW(Word) hash, const char *string,
 		       map->l_name[0] ? map->l_name : _dl_argv[0],
 		       " required by file ", name, "\n", NULL);
 
-  if (map->l_info[VERSTAG (DT_VERDEF)] == NULL)
+  if (map->l_info[VERSYMIDX (DT_VERDEF)] == NULL)
     {
       /* The file has no symbol versioning.  I.e., the dependent
 	 object was linked against another version of this file.  We
@@ -98,7 +99,7 @@ no version information available (required by ",
       return 0;
     }
 
-  def_offset = map->l_info[VERSTAG (DT_VERDEF)]->d_un.d_ptr;
+  def_offset = map->l_info[VERSYMIDX (DT_VERDEF)]->d_un.d_ptr;
   assert (def_offset != 0);
 
   def = (ElfW(Verdef) *) ((char *) map->l_addr + def_offset);
@@ -173,10 +174,10 @@ _dl_check_map_versions (struct link_map *map, int verbose)
   /* If we don't have a string table, we must be ok.  */
   if (map->l_info[DT_STRTAB] == NULL)
     return 0;
-  strtab = (const char *) (map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
+  strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 
-  dyn = map->l_info[VERSTAG (DT_VERNEED)];
-  def = map->l_info[VERSTAG (DT_VERDEF)];
+  dyn = map->l_info[VERSYMIDX (DT_VERNEED)];
+  def = map->l_info[VERSYMIDX (DT_VERDEF)];
 
   if (dyn != NULL)
     {
@@ -282,8 +283,8 @@ _dl_check_map_versions (struct link_map *map, int verbose)
 	  map->l_nversions = ndx_high + 1;
 
 	  /* Compute the pointer to the version symbols.  */
-	  map->l_versyms = ((void *) map->l_addr
-			    + map->l_info[VERSTAG (DT_VERSYM)]->d_un.d_ptr);
+	  map->l_versyms =
+	    (void *) map->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
 
 	  if (dyn != NULL)
 	    {
diff --git a/elf/do-rel.h b/elf/do-rel.h
index c0f48241bf..803d250bba 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -1,5 +1,5 @@
 /* Do relocations for ELF dynamic linking.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -40,8 +40,8 @@ elf_dynamic_do_rel (struct link_map *map,
 		    ElfW(Addr) reladdr, ElfW(Addr) relsize,
 		    int lazy)
 {
-  const ElfW(Rel) *r = (const ElfW(Rel) *)(map->l_addr + reladdr);
-  const ElfW(Rel) *end = (const ElfW(Rel) *)(map->l_addr + reladdr + relsize);
+  const ElfW(Rel) *r = (const void *) reladdr;
+  const ElfW(Rel) *end = (const void *) (reladdr + relsize);
 
   if (lazy)
     {
@@ -53,13 +53,12 @@ elf_dynamic_do_rel (struct link_map *map,
   else
     {
       const ElfW(Sym) *const symtab =
-	(const ElfW(Sym) *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
+	(const void *) map->l_info[DT_SYMTAB]->d_un.d_ptr;
 
       if (map->l_info[VERSYMIDX (DT_VERSYM)])
 	{
 	  const ElfW(Half) *const version =
-	    (const ElfW(Half) *) (map->l_addr
-				  + map->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
+	    (const void *) map->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
 
 	  for (; r < end; ++r)
 	    {
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index 3d96ecc143..d322c1231f 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -21,6 +21,10 @@
 #include <dl-machine.h>
 #include <assert.h>
 
+#ifndef VERSYMIDX
+# define VERSYMIDX(sym)	(DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (sym))
+#endif
+
 
 /* Global read-only variable defined in rtld.c which is nonzero if we
    shall give more warning messages.  */
@@ -30,13 +34,10 @@ extern int _dl_verbose __attribute__ ((unused));
 /* Read the dynamic section at DYN and fill in INFO with indices DT_*.  */
 
 static inline void __attribute__ ((unused))
-elf_get_dynamic_info (ElfW(Dyn) *dyn,
+elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Addr) l_addr,
 		      ElfW(Dyn) *info[DT_NUM + DT_PROCNUM + DT_VERSIONTAGNUM
 				     + DT_EXTRANUM])
 {
-  memset (info, '\0', ((DT_NUM + DT_PROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM)
-		       * sizeof (ElfW(Dyn) *)));
-
   if (! dyn)
     return;
 
@@ -48,7 +49,7 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
 	       dyn->d_tag < DT_LOPROC + DT_PROCNUM)
 	info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
       else if ((Elf32_Word) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
-	info[DT_VERSIONTAGIDX (dyn->d_tag) + DT_NUM + DT_PROCNUM] = dyn;
+	info[VERSYMIDX (dyn->d_tag)] = dyn;
       else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
 	info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_PROCNUM
 	     + DT_VERSIONTAGNUM] = dyn;
@@ -57,13 +58,41 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
       ++dyn;
     }
 
-  if (info[DT_RELA])
-    assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
-  if (info[DT_REL])
-    assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
-  if (info[DT_PLTREL])
-    assert (info[DT_PLTREL]->d_un.d_val == DT_REL ||
-	    info[DT_PLTREL]->d_un.d_val == DT_RELA);
+  if (info[DT_PLTGOT] != NULL)
+    info[DT_PLTGOT]->d_un.d_ptr += l_addr;
+  if (info[DT_STRTAB] != NULL)
+    info[DT_STRTAB]->d_un.d_ptr += l_addr;
+  if (info[DT_SYMTAB] != NULL)
+    info[DT_SYMTAB]->d_un.d_ptr += l_addr;
+#if ! ELF_MACHINE_NO_RELA
+  if (info[DT_RELA] != NULL)
+    {
+      assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
+      info[DT_RELA]->d_un.d_ptr += l_addr;
+    }
+#endif
+#if ! ELF_MACHINE_NO_REL
+  if (info[DT_REL] != NULL)
+    {
+      assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
+      info[DT_REL]->d_un.d_ptr += l_addr;
+    }
+#endif
+  if (info[DT_PLTREL] != NULL)
+    {
+#if ELF_MACHINE_NO_RELA
+      assert (info[DT_PLTREL]->d_un.d_val == DT_REL);
+#elif ELF_MACHINE_NO_REL
+      assert (info[DT_PLTREL]->d_un.d_val == DT_RELA);
+#else
+      assert (info[DT_PLTREL]->d_un.d_val == DT_REL
+	      || info[DT_PLTREL]->d_un.d_val == DT_RELA);
+#endif
+    }
+  if (info[DT_JMPREL] != NULL)
+    info[DT_JMPREL]->d_un.d_ptr += l_addr;
+  if (info[VERSYMIDX (DT_VERSYM)] != NULL)
+    info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr += l_addr;
 }
 
 #ifdef RESOLVE
@@ -73,13 +102,13 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
    duplicating their code.  It cannot be done in a more general function
    because we must be able to completely inline.  */
 
-/* On some machines, notably Sparc, DT_REL* includes DT_JMPREL in its
+/* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
    range.  Note that according to the ELF spec, this is completely legal!
    But conditionally define things so that on machines we know this will
    not happen we do something more optimal.  */
 
-#ifdef ELF_MACHINE_PLTREL_OVERLAP
-#define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy) \
+# ifdef ELF_MACHINE_PLTREL_OVERLAP
+#  define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
   do {									      \
     struct { ElfW(Addr) start, size; int lazy; } ranges[3];		      \
     int ranges_index;							      \
@@ -96,7 +125,7 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
 									      \
      if ((do_lazy)							      \
 	&& (map)->l_info[DT_PLTREL]					      \
-	&& (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)		      \
+	&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
       {									      \
 	ranges[1].start = (map)->l_info[DT_JMPREL]->d_un.d_ptr;		      \
 	ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val;	      \
@@ -111,8 +140,8 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
 			      ranges[ranges_index].size,		      \
 			      ranges[ranges_index].lazy);		      \
   } while (0)
-#else
-#define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy) \
+# else
+#  define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
   do {									      \
     struct { ElfW(Addr) start, size; int lazy; } ranges[2];		      \
     int ranges_index;							      \
@@ -125,8 +154,8 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
         ranges[0].start = (map)->l_info[DT_##RELOC]->d_un.d_ptr;	      \
         ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val;	      \
       }									      \
-    if ((map)->l_info[DT_PLTREL] &&					      \
-	(map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)		      \
+    if ((map)->l_info[DT_PLTREL]					      \
+	&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
       {									      \
 	ElfW(Addr) start = (map)->l_info[DT_JMPREL]->d_un.d_ptr;	      \
 									      \
@@ -151,28 +180,34 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
 			      ranges[ranges_index].size,		      \
 			      ranges[ranges_index].lazy);		      \
   } while (0)
-#endif
-
-#if ! ELF_MACHINE_NO_REL
-#include "do-rel.h"
-#define ELF_DYNAMIC_DO_REL(map, lazy) \
-  _ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy)
-#else
-#define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do.  */
-#endif
-
-#if ! ELF_MACHINE_NO_RELA
-#define DO_RELA
-#include "do-rel.h"
-#define ELF_DYNAMIC_DO_RELA(map, lazy) \
-  _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy)
-#else
-#define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do.  */
-#endif
+# endif
+
+# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
+#  define _ELF_CHECK_REL 0
+# else
+#  define _ELF_CHECK_REL 1
+# endif
+
+# if ! ELF_MACHINE_NO_REL
+#  include "do-rel.h"
+#  define ELF_DYNAMIC_DO_REL(map, lazy) \
+  _ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, _ELF_CHECK_REL)
+# else
+#  define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do.  */
+# endif
+
+# if ! ELF_MACHINE_NO_RELA
+#  define DO_RELA
+#  include "do-rel.h"
+#  define ELF_DYNAMIC_DO_RELA(map, lazy) \
+  _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, _ELF_CHECK_REL)
+# else
+#  define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do.  */
+# endif
 
 /* This can't just be an inline function because GCC is too dumb
    to inline functions containing inlines themselves.  */
-#define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
+# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
   do {									      \
     int edr_lazy = elf_machine_runtime_setup ((map), (lazy),		      \
 					      (consider_profile));	      \
diff --git a/elf/rtld.c b/elf/rtld.c
index 6aa3a65fbb..762cdc5ff2 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1,5 +1,5 @@
 /* Run time dynamic linker.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -156,7 +156,8 @@ _dl_start (void *arg)
 
   /* Read our own dynamic section and fill in the info array.  */
   bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic ();
-  elf_get_dynamic_info (bootstrap_map.l_ld, bootstrap_map.l_info);
+  elf_get_dynamic_info (bootstrap_map.l_ld, bootstrap_map.l_addr,
+			bootstrap_map.l_info);
 
 #ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
   ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
@@ -290,8 +291,7 @@ find_needed (const char *name)
 static int
 match_version (const char *string, struct link_map *map)
 {
-  const char *strtab = (const char *) (map->l_addr
-				       + map->l_info[DT_STRTAB]->d_un.d_ptr);
+  const char *strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
   ElfW(Verdef) *def;
 
 #define VERDEFTAG (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (DT_VERDEF))
@@ -575,7 +575,8 @@ of this helper program; chances are you did not intend to run this program.\n\
     assert (_dl_rtld_map.l_libname); /* How else did we get here?  */
 
   /* Extract the contents of the dynamic section for easy access.  */
-  elf_get_dynamic_info (_dl_loaded->l_ld, _dl_loaded->l_info);
+  elf_get_dynamic_info (_dl_loaded->l_ld, _dl_loaded->l_addr,
+			_dl_loaded->l_info);
   if (_dl_loaded->l_info[DT_HASH])
     /* Set up our cache of pointers into the hash table.  */
     _dl_setup_hash (_dl_loaded);
@@ -889,8 +890,7 @@ of this helper program; chances are you did not intend to run this program.\n\
 		  if (dyn == NULL)
 		    continue;
 
-		  strtab = (const char *)
-		    (map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
+		  strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 		  ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
 
 		  if (first)
diff --git a/grp/initgroups.c b/grp/initgroups.c
index b7708077b6..93f78eb547 100644
--- a/grp/initgroups.c
+++ b/grp/initgroups.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 91, 93, 96, 97, 98 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 91, 93, 96, 97, 98, 99 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
@@ -198,7 +198,8 @@ initgroups (user, group)
       if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
 	 __libc_fatal ("illegal status in " __FUNCTION__);
 
-      if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
+      if (status != NSS_STATUS_SUCCESS
+	  && nss_next_action (nip, status) == NSS_ACTION_RETURN)
 	 break;
 
       if (nip->next == NULL)
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index d351e9dccc..6e11380774 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  Alpha version.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
@@ -350,8 +350,8 @@ elf_machine_fixup_plt(struct link_map *l, const Elf64_Rela *reloc,
 
   /* Recover the PLT entry address by calculating reloc's index into the
      .rela.plt, and finding that entry in the .plt.  */
-  rela_plt = (void *)(l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr);
-  plte = (void *)(l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr + 32);
+  rela_plt = (void *) l->l_info[DT_JMPREL]->d_un.d_ptr;
+  plte = (void *) (l->l_info[DT_PLTGOT]->d_un.d_ptr + 32);
   plte += 3 * (reloc - rela_plt);
 
   /* Find the displacement from the plt entry to the function.  */
@@ -481,7 +481,7 @@ elf_machine_rela (struct link_map *map,
 		 than the dynamic linker's built-in definitions used
 		 while loading those libraries.  */
 	      const Elf64_Sym *const dlsymtab
-		= (void *)(map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
+		= (void *) map->l_info[DT_SYMTAB]->d_un.d_ptr;
 	      sym_value -= map->l_addr;
 	      sym_value -= dlsymtab[ELF64_R_SYM(reloc->r_info)].st_value;
 	      sym_value -= reloc->r_addend;
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
index b8a1e19359..e443711fba 100644
--- a/sysdeps/arm/dl-machine.h
+++ b/sysdeps/arm/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  ARM version.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -405,8 +405,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	    {
 	      const char *strtab;
 
-	      strtab = ((const char *) map->l_addr
-			+ map->l_info[DT_STRTAB]->d_un.d_ptr);
+	      strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 	      _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
 				": Symbol `", strtab + refsym->st_name,
 				"' has different size in shared object, "
@@ -417,9 +416,9 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	  break;
 	case R_ARM_GLOB_DAT:
 	case R_ARM_JUMP_SLOT:
-#ifdef RTLD_BOOTSTRAP 
+#ifdef RTLD_BOOTSTRAP
 	  /* Fix weak undefined references.  */
-	  if (sym != NULL && sym->st_value == 0) 
+	  if (sym != NULL && sym->st_value == 0)
 	    *reloc_addr = 0;
 	  else
 #endif
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 8338a93617..fb7fc4095e 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  i386 version.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -339,8 +339,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	    {
 	      const char *strtab;
 
-	      strtab = ((const char *) map->l_addr
-			+ map->l_info[DT_STRTAB]->d_un.d_ptr);
+	      strtab = (const char *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 	      _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
 				": Symbol `", strtab + refsym->st_name,
 				"' has different size in shared object, "
@@ -359,7 +358,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	   /* This is defined in rtld.c, but nowhere in the static
 	      libc.a; make the reference weak so static programs can
 	      still link.  This declaration cannot be done when
-	      compiling rtld.c (i.e.  #ifdef RTLD_BOOTSTRAP) because
+	      compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP) because
 	      rtld.c contains the common defn for _dl_rtld_map, which
 	      is incompatible with a weak decl in the same file.  */
 	    weak_extern (_dl_rtld_map);
diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h
index f2fe553069..8ce24a7f63 100644
--- a/sysdeps/m68k/dl-machine.h
+++ b/sysdeps/m68k/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  m68k version.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999 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
@@ -277,8 +277,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 	      extern char **_dl_argv;
 	      const char *strtab;
 
-	      strtab = ((void *) map->l_addr
-			+ map->l_info[DT_STRTAB]->d_un.d_ptr);
+	      strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 	      _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
 				": Symbol `", strtab + refsym->st_name,
 				"' has different size in shared object, "
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index 77b8c4e18f..749ea00170 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  MIPS version.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
 
@@ -144,8 +144,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
   ElfW(Addr) *got;
   ElfW(Sym) *sym;
   int i, n;
-  const char *strtab
-    = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
+  const char *strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 
 #define RESOLVE_GOTSYM(sym) \
     ({ \
@@ -170,8 +169,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
 
   /* Handle global got entries. */
   got += n;
-  sym = (ElfW(Sym) *) ((void *) map->l_addr
-		       + map->l_info[DT_SYMTAB]->d_un.d_ptr);
+  sym = (void *) map->l_info[DT_SYMTAB]->d_un.d_ptr;
   sym += map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
   i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val
        - map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val);
@@ -348,9 +346,9 @@ __dl_runtime_resolve (ElfW(Word) sym_index,				      \
 {									      \
   struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);     \
   const ElfW(Sym) *const symtab						      \
-    = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);     \
+    = (const void *) l->l_info[DT_SYMTAB]->d_un.d_ptr;			      \
   const char *strtab							      \
-    = (void *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);		      \
+    = (const void *) l->l_info[DT_STRTAB]->d_un.d_ptr;			      \
   const ElfW(Addr) *got							      \
     = (const ElfW(Addr) *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);    \
   const ElfW(Word) local_gotno						      \
diff --git a/sysdeps/powerpc/dl-machine.c b/sysdeps/powerpc/dl-machine.c
index 7d45e74d65..35086997b5 100644
--- a/sysdeps/powerpc/dl-machine.c
+++ b/sysdeps/powerpc/dl-machine.c
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation functions.  PowerPC version.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -417,8 +417,7 @@ __process_machine_rela (struct link_map *map,
 	{
 	  const char *strtab;
 
-	  strtab = ((void *) map->l_addr
-		    + map->l_info[DT_STRTAB]->d_un.d_ptr);
+	  strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 	  _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
 			    ": Symbol `", strtab + refsym->st_name,
 			    "' has different size in shared object, "
diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h
index e1fb2b68ce..fa8cd45f45 100644
--- a/sysdeps/sparc/sparc32/dl-machine.h
+++ b/sysdeps/sparc/sparc32/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  SPARC version.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999 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
@@ -386,8 +386,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 	      extern char **_dl_argv;
 	      const char *strtab;
 
-	      strtab = ((void *) map->l_addr
-			+ map->l_info[DT_STRTAB]->d_un.d_ptr);
+	      strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 	      _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
 				": Symbol `", strtab + refsym->st_name,
 				"' has different size in shared object, "
diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h
index 33def6b455..851801bc42 100644
--- a/sysdeps/sparc/sparc64/dl-machine.h
+++ b/sysdeps/sparc/sparc64/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  Sparc64 version.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 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
@@ -213,8 +213,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
 	      extern char **_dl_argv;
 	      const char *strtab;
 
-	      strtab = ((void *) map->l_addr
-			+ map->l_info[DT_STRTAB]->d_un.d_ptr);
+	      strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
 	      _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
 				": Symbol `", strtab + refsym->st_name,
 				"' has different size in shared object, "