diff options
author | Ulrich Drepper <drepper@redhat.com> | 2001-08-24 08:40:21 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2001-08-24 08:40:21 +0000 |
commit | c65c9d8ba06fe2b9202a84b31895c7633574bc92 (patch) | |
tree | 746b176b7c255f5ff35dfdf7c99c05d9515d6079 /elf/do-rel.h | |
parent | 37d8d3629e6851c933808c0dbf9b7368f14ce920 (diff) | |
download | glibc-c65c9d8ba06fe2b9202a84b31895c7633574bc92.zip glibc-c65c9d8ba06fe2b9202a84b31895c7633574bc92.tar.gz glibc-c65c9d8ba06fe2b9202a84b31895c7633574bc92.tar.bz2 |
(elf_dynamic_do_rel): If not relocating lazily, don't call elf_machine_rel for the last DT_RELCOUNT relocations but instead elf_machine_rel_relative.
Diffstat (limited to 'elf/do-rel.h')
-rw-r--r-- | elf/do-rel.h | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/elf/do-rel.h b/elf/do-rel.h index 7c9afa8..b1c6033 100644 --- a/elf/do-rel.h +++ b/elf/do-rel.h @@ -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 @@ -22,8 +22,11 @@ #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)); } } |