(elf_dynamic_do_rel): If not relocating lazily, don't call elf_machine_rel for the...
authorUlrich Drepper <drepper@redhat.com>
Fri, 24 Aug 2001 08:40:21 +0000 (08:40 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 24 Aug 2001 08:40:21 +0000 (08:40 +0000)
elf/do-rel.h

index 7c9afa8..b1c6033 100644 (file)
@@ -1,5 +1,5 @@
 /* Do relocations for ELF dynamic linking.
-   Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
+   Copyright (C) 1995,96,97,98,99,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
 
 #ifdef DO_RELA
 # define elf_dynamic_do_rel    elf_dynamic_do_rela
+# define RELCOUNT_IDX          VERSYMIDX (DT_RELACOUNT)
 # define Rel                   Rela
 # define elf_machine_rel       elf_machine_rela
+#else
+# define RELCOUNT_IDX          VERSYMIDX (DT_RELCOUNT)
 #endif
 
 #ifndef VERSYMIDX
@@ -42,11 +45,11 @@ elf_dynamic_do_rel (struct link_map *map,
 {
   const ElfW(Rel) *r = (const void *) reladdr;
   const ElfW(Rel) *end = (const void *) (reladdr + relsize);
+  ElfW(Addr) l_addr = map->l_addr;
 
   if (lazy)
     {
       /* Doing lazy PLT relocations; they need very little info.  */
-      ElfW(Addr) l_addr = map->l_addr;
       for (; r < end; ++r)
        elf_machine_lazy_rel (map, l_addr, r);
     }
@@ -54,6 +57,10 @@ elf_dynamic_do_rel (struct link_map *map,
     {
       const ElfW(Sym) *const symtab =
        (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+      ElfW(Word) nrelative = (map->l_info[RELCOUNT_IDX] == NULL
+                             ? 0 : map->l_info[RELCOUNT_IDX]->d_un.d_val);
+      const ElfW(Rel) *endrel = end;
+      end -= nrelative;
 
       if (map->l_info[VERSYMIDX (DT_VERSYM)])
        {
@@ -65,13 +72,27 @@ elf_dynamic_do_rel (struct link_map *map,
              ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)];
              elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
                               &map->l_versions[ndx],
-                              (void *) (map->l_addr + r->r_offset));
+                              (void *) (l_addr + r->r_offset));
            }
        }
       else
        for (; r < end; ++r)
          elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
-                          (void *) (map->l_addr + r->r_offset));
+                          (void *) (l_addr + r->r_offset));
+
+#ifndef RTLD_BOOTSTRAP
+      /* 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 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);
+      if (map != &_dl_rtld_map) /* Already done in rtld itself.  */
+#endif
+       for (; r < endrel; ++r)
+         elf_machine_rel_relative (l_addr, r,
+                                   (void *) (l_addr + r->r_offset));
     }
 }