diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | elf/dl-load.c | 2 | ||||
-rw-r--r-- | elf/dynamic-link.h | 47 | ||||
-rw-r--r-- | elf/rtld.c | 8 |
4 files changed, 46 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog index e2a9f39044..29791a6a46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8429,6 +8429,16 @@ (common-mostlyclean, common-clean): Clean up rtld-* files. * sysdeps/unix/make-syscalls.sh: Add rtld-*.os target name to rules. +2003-05-20 Jakub Jelinek <jakub@redhat.com> + + * elf/dynamic-link.h (elf_get_dynamic_info): Add temp argument. + If temp != NULL, copy dynamic entries which need relocation to temp + array before relocating. + (DL_RO_DYN_TEMP_CNT): Define. + * elf/dl-load.c (_dl_map_object_from_fd): Adjust caller. + * elf/rtld.c (_dl_start): Likewise. + (dl_main): Likewise. Add dyn_temp static variable. + 2002-10-11 Roland McGrath <roland@redhat.com> * sysdeps/generic/dl-tls.c (__tls_get_addr): After freeing block in diff --git a/elf/dl-load.c b/elf/dl-load.c index 290236b5e1..8b0c82bb52 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1268,7 +1268,7 @@ cannot allocate TLS data structures for initial thread"); (unsigned long int) l->l_phdr, (int) sizeof (void *) * 2, l->l_phnum); - elf_get_dynamic_info (l); + elf_get_dynamic_info (l, NULL); /* Make sure we are not dlopen'ing an object that has the DF_1_NOOPEN flag set. */ diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index 63adfcb802..5bf3f6f0f6 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -56,7 +56,7 @@ elf_machine_lazy_rel (struct link_map *map, /* Read the dynamic section at DYN and fill in INFO with indices DT_*. */ static inline void __attribute__ ((unused, always_inline)) -elf_get_dynamic_info (struct link_map *l) +elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) { ElfW(Dyn) *dyn = l->l_ld; ElfW(Dyn) **info; @@ -88,32 +88,45 @@ elf_get_dynamic_info (struct link_map *l) + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn; ++dyn; } + +#define DL_RO_DYN_TEMP_CNT 8 + #ifndef DL_RO_DYN_SECTION /* Don't adjust .dynamic unnecessarily. */ if (l->l_addr != 0) { ElfW(Addr) l_addr = l->l_addr; + int cnt = 0; + +# define ADJUST_DYN_INFO(tag) \ + do \ + if (info[tag] != NULL) \ + { \ + if (temp) \ + { \ + temp[cnt].d_tag = info[tag]->d_tag; \ + temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr; \ + info[tag] = temp + cnt++; \ + } \ + else \ + info[tag]->d_un.d_ptr += l_addr; \ + } \ + while (0) - if (info[DT_HASH] != NULL) - info[DT_HASH]->d_un.d_ptr += l_addr; - if (info[DT_PLTGOT] != NULL) - info[DT_PLTGOT]->d_un.d_ptr += l_addr; - if (info[DT_STRTAB] != NULL) - info[DT_STRTAB]->d_un.d_ptr += l_addr; - if (info[DT_SYMTAB] != NULL) - info[DT_SYMTAB]->d_un.d_ptr += l_addr; + ADJUST_DYN_INFO (DT_HASH); + ADJUST_DYN_INFO (DT_PLTGOT); + ADJUST_DYN_INFO (DT_STRTAB); + ADJUST_DYN_INFO (DT_SYMTAB); # if ! ELF_MACHINE_NO_RELA - if (info[DT_RELA] != NULL) - info[DT_RELA]->d_un.d_ptr += l_addr; + ADJUST_DYN_INFO (DT_RELA); # endif # if ! ELF_MACHINE_NO_REL - if (info[DT_REL] != NULL) - info[DT_REL]->d_un.d_ptr += l_addr; + ADJUST_DYN_INFO (DT_REL); # endif - if (info[DT_JMPREL] != NULL) - info[DT_JMPREL]->d_un.d_ptr += l_addr; - if (info[VERSYMIDX (DT_VERSYM)] != NULL) - info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr += l_addr; + ADJUST_DYN_INFO (DT_JMPREL); + ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM)); +# undef ADJUST_DYN_INFO + assert (cnt <= DL_RO_DYN_TEMP_CNT); } #endif if (info[DT_PLTREL] != NULL) diff --git a/elf/rtld.c b/elf/rtld.c index a0d8e98c57..367a9dcba9 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -317,7 +317,7 @@ _dl_start (void *arg) /* Read our own dynamic section and fill in the info array. */ bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); - elf_get_dynamic_info (&bootstrap_map); + elf_get_dynamic_info (&bootstrap_map, NULL); #if defined USE_TLS && NO_TLS_OFFSET != 0 bootstrap_map.l_tls_offset = NO_TLS_OFFSET; @@ -892,7 +892,7 @@ of this helper program; chances are you did not intend to run this program.\n\ if (! rtld_is_main) { /* Extract the contents of the dynamic section for easy access. */ - elf_get_dynamic_info (GL(dl_loaded)); + elf_get_dynamic_info (GL(dl_loaded), NULL); if (GL(dl_loaded)->l_info[DT_HASH]) /* Set up our cache of pointers into the hash table. */ _dl_setup_hash (GL(dl_loaded)); @@ -1083,6 +1083,8 @@ of this helper program; chances are you did not intend to run this program.\n\ struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL); if (__builtin_expect (l != NULL, 1)) { + static ElfW(Dyn) dyn_temp [DL_RO_DYN_TEMP_CNT]; + l->l_phdr = ((const void *) GL(dl_sysinfo_dso) + GL(dl_sysinfo_dso)->e_phoff); l->l_phnum = GL(dl_sysinfo_dso)->e_phnum; @@ -1098,7 +1100,7 @@ of this helper program; chances are you did not intend to run this program.\n\ if (ph->p_type == PT_LOAD) assert ((void *) ph->p_vaddr == GL(dl_sysinfo_dso)); } - elf_get_dynamic_info (l); + elf_get_dynamic_info (l, dyn_temp); _dl_setup_hash (l); l->l_relocated = 1; |