aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-10-16 09:34:51 -0400
committerUlrich Drepper <drepper@gmail.com>2011-10-16 09:34:51 -0400
commite453f6cd0ccdd64a3f5f156e2c5f70085e9289e7 (patch)
tree52ffc06dedd14b973a77112d6847614eb976542f /elf
parent79b195b55af84a9044dfb26ebdc49d9f308829af (diff)
downloadglibc-e453f6cd0ccdd64a3f5f156e2c5f70085e9289e7.zip
glibc-e453f6cd0ccdd64a3f5f156e2c5f70085e9289e7.tar.gz
glibc-e453f6cd0ccdd64a3f5f156e2c5f70085e9289e7.tar.bz2
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.
Diffstat (limited to 'elf')
-rw-r--r--elf/do-rel.h17
-rw-r--r--elf/dynamic-link.h31
2 files changed, 27 insertions, 21 deletions
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