From a94d834c9d0108f0bb50ddc311554d1bed320f54 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 2 Aug 2016 11:56:55 +0100 Subject: [PATCH] Fix SH GOT allocation in the presence of linker garbage collection. PR ld/17739 ld * emulparams/shelf.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): Define with valye 'yes'. * emulparams/shelf32.sh: Likewise. * emulparams/shelf32.sh: Likewise. * emulparams/shelf_nto.sh: Likewise. * emulparams/shelf_nto.sh: Likewise. * emulparams/shelf_vxworks.sh: Likewise. * emulparams/shelf_vxworks.sh: Likewise. * emulparams/shlelf32_linux.sh: Likewise. * emulparams/shlelf32_linux.sh: Likewise. * emulparams/shlelf_linux.sh: Likewise. * emulparams/shlelf_linux.sh: Likewise. * emulparams/shlelf_nto.sh: Likewise. * emulparams/shlelf_nto.sh: Likewise. bfd * elf32-sh.c (sh_elf_gc_sweep_hook): Delete. (elf_backend_sweep_hook): Delete. --- bfd/elf32-sh.c | 215 --------------------------------------- ld/emulparams/shelf.sh | 3 + ld/emulparams/shelf32.sh | 3 + ld/emulparams/shelf_nto.sh | 3 + ld/emulparams/shelf_vxworks.sh | 4 + ld/emulparams/shlelf32_linux.sh | 4 +- ld/emulparams/shlelf_linux.sh | 3 + ld/emulparams/shlelf_nto.sh | 3 + 10 files changed, 46 insertions(+), 216 deletions(-) diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index 52a5fd1..84c5b1e 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -5682,220 +5682,6 @@ sh_elf_gc_mark_hook (asection *sec, return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } -/* Update the got entry reference counts for the section being removed. */ - -static bfd_boolean -sh_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, - asection *sec, const Elf_Internal_Rela *relocs) -{ - Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes; - bfd_signed_vma *local_got_refcounts; - union gotref *local_funcdesc; - const Elf_Internal_Rela *rel, *relend; - - if (bfd_link_relocatable (info)) - return TRUE; - - elf_section_data (sec)->local_dynrel = NULL; - - symtab_hdr = &elf_symtab_hdr (abfd); - sym_hashes = elf_sym_hashes (abfd); - local_got_refcounts = elf_local_got_refcounts (abfd); - local_funcdesc = sh_elf_local_funcdesc (abfd); - - relend = relocs + sec->reloc_count; - for (rel = relocs; rel < relend; rel++) - { - unsigned long r_symndx; - unsigned int r_type; - struct elf_link_hash_entry *h = NULL; -#ifdef INCLUDE_SHMEDIA - int seen_stt_datalabel = 0; -#endif - - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf_sh_link_hash_entry *eh; - struct elf_sh_dyn_relocs **pp; - struct elf_sh_dyn_relocs *p; - - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - { -#ifdef INCLUDE_SHMEDIA - seen_stt_datalabel |= h->type == STT_DATALABEL; -#endif - h = (struct elf_link_hash_entry *) h->root.u.i.link; - } - eh = (struct elf_sh_link_hash_entry *) h; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - /* Everything must go for SEC. */ - *pp = p->next; - break; - } - } - - r_type = ELF32_R_TYPE (rel->r_info); - switch (sh_elf_optimized_tls_reloc (info, r_type, h != NULL)) - { - case R_SH_TLS_LD_32: - if (sh_elf_hash_table (info)->tls_ldm_got.refcount > 0) - sh_elf_hash_table (info)->tls_ldm_got.refcount -= 1; - break; - - case R_SH_GOT32: - case R_SH_GOT20: - case R_SH_GOTOFF: - case R_SH_GOTOFF20: - case R_SH_GOTPC: -#ifdef INCLUDE_SHMEDIA - case R_SH_GOT_LOW16: - case R_SH_GOT_MEDLOW16: - case R_SH_GOT_MEDHI16: - case R_SH_GOT_HI16: - case R_SH_GOT10BY4: - case R_SH_GOT10BY8: - case R_SH_GOTOFF_LOW16: - case R_SH_GOTOFF_MEDLOW16: - case R_SH_GOTOFF_MEDHI16: - case R_SH_GOTOFF_HI16: - case R_SH_GOTPC_LOW16: - case R_SH_GOTPC_MEDLOW16: - case R_SH_GOTPC_MEDHI16: - case R_SH_GOTPC_HI16: -#endif - case R_SH_TLS_GD_32: - case R_SH_TLS_IE_32: - case R_SH_GOTFUNCDESC: - case R_SH_GOTFUNCDESC20: - if (h != NULL) - { -#ifdef INCLUDE_SHMEDIA - if (seen_stt_datalabel) - { - struct elf_sh_link_hash_entry *eh; - eh = (struct elf_sh_link_hash_entry *) h; - if (eh->datalabel_got.refcount > 0) - eh->datalabel_got.refcount -= 1; - } - else -#endif - if (h->got.refcount > 0) - h->got.refcount -= 1; - } - else if (local_got_refcounts != NULL) - { -#ifdef INCLUDE_SHMEDIA - if (rel->r_addend & 1) - { - if (local_got_refcounts[symtab_hdr->sh_info + r_symndx] > 0) - local_got_refcounts[symtab_hdr->sh_info + r_symndx] -= 1; - } - else -#endif - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx] -= 1; - } - break; - - case R_SH_FUNCDESC: - if (h != NULL) - sh_elf_hash_entry (h)->abs_funcdesc_refcount -= 1; - else if (sh_elf_hash_table (info)->fdpic_p && !bfd_link_pic (info)) - sh_elf_hash_table (info)->srofixup->size -= 4; - - /* Fall through. */ - - case R_SH_GOTOFFFUNCDESC: - case R_SH_GOTOFFFUNCDESC20: - if (h != NULL) - sh_elf_hash_entry (h)->funcdesc.refcount -= 1; - else - local_funcdesc[r_symndx].refcount -= 1; - break; - - case R_SH_DIR32: - if (sh_elf_hash_table (info)->fdpic_p && !bfd_link_pic (info) - && (sec->flags & SEC_ALLOC) != 0) - sh_elf_hash_table (info)->srofixup->size -= 4; - /* Fall thru */ - - case R_SH_REL32: - if (bfd_link_pic (info)) - break; - /* Fall thru */ - - case R_SH_PLT32: -#ifdef INCLUDE_SHMEDIA - case R_SH_PLT_LOW16: - case R_SH_PLT_MEDLOW16: - case R_SH_PLT_MEDHI16: - case R_SH_PLT_HI16: -#endif - if (h != NULL) - { - if (h->plt.refcount > 0) - h->plt.refcount -= 1; - } - break; - - case R_SH_GOTPLT32: -#ifdef INCLUDE_SHMEDIA - case R_SH_GOTPLT_LOW16: - case R_SH_GOTPLT_MEDLOW16: - case R_SH_GOTPLT_MEDHI16: - case R_SH_GOTPLT_HI16: - case R_SH_GOTPLT10BY4: - case R_SH_GOTPLT10BY8: -#endif - if (h != NULL) - { - struct elf_sh_link_hash_entry *eh; - eh = (struct elf_sh_link_hash_entry *) h; - if (eh->gotplt_refcount > 0) - { - eh->gotplt_refcount -= 1; - if (h->plt.refcount > 0) - h->plt.refcount -= 1; - } -#ifdef INCLUDE_SHMEDIA - else if (seen_stt_datalabel) - { - if (eh->datalabel_got.refcount > 0) - eh->datalabel_got.refcount -= 1; - } -#endif - else if (h->got.refcount > 0) - h->got.refcount -= 1; - } - else if (local_got_refcounts != NULL) - { -#ifdef INCLUDE_SHMEDIA - if (rel->r_addend & 1) - { - if (local_got_refcounts[symtab_hdr->sh_info + r_symndx] > 0) - local_got_refcounts[symtab_hdr->sh_info + r_symndx] -= 1; - } - else -#endif - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx] -= 1; - } - break; - - default: - break; - } - } - - return TRUE; -} - /* Copy the extra info we tack onto an elf_link_hash_entry. */ static void @@ -7455,7 +7241,6 @@ sh_elf_encode_eh_address (bfd *abfd, sh_elf_merge_private_data #define elf_backend_gc_mark_hook sh_elf_gc_mark_hook -#define elf_backend_gc_sweep_hook sh_elf_gc_sweep_hook #define elf_backend_check_relocs sh_elf_check_relocs #define elf_backend_copy_indirect_symbol \ sh_elf_copy_indirect_symbol diff --git a/ld/emulparams/shelf.sh b/ld/emulparams/shelf.sh index 83680a6..d3f4752 100644 --- a/ld/emulparams/shelf.sh +++ b/ld/emulparams/shelf.sh @@ -11,6 +11,9 @@ MACHINE= TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes EMBEDDED=yes +# PR 17739. Delay checking relocs until after all files have +# been opened and linker garbage collection has taken place. +CHECK_RELOCS_AFTER_OPEN_INPUT=yes # These are for compatibility with the COFF toolchain. ENTRY=start diff --git a/ld/emulparams/shelf32.sh b/ld/emulparams/shelf32.sh index 966bd30..bf362c5 100644 --- a/ld/emulparams/shelf32.sh +++ b/ld/emulparams/shelf32.sh @@ -11,6 +11,9 @@ ALIGNMENT=8 TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes EMBEDDED=yes +# PR 17739. Delay checking relocs until after all files have +# been opened and linker garbage collection has taken place. +CHECK_RELOCS_AFTER_OPEN_INPUT=yes DATA_START_SYMBOLS='PROVIDE (___data = .);' diff --git a/ld/emulparams/shelf_nto.sh b/ld/emulparams/shelf_nto.sh index c4d71aa..46efd87 100644 --- a/ld/emulparams/shelf_nto.sh +++ b/ld/emulparams/shelf_nto.sh @@ -9,3 +9,6 @@ TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes TEXT_START_SYMBOLS='_btext = .;' ENTRY=_start +# PR 17739. Delay checking relocs until after all files have +# been opened and linker garbage collection has taken place. +CHECK_RELOCS_AFTER_OPEN_INPUT=yes diff --git a/ld/emulparams/shelf_vxworks.sh b/ld/emulparams/shelf_vxworks.sh index 77619cb..759ffac 100644 --- a/ld/emulparams/shelf_vxworks.sh +++ b/ld/emulparams/shelf_vxworks.sh @@ -14,6 +14,10 @@ TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes ENTRY=__start SYMPREFIX=_ +# PR 17739. Delay checking relocs until after all files have +# been opened and linker garbage collection has taken place. +CHECK_RELOCS_AFTER_OPEN_INPUT=yes + GOT=".got ${RELOCATING-0} : { PROVIDE(__GLOBAL_OFFSET_TABLE_ = .); *(.got.plt) *(.got) }" diff --git a/ld/emulparams/shlelf32_linux.sh b/ld/emulparams/shlelf32_linux.sh index 81aea39..0327e57 100644 --- a/ld/emulparams/shlelf32_linux.sh +++ b/ld/emulparams/shlelf32_linux.sh @@ -13,7 +13,9 @@ ALIGNMENT=8 TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes GENERATE_PIE_SCRIPT=yes - +# PR 17739. Delay checking relocs until after all files have +# been opened and linker garbage collection has taken place. +CHECK_RELOCS_AFTER_OPEN_INPUT=yes DATA_START_SYMBOLS='PROVIDE (___data = .);' diff --git a/ld/emulparams/shlelf_linux.sh b/ld/emulparams/shlelf_linux.sh index c14aae2..4e2a581 100644 --- a/ld/emulparams/shlelf_linux.sh +++ b/ld/emulparams/shlelf_linux.sh @@ -12,6 +12,9 @@ MACHINE= TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes GENERATE_PIE_SCRIPT=yes +# PR 17739. Delay checking relocs until after all files have +# been opened and linker garbage collection has taken place. +CHECK_RELOCS_AFTER_OPEN_INPUT=yes DATA_START_SYMBOLS='PROVIDE (__data_start = .);'; diff --git a/ld/emulparams/shlelf_nto.sh b/ld/emulparams/shlelf_nto.sh index 16f6508..f8ffc13 100644 --- a/ld/emulparams/shlelf_nto.sh +++ b/ld/emulparams/shlelf_nto.sh @@ -9,3 +9,6 @@ TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes TEXT_START_SYMBOLS='_btext = .;' ENTRY=_start +# PR 17739. Delay checking relocs until after all files have +# been opened and linker garbage collection has taken place. +CHECK_RELOCS_AFTER_OPEN_INPUT=yes -- 1.7.1