From: Ulrich Drepper Date: Sun, 16 Oct 2011 13:34:51 +0000 (-0400) Subject: Fix potential problem with skipping relocations X-Git-Tag: upstream/2.30~11990 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e453f6cd0ccdd64a3f5f156e2c5f70085e9289e7;p=external%2Fglibc.git Fix potential problem with skipping relocations We never seem to have hit this problem but way relative relocations were skipped was wrong. There are relative relocations only in the DT_REL/DT_RELA section. The elf_dynamic_do_##reloc function skipped the entries in all calls, though. --- diff --git a/ChangeLog b/ChangeLog index 96ebe99..9a792f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-10-16 Ulrich Drepper + + * elf/do-rel.h: Add another parameter nrelative, replacing the + local variable with the same name. Change name of the function + to end in Rel or Rela (uppercase). + * elf/dynamic-link.h (_ELF_DYNAMIC_DO_RELOC): Add new element + nrelative to ranges. Only nonzero for DT_REL/DT_RELA. Pass to the + elf_dynamic_do_##reloc function. + 2011-10-15 Ulrich Drepper * sysdeps/i386/i686/fpu/e_log.S: No need for the fyl2xp1 use, fyl2x diff --git a/elf/do-rel.h b/elf/do-rel.h index 6187b9e..69f2f0e 100644 --- a/elf/do-rel.h +++ b/elf/do-rel.h @@ -21,13 +21,10 @@ `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */ #ifdef DO_RELA -# define elf_dynamic_do_rel elf_dynamic_do_rela -# define RELCOUNT_IDX VERSYMIDX (DT_RELACOUNT) +# define elf_dynamic_do_Rel elf_dynamic_do_Rela # define Rel Rela # define elf_machine_rel elf_machine_rela # define elf_machine_rel_relative elf_machine_rela_relative -#else -# define RELCOUNT_IDX VERSYMIDX (DT_RELCOUNT) #endif #ifndef DO_ELF_MACHINE_REL_RELATIVE @@ -50,9 +47,9 @@ than fully resolved now. */ auto inline void __attribute__ ((always_inline)) -elf_dynamic_do_rel (struct link_map *map, +elf_dynamic_do_Rel (struct link_map *map, ElfW(Addr) reladdr, ElfW(Addr) relsize, - int lazy, int skip_ifunc) + ElfW(Word) nrelative, int lazy, int skip_ifunc) { const ElfW(Rel) *r = (const void *) reladdr; const ElfW(Rel) *end = (const void *) (reladdr + relsize); @@ -73,10 +70,8 @@ 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) *relative = r; - r = r + MIN (nrelative, relsize / sizeof (ElfW(Rel))); + r += nrelative; #ifndef RTLD_BOOTSTRAP /* This is defined in rtld.c, but nowhere in the static libc.a; make @@ -131,9 +126,9 @@ elf_dynamic_do_rel (struct link_map *map, } } -#undef elf_dynamic_do_rel +#undef elf_dynamic_do_Rel #undef Rel #undef elf_machine_rel #undef elf_machine_rel_relative #undef DO_ELF_MACHINE_REL_RELATIVE -#undef RELCOUNT_IDX +#undef DO_RELA diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index 2bdab45..486408d 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -258,17 +258,23 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) # ifdef ELF_MACHINE_PLTREL_OVERLAP # define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \ do { \ - struct { ElfW(Addr) start, size; int lazy; } ranges[3]; \ + struct { ElfW(Addr) start, size; ElfW(Word) nrelative; int lazy; } \ + ranges[3]; \ int ranges_index; \ \ ranges[0].lazy = ranges[2].lazy = 0; \ ranges[1].lazy = 1; \ ranges[0].size = ranges[1].size = ranges[2].size = 0; \ + ranges[0].nrelative = ranges[1].nrelative = ranges[2].nrelative = 0; \ \ if ((map)->l_info[DT_##RELOC]) \ { \ ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \ ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \ + if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL) \ + ranges[0].nrelative \ + = MIN (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val, \ + ranges[0].size / sizeof (ElfW(reloc))); \ } \ \ if ((do_lazy) \ @@ -286,21 +292,24 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) elf_dynamic_do_##reloc ((map), \ ranges[ranges_index].start, \ ranges[ranges_index].size, \ + ranges[ranges_index].nrelative, \ ranges[ranges_index].lazy, \ skip_ifunc); \ } while (0) # else # define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \ do { \ - struct { ElfW(Addr) start, size; int lazy; } ranges[2]; \ - ranges[0].lazy = 0; \ - ranges[0].size = ranges[1].size = 0; \ - ranges[0].start = 0; \ + struct { ElfW(Addr) start, size; ElfW(Word) nrelative; int lazy; } \ + ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; \ \ if ((map)->l_info[DT_##RELOC]) \ { \ ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \ ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \ + if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL) \ + ranges[0].nrelative \ + = MIN (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val, \ + ranges[0].size / sizeof (ElfW(reloc))); \ } \ if ((map)->l_info[DT_PLTREL] \ && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \ @@ -312,7 +321,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) /* This test does not only detect whether the relocation \ sections are in the right order, it also checks whether \ there is a DT_REL/DT_RELA section. */ \ - || ranges[0].start + ranges[0].size != start)) \ + || __builtin_expect (ranges[0].start + ranges[0].size \ + != start, 0))) \ { \ ranges[1].start = start; \ ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \ @@ -327,8 +337,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) } \ \ if (ELF_DURING_STARTUP) \ - elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, 0, \ - skip_ifunc); \ + elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, \ + ranges[0].nrelative, 0, skip_ifunc); \ else \ { \ int ranges_index; \ @@ -336,6 +346,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) elf_dynamic_do_##reloc ((map), \ ranges[ranges_index].start, \ ranges[ranges_index].size, \ + ranges[ranges_index].nrelative, \ ranges[ranges_index].lazy, \ skip_ifunc); \ } \ @@ -351,7 +362,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) # if ! ELF_MACHINE_NO_REL # include "do-rel.h" # define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \ - _ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, skip_ifunc, _ELF_CHECK_REL) + _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, lazy, skip_ifunc, _ELF_CHECK_REL) # else # define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do. */ # endif @@ -360,7 +371,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) # define DO_RELA # include "do-rel.h" # define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \ - _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, skip_ifunc, _ELF_CHECK_REL) + _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, lazy, skip_ifunc, _ELF_CHECK_REL) # else # define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do. */ # endif