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.
This commit is contained in:
Ulrich Drepper 2011-10-16 09:34:51 -04:00
parent 79b195b55a
commit e453f6cd0c
3 changed files with 36 additions and 21 deletions

View File

@ -1,3 +1,12 @@
2011-10-16 Ulrich Drepper <drepper@gmail.com>
* 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 <drepper@gmail.com>
* sysdeps/i386/i686/fpu/e_log.S: No need for the fyl2xp1 use, fyl2x

View File

@ -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

View File

@ -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