From: Alan Modra Date: Sat, 10 Nov 2001 00:23:35 +0000 (+0000) Subject: * elf32-arm.h (elf32_arm_final_link_relocate): Don't copy STN_UNDEF X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ec33885937c311707a20bac4207422abde93511e;p=binutils-gdb.git * elf32-arm.h (elf32_arm_final_link_relocate): Don't copy STN_UNDEF relocs into shared libs. * elf32-cris.c (cris_elf_relocate_section): Likewise. * elf32-i370.c (i370_elf_relocate_section): Likewise. * elf32-m68k.c (elf_m68k_relocate_section): Likewise. * elf32-mips.c (mips_elf_calculate_relocation): Likewise. * elf32-ppc.c (ppc_elf_relocate_section): Likewise. * elf32-sh.c (sh_elf_relocate_section): Likewise. * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. * elf64-alpha.c (elf64_alpha_relocate_section): Likewise. * elf64-s390.c (elf_s390_relocate_section): Likewise. * elf64-sparc.c (sparc64_elf_relocate_section): Likewise. * elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise. * elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise. * elf.c (bfd_section_from_r_symndx): New function. * elf-bfd.h (LOCAL_SYM_CACHE_SIZE): Define. (struct sym_sec_cache): New. (bfd_section_from_r_symndx): Declare. (struct bfd_elf_section_data): Change local_dynrel type to PTR. * elflink.h (elf_link_input_bfd): Don't test for removed linkonce relocs when relocatable. Don't zero entire reloc, just zero the addend and sym. * elf32-i386.c (struct elf_i386_link_hash_table): Add sym_sec. (elf_i386_link_hash_table_create): Init it. (elf_i386_check_relocs): Track dynamic relocs needed for local syms on a per-section basis as we do for globals. (elf_i386_gc_sweep_hook): Update for local_dynrel change. Remove dead code. (allocate_dynrelocs): Warning fix. (elf_i386_size_dynamic_sections): Don't allocate relocs when section has been discarded. (elf_i386_relocate_section): Don't copy STN_UNDEF relocs into shared libs. * elf32-hppa.c: Likewise. * elf32-s390.c: Likewise. * elf64-ppc.c: Likewise. * elf64-s390.c: Likewise. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e189fe5947e..556e6135b6b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,83 @@ +2001-11-10 Alan Modra + + * elf32-arm.h (elf32_arm_final_link_relocate): Don't copy STN_UNDEF + relocs into shared libs. + * elf32-cris.c (cris_elf_relocate_section): Likewise. + * elf32-i370.c (i370_elf_relocate_section): Likewise. + * elf32-m68k.c (elf_m68k_relocate_section): Likewise. + * elf32-mips.c (mips_elf_calculate_relocation): Likewise. + * elf32-ppc.c (ppc_elf_relocate_section): Likewise. + * elf32-sh.c (sh_elf_relocate_section): Likewise. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + * elf64-alpha.c (elf64_alpha_relocate_section): Likewise. + * elf64-s390.c (elf_s390_relocate_section): Likewise. + * elf64-sparc.c (sparc64_elf_relocate_section): Likewise. + * elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise. + * elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise. + + * elf.c (bfd_section_from_r_symndx): New function. + * elf-bfd.h (LOCAL_SYM_CACHE_SIZE): Define. + (struct sym_sec_cache): New. + (bfd_section_from_r_symndx): Declare. + (struct bfd_elf_section_data): Change local_dynrel type to PTR. + * elflink.h (elf_link_input_bfd): Don't test for removed linkonce + relocs when relocatable. Don't zero entire reloc, just zero the + addend and sym. + * elf32-hppa.c (struct elf32_hppa_link_hash_table): Add sym_sec. + (elf32_hppa_link_hash_table_create): Init it. + (elf32_hppa_check_relocs): Track dynamic relocs needed for local + syms on a per-section basis as we do for globals. + (elf32_hppa_gc_sweep_hook): Update for local_dynrel change. + (allocate_dynrelocs): Warning fix. + (elf32_hppa_size_dynamic_sections): Don't allocate relocs when + section has been discarded. + (elf32_hppa_relocate_section): Don't copy STN_UNDEF relocs + into shared libs. + * elf32-i386.c (struct elf_i386_link_hash_table): Add sym_sec. + (elf_i386_link_hash_table_create): Init it. + (elf_i386_check_relocs): Track dynamic relocs needed for local + syms on a per-section basis as we do for globals. + (elf_i386_gc_sweep_hook): Update for local_dynrel change. + Remove dead code. + (allocate_dynrelocs): Warning fix. + (elf_i386_size_dynamic_sections): Don't allocate relocs when + section has been discarded. + (elf_i386_relocate_section): Don't copy STN_UNDEF relocs + into shared libs. + * elf32-s390.c (struct elf_s390_link_hash_table): Add sym_sec. + (elf_s390_link_hash_table_create): Init it. + (elf_s390_check_relocs): Track dynamic relocs needed for local + syms on a per-section basis as we do for globals. + (elf_s390_gc_sweep_hook): Update for local_dynrel change. + Remove dead code. + (allocate_dynrelocs): Warning fix. + (elf_s390_size_dynamic_sections): Don't allocate relocs when + section has been discarded. + (elf_s390_relocate_section): Don't copy STN_UNDEF relocs + into shared libs. + * elf64-ppc.c (struct ppc_link_hash_table): Add sym_sec. + (ppc64_link_hash_table_create): Init it. + (ppc64_elf_check_relocs): Track dynamic relocs needed for local + syms on a per-section basis as we do for globals. + (ppc64_elf_gc_sweep_hook): Update for local_dynrel change. + (allocate_dynrelocs): Call the correct record_dynamic_dymbol + function. Warning fix. + (ppc64_elf_size_dynamic_sections): Don't allocate relocs when + section has been discarded. + (ppc64_elf_relocate_section): Don't copy STN_UNDEF relocs + into shared libs. + * elf64-s390.c (struct elf_s390_link_hash_table): Add sym_sec. + (elf_s390_link_hash_table_create): Init it. + (elf_s390_check_relocs): Track dynamic relocs needed for local + syms on a per-section basis as we do for globals. + (elf_s390_gc_sweep_hook): Update for local_dynrel change. + Remove dead code. + (allocate_dynrelocs): Warning fix. + (elf_s390_size_dynamic_sections): Don't allocate relocs when + section has been discarded. + (elf_s390_relocate_section): Don't copy STN_UNDEF relocs + into shared libs. + 2001-11-08 Martin Schwidefsky * elf32-s390: Major rework that introduces all recent changes to @@ -65,7 +145,7 @@ (elf_s390_copy_indirect_symbol): New function. (elf_s390_create_dynamic_sections): New function. (readonly_dynrelocs): New function. - * elf64-s390x: Likewise. + * elf64-s390.c: Likewise. 2001-11-07 Jakub Jelinek diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index e9a8b838368..cb79eeab69f 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -299,6 +299,16 @@ struct elf_link_hash_table /* Returns true if the hash table is a struct elf_link_hash_table. */ #define is_elf_hash_table(p) \ ((p)->hash->type == bfd_link_elf_hash_table) + +/* Used by bfd_section_from_r_symndx to cache a small number of local + symbol to section mappings. */ +#define LOCAL_SYM_CACHE_SIZE 32 +struct sym_sec_cache +{ + bfd *abfd; + unsigned long indx[LOCAL_SYM_CACHE_SIZE]; + asection *sec[LOCAL_SYM_CACHE_SIZE]; +}; /* Constant information held for an ELF backend. */ @@ -778,8 +788,9 @@ struct bfd_elf_section_data /* The number of relocations currently assigned to REL_HDR2. */ unsigned int rel_count2; - /* The number of dynamic relocs copied for local symbols. */ - unsigned int local_dynrel; + /* A pointer to a linked list tracking dynamic relocs copied for + local symbols. */ + PTR local_dynrel; /* A pointer to the bfd section used for dynamic relocs. */ asection *sreloc; @@ -1198,6 +1209,8 @@ extern boolean bfd_section_from_phdr extern int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *, asymbol **)); +extern asection *bfd_section_from_r_symndx + PARAMS ((bfd *, struct sym_sec_cache *, asection *, unsigned long)); extern asection *bfd_section_from_elf_index PARAMS ((bfd *, unsigned int)); extern boolean _bfd_elf_create_dynamic_sections diff --git a/bfd/elf.c b/bfd/elf.c index 8c1694e41cf..7bffecdb40f 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1747,6 +1747,62 @@ bfd_section_from_shdr (abfd, shindex) return true; } +/* Return the section for the local symbol specified by ABFD, R_SYMNDX. + Return SEC for sections that have no elf section, and NULL on error. */ + +asection * +bfd_section_from_r_symndx (abfd, cache, sec, r_symndx) + bfd *abfd; + struct sym_sec_cache *cache; + asection *sec; + unsigned long r_symndx; +{ + unsigned char esym_shndx[2]; + unsigned int isym_shndx; + Elf_Internal_Shdr *symtab_hdr; + file_ptr pos; + bfd_size_type amt; + unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE; + + if (cache->abfd == abfd && cache->indx[ent] == r_symndx) + return cache->sec[ent]; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + pos = symtab_hdr->sh_offset; + if (get_elf_backend_data (abfd)->s->sizeof_sym + == sizeof (Elf64_External_Sym)) + { + pos += r_symndx * sizeof (Elf64_External_Sym); + pos += offsetof (Elf64_External_Sym, st_shndx); + } + else + { + pos += r_symndx * sizeof (Elf32_External_Sym); + pos += offsetof (Elf32_External_Sym, st_shndx); + } + amt = sizeof (esym_shndx); + if (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt) + return NULL; + isym_shndx = H_GET_16 (abfd, esym_shndx); + + if (cache->abfd != abfd) + { + memset (cache->indx, -1, sizeof (cache->indx)); + cache->abfd = abfd; + } + cache->indx[ent] = r_symndx; + cache->sec[ent] = sec; + if (isym_shndx > 0 && isym_shndx < SHN_LORESERVE) + { + asection *s; + s = bfd_section_from_elf_index (abfd, isym_shndx); + if (s != NULL) + cache->sec[ent] = s; + } + return cache->sec[ent]; +} + /* Given an ELF section number, retrieve the corresponding BFD section. */ diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index 838c24ff556..83a2d6d7ff0 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -1116,6 +1116,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ if (info->shared + && r_symndx != 0 && (r_type != R_ARM_PC24 || (h != NULL && h->dynindx != -1 diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c index c881ee4dc0a..41f4cfcd803 100644 --- a/bfd/elf32-cris.c +++ b/bfd/elf32-cris.c @@ -1233,6 +1233,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_CRIS_16: case R_CRIS_32: if (info->shared + && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0 && ((r_type != R_CRIS_8_PCREL && r_type != R_CRIS_16_PCREL diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 0bebd89e5da..97abe8ff748 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -263,6 +263,9 @@ struct elf32_hppa_link_hash_table { /* Set if we need a .plt stub to support lazy dynamic linking. */ unsigned int need_plt_stub:1; + + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; }; /* Various hash macros and functions. */ @@ -507,6 +510,7 @@ elf32_hppa_link_hash_table_create (abfd) ret->has_12bit_branch = 0; ret->has_17bit_branch = 0; ret->need_plt_stub = 0; + ret->sym_sec.abfd = NULL; return &ret->elf.root; } @@ -1514,6 +1518,9 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) || (h->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { + struct elf32_hppa_dyn_reloc_entry *p; + struct elf32_hppa_dyn_reloc_entry **head; + /* Create a reloc section in dynobj and make room for this reloc. */ if (sreloc == NULL) @@ -1561,36 +1568,46 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) relocations we need for this symbol. */ if (h != NULL) { - struct elf32_hppa_dyn_reloc_entry *p; + head = &h->dyn_relocs; + } + else + { + /* Track dynamic relocs needed for local syms too. + We really need local syms available to do this + easily. Oh well. */ + + asection *s; + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, + sec, r_symndx); + if (s == NULL) + return false; - p = h->dyn_relocs; - if (p == NULL || p->sec != sec) - { - p = ((struct elf32_hppa_dyn_reloc_entry *) - bfd_alloc (htab->elf.dynobj, - (bfd_size_type) sizeof *p)); - if (p == NULL) - return false; - p->next = h->dyn_relocs; - h->dyn_relocs = p; - p->sec = sec; - p->count = 0; + head = ((struct elf32_hppa_dyn_reloc_entry **) + &elf_section_data (s)->local_dynrel); + } + + p = *head; + if (p == NULL || p->sec != sec) + { + p = ((struct elf32_hppa_dyn_reloc_entry *) + bfd_alloc (htab->elf.dynobj, + (bfd_size_type) sizeof *p)); + if (p == NULL) + return false; + p->next = *head; + *head = p; + p->sec = sec; + p->count = 0; #if RELATIVE_DYNRELOCS - p->relative_count = 0; + p->relative_count = 0; #endif - } + } - p->count += 1; + p->count += 1; #if RELATIVE_DYNRELOCS - if (!IS_ABSOLUTE_RELOC (rtype)) - p->relative_count += 1; + if (!IS_ABSOLUTE_RELOC (rtype)) + p->relative_count += 1; #endif - } - else - { - /* Track dynamic relocs needed for local syms too. */ - elf_section_data (sec)->local_dynrel += 1; - } } } } @@ -1666,7 +1683,7 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs) struct elf32_hppa_link_hash_table *htab; bfd *dynobj; - elf_section_data (sec)->local_dynrel = 0; + elf_section_data (sec)->local_dynrel = NULL; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -2184,7 +2201,7 @@ allocate_dynrelocs (h, inf) eh->dyn_relocs = NULL; return true; - keep: + keep: ; } /* Finally, allocate space. */ @@ -2311,12 +2328,26 @@ elf32_hppa_size_dynamic_sections (output_bfd, info) for (s = ibfd->sections; s != NULL; s = s->next) { - bfd_size_type count = elf_section_data (s)->local_dynrel; + struct elf32_hppa_dyn_reloc_entry *p; - if (count != 0) + for (p = ((struct elf32_hppa_dyn_reloc_entry *) + elf_section_data (s)->local_dynrel); + p != NULL; + p = p->next) { - srel = elf_section_data (s)->sreloc; - srel->_raw_size += count * sizeof (Elf32_External_Rela); + if (!bfd_is_abs_section (p->sec) + && bfd_is_abs_section (p->sec->output_section)) + { + /* Input section has been discarded, either because + it is a copy of a linkonce section or due to + linker script /DISCARD/, so we'll be discarding + the relocs too. */ + } + else + { + srel = elf_section_data (p->sec)->sreloc; + srel->_raw_size += p->count * sizeof (Elf32_External_Rela); + } } } @@ -3877,12 +3908,19 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, case R_PARISC_DPREL14R: case R_PARISC_DPREL21L: case R_PARISC_DIR32: + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + if (r_symndx == 0 + || (input_section->flags & SEC_ALLOC) == 0) + break; + /* The reloc types handled here and this conditional expression must match the code in ..check_relocs and - ..discard_relocs. ie. We need exactly the same condition + allocate_dynrelocs. ie. We need exactly the same condition as in ..check_relocs, with some extra conditions (dynindx test in this case) to cater for relocs removed by - ..discard_relocs. If you squint, the non-shared test + allocate_dynrelocs. If you squint, the non-shared test here does indeed match the one in ..check_relocs, the difference being that here we test DEF_DYNAMIC as well as !DEF_REGULAR. All common syms end up with !DEF_REGULAR, @@ -3890,7 +3928,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, Conversely, DEF_DYNAMIC can't be used in check_relocs as there all files have not been loaded. */ if ((info->shared - && (input_section->flags & SEC_ALLOC) != 0 && (IS_ABSOLUTE_RELOC (r_type) || (h != NULL && h->elf.dynindx != -1 @@ -3898,7 +3935,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)))) || (!info->shared - && (input_section->flags & SEC_ALLOC) != 0 && h != NULL && h->elf.dynindx != -1 && (h->elf.elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 diff --git a/bfd/elf32-i370.c b/bfd/elf32-i370.c index a93e9a7c122..3f9c9c1e210 100644 --- a/bfd/elf32-i370.c +++ b/bfd/elf32-i370.c @@ -1449,7 +1449,8 @@ i370_elf_relocate_section (output_bfd, info, input_bfd, input_section, object. */ case (int)R_I370_ADDR31: case (int)R_I370_ADDR16: - if (info->shared) + if (info->shared + && r_symndx != 0) { Elf_Internal_Rela outrel; boolean skip; diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 211a19cb081..238772e4c61 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -497,6 +497,9 @@ struct elf_i386_link_hash_table asection *srelplt; asection *sdynbss; asection *srelbss; + + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; }; /* Get the i386 ELF linker hash table from a link_info structure. */ @@ -561,6 +564,7 @@ elf_i386_link_hash_table_create (abfd) ret->srelplt = NULL; ret->sdynbss = NULL; ret->srelbss = NULL; + ret->sym_sec.abfd = NULL; return &ret->elf.root; } @@ -833,6 +837,9 @@ elf_i386_check_relocs (abfd, info, sec, relocs) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { + struct elf_i386_dyn_relocs *p; + struct elf_i386_dyn_relocs **head; + /* We must copy these reloc types into the output file. Create a reloc section in dynobj and make room for this reloc. */ @@ -883,35 +890,42 @@ elf_i386_check_relocs (abfd, info, sec, relocs) relocations we need for this symbol. */ if (h != NULL) { - struct elf_i386_link_hash_entry *eh; - struct elf_i386_dyn_relocs *p; - - eh = (struct elf_i386_link_hash_entry *) h; - p = eh->dyn_relocs; - - if (p == NULL || p->sec != sec) - { - bfd_size_type amt = sizeof *p; - p = ((struct elf_i386_dyn_relocs *) - bfd_alloc (htab->elf.dynobj, amt)); - if (p == NULL) - return false; - p->next = eh->dyn_relocs; - eh->dyn_relocs = p; - p->sec = sec; - p->count = 0; - p->pc_count = 0; - } - - p->count += 1; - if (ELF32_R_TYPE (rel->r_info) == R_386_PC32) - p->pc_count += 1; + head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs; } else { - /* Track dynamic relocs needed for local syms too. */ - elf_section_data (sec)->local_dynrel += 1; + /* Track dynamic relocs needed for local syms too. + We really need local syms available to do this + easily. Oh well. */ + + asection *s; + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, + sec, r_symndx); + if (s == NULL) + return false; + + head = ((struct elf_i386_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + } + + p = *head; + if (p == NULL || p->sec != sec) + { + bfd_size_type amt = sizeof *p; + p = ((struct elf_i386_dyn_relocs *) + bfd_alloc (htab->elf.dynobj, amt)); + if (p == NULL) + return false; + p->next = *head; + *head = p; + p->sec = sec; + p->count = 0; + p->pc_count = 0; } + + p->count += 1; + if (ELF32_R_TYPE (rel->r_info) == R_386_PC32) + p->pc_count += 1; } break; @@ -1000,13 +1014,8 @@ elf_i386_gc_sweep_hook (abfd, info, sec, relocs) const Elf_Internal_Rela *rel, *relend; unsigned long r_symndx; struct elf_link_hash_entry *h; - bfd *dynobj; - elf_section_data (sec)->local_dynrel = 0; - - dynobj = elf_hash_table (info)->dynobj; - if (dynobj == NULL) - return true; + elf_section_data (sec)->local_dynrel = NULL; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -1393,7 +1402,7 @@ allocate_dynrelocs (h, inf) eh->dyn_relocs = NULL; - keep: + keep: ; } /* Finally, allocate space. */ @@ -1480,12 +1489,26 @@ elf_i386_size_dynamic_sections (output_bfd, info) for (s = ibfd->sections; s != NULL; s = s->next) { - bfd_size_type count = elf_section_data (s)->local_dynrel; + struct elf_i386_dyn_relocs *p; - if (count != 0) + for (p = *((struct elf_i386_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + p != NULL; + p = p->next) { - srel = elf_section_data (s)->sreloc; - srel->_raw_size += count * sizeof (Elf32_External_Rel); + if (!bfd_is_abs_section (p->sec) + && bfd_is_abs_section (p->sec->output_section)) + { + /* Input section has been discarded, either because + it is a copy of a linkonce section or due to + linker script /DISCARD/, so we'll be discarding + the relocs too. */ + } + else + { + srel = elf_section_data (p->sec)->sreloc; + srel->_raw_size += p->count * sizeof (Elf32_External_Rel); + } } } @@ -1924,8 +1947,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, case R_386_32: case R_386_PC32: + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + if (r_symndx == 0 + || (input_section->flags & SEC_ALLOC) == 0) + break; + if ((info->shared - && (input_section->flags & SEC_ALLOC) != 0 && (r_type != R_386_PC32 || (h != NULL && h->dynindx != -1 @@ -1933,7 +1962,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)))) || (!info->shared - && (input_section->flags & SEC_ALLOC) != 0 && h != NULL && h->dynindx != -1 && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 @@ -2010,7 +2038,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, if (! relocate) continue; } - break; default: diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 609e91a5371..a613024c24a 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -1644,6 +1644,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, case R_68K_16: case R_68K_32: if (info->shared + && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0 && ((r_type != R_68K_PC8 && r_type != R_68K_PC16 diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 6b0c7a46adf..b40c56e68b3 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -6325,6 +6325,7 @@ mips_elf_calculate_relocation (abfd, & ELF_LINK_HASH_DEF_DYNAMIC) != 0) && ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) + && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0) { /* If we're creating a shared library, or this relocation is diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 6dd826041fc..cd6bd959607 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -3175,7 +3175,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, case (int) R_PPC_ADDR14: case (int) R_PPC_UADDR32: case (int) R_PPC_UADDR16: - if (info->shared) + if (info->shared && r_symndx != 0) { Elf_Internal_Rela outrel; boolean skip; diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index f09410bee70..aeb9805a25e 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -123,7 +123,7 @@ elf_s390_reloc_type_lookup (abfd, code) bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code; { - switch (code) + switch (code) { case BFD_RELOC_NONE: return &elf_howto_table[(int) R_390_NONE]; @@ -415,6 +415,9 @@ struct elf_s390_link_hash_table asection *srelplt; asection *sdynbss; asection *srelbss; + + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; }; /* Get the s390 ELF linker hash table from a link_info structure. */ @@ -439,13 +442,13 @@ link_hash_newfunc (entry, table, string) if (entry == NULL) return entry; } - + /* Call the allocation method of the superclass. */ entry = _bfd_elf_link_hash_newfunc (entry, table, string); if (entry != NULL) { struct elf_s390_link_hash_entry *eh; - + eh = (struct elf_s390_link_hash_entry *) entry; eh->dyn_relocs = NULL; } @@ -479,6 +482,7 @@ elf_s390_link_hash_table_create (abfd) ret->srelplt = NULL; ret->sdynbss = NULL; ret->srelbss = NULL; + ret->sym_sec.abfd = NULL; return &ret->elf.root; } @@ -716,7 +720,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) Tentatively set the flag for now, and correct in adjust_dynamic_symbol. */ h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; - + /* We may need a .plt entry if the function this reloc refers to is in a shared lib. */ h->plt.refcount += 1; @@ -745,7 +749,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) symbol. */ if ((info->shared && (sec->flags & SEC_ALLOC) != 0 - && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16 + && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16 && ELF32_R_TYPE (rel->r_info) != R_390_PC16DBL && ELF32_R_TYPE (rel->r_info) != R_390_PC32) || (h != NULL @@ -760,6 +764,9 @@ elf_s390_check_relocs (abfd, info, sec, relocs) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { + struct elf_s390_dyn_relocs *p; + struct elf_s390_dyn_relocs **head; + /* We must copy these reloc types into the output file. Create a reloc section in dynobj and make room for this reloc. */ @@ -767,7 +774,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) { const char *name; bfd *dynobj; - + name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader (abfd)->e_shstrndx, @@ -810,54 +817,61 @@ elf_s390_check_relocs (abfd, info, sec, relocs) relocations we need for this symbol. */ if (h != NULL) { - struct elf_s390_link_hash_entry *eh; - struct elf_s390_dyn_relocs *p; - - eh = (struct elf_s390_link_hash_entry *) h; - p = eh->dyn_relocs; - - if (p == NULL || p->sec != sec) - { - bfd_size_type amt = sizeof *p; - p = ((struct elf_s390_dyn_relocs *) - bfd_alloc (htab->elf.dynobj, amt)); - if (p == NULL) - return false; - p->next = eh->dyn_relocs; - eh->dyn_relocs = p; - p->sec = sec; - p->count = 0; - p->pc_count = 0; - } - - p->count += 1; - if (ELF32_R_TYPE (rel->r_info) == R_390_PC16 - || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL - || ELF32_R_TYPE (rel->r_info) == R_390_PC32) - p->pc_count += 1; + head = &((struct elf_s390_link_hash_entry *) h)->dyn_relocs; } else { - /* Track dynamic relocs needed for local syms too. */ - elf_section_data (sec)->local_dynrel += 1; + /* Track dynamic relocs needed for local syms too. + We really need local syms available to do this + easily. Oh well. */ + + asection *s; + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, + sec, r_symndx); + if (s == NULL) + return false; + + head = ((struct elf_s390_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + } + + p = *head; + if (p == NULL || p->sec != sec) + { + bfd_size_type amt = sizeof *p; + p = ((struct elf_s390_dyn_relocs *) + bfd_alloc (htab->elf.dynobj, amt)); + if (p == NULL) + return false; + p->next = *head; + *head = p; + p->sec = sec; + p->count = 0; + p->pc_count = 0; } + + p->count += 1; + if (ELF32_R_TYPE (rel->r_info) == R_390_PC16 + || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL + || ELF32_R_TYPE (rel->r_info) == R_390_PC32) + p->pc_count += 1; } break; - + /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_390_GNU_VTINHERIT: if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return false; break; - + /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_390_GNU_VTENTRY: if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset)) return false; break; - + default: break; } @@ -929,13 +943,8 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) const Elf_Internal_Rela *rel, *relend; unsigned long r_symndx; struct elf_link_hash_entry *h; - bfd *dynobj; - - elf_section_data (sec)->local_dynrel = 0; - dynobj = elf_hash_table (info)->dynobj; - if (dynobj == NULL) - return true; + elf_section_data (sec)->local_dynrel = NULL; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -1108,7 +1117,7 @@ elf_s390_adjust_dynamic_symbol (info, h) } /* If we didn't find any dynamic relocs in read-only sections, then - we'll be keeping the dynamic relocs and avoiding the copy reloc. */ + we'll be keeping the dynamic relocs and avoiding the copy reloc. */ if (p == NULL) { h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; @@ -1226,10 +1235,10 @@ allocate_dynrelocs (h, inf) h->root.u.def.section = s; h->root.u.def.value = h->plt.offset; } - + /* Make room for this entry. */ s->_raw_size += PLT_ENTRY_SIZE; - + /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ htab->sgotplt->_raw_size += GOT_ENTRY_SIZE; @@ -1242,13 +1251,13 @@ allocate_dynrelocs (h, inf) h->plt.offset = (bfd_vma) -1; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } - } + } else { h->plt.offset = (bfd_vma) -1; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; - } - + } + if (h->got.refcount > 0) { asection *s; @@ -1332,7 +1341,7 @@ allocate_dynrelocs (h, inf) eh->dyn_relocs = NULL; - keep: + keep: ; } /* Finally, allocate space. */ @@ -1419,12 +1428,26 @@ elf_s390_size_dynamic_sections (output_bfd, info) for (s = ibfd->sections; s != NULL; s = s->next) { - bfd_size_type count = elf_section_data (s)->local_dynrel; + struct elf_s390_dyn_relocs *p; - if (count != 0) + for (p = *((struct elf_s390_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + p != NULL; + p = p->next) { - srela = elf_section_data (s)->sreloc; - srela->_raw_size += count * sizeof (Elf32_External_Rela); + if (!bfd_is_abs_section (p->sec) + && bfd_is_abs_section (p->sec->output_section)) + { + /* Input section has been discarded, either because + it is a copy of a linkonce section or due to + linker script /DISCARD/, so we'll be discarding + the relocs too. */ + } + else + { + srela = elf_section_data (p->sec)->sreloc; + srela->_raw_size += p->count * sizeof (Elf32_External_Rela); + } } } @@ -1474,7 +1497,7 @@ elf_s390_size_dynamic_sections (output_bfd, info) { if (s->_raw_size != 0 && s != htab->srelplt) relocs = true; - + /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ s->reloc_count = 0; @@ -1510,7 +1533,7 @@ elf_s390_size_dynamic_sections (output_bfd, info) if (s->contents == NULL) return false; } - + if (htab->elf.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the @@ -1520,13 +1543,13 @@ elf_s390_size_dynamic_sections (output_bfd, info) dynamic linker and used by the debugger. */ #define add_dynamic_entry(TAG, VAL) \ bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) - + if (! info->shared) { if (!add_dynamic_entry (DT_DEBUG, 0)) return false; } - + if (htab->splt->_raw_size != 0) { if (!add_dynamic_entry (DT_PLTGOT, 0) @@ -1535,7 +1558,7 @@ elf_s390_size_dynamic_sections (output_bfd, info) || !add_dynamic_entry (DT_JMPREL, 0)) return false; } - + if (relocs) { if (!add_dynamic_entry (DT_RELA, 0) @@ -1546,7 +1569,7 @@ elf_s390_size_dynamic_sections (output_bfd, info) /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, (PTR) info); - + if ((info->flags & DF_TEXTREL) != 0) { if (!add_dynamic_entry (DT_TEXTREL, 0)) @@ -1555,7 +1578,7 @@ elf_s390_size_dynamic_sections (output_bfd, info) } } #undef add_dynamic_entry - + return true; } @@ -1599,7 +1622,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, bfd_vma relocation; boolean unresolved_reloc; bfd_reloc_status_type r; - + r_type = ELF32_R_TYPE (rel->r_info); if (r_type == (int) R_390_GNU_VTINHERIT || r_type == (int) R_390_GNU_VTENTRY) @@ -1610,9 +1633,9 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, return false; } howto = elf_howto_table + r_type; - + r_symndx = ELF32_R_SYM (rel->r_info); - + if (info->relocateable) { /* This is a relocateable link. We don't have to change @@ -1628,10 +1651,10 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, rel->r_addend += sec->output_offset + sym->st_value; } } - + continue; } - + /* This is a final link. */ h = NULL; sym = NULL; @@ -1651,7 +1674,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - + if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { @@ -1725,7 +1748,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, relocation = 0; } } - + switch (r_type) { case R_390_GOT12: @@ -1735,11 +1758,11 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, offset table. */ if (htab->sgot == NULL) abort (); - + if (h != NULL) { boolean dyn; - + off = h->got.offset; dyn = htab->elf.dynamic_sections_created; if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) @@ -1869,8 +1892,14 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, case R_390_PC16: case R_390_PC16DBL: case R_390_PC32: + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + if (r_symndx == 0 + || (input_section->flags & SEC_ALLOC) == 0) + break; + if ((info->shared - && (input_section->flags & SEC_ALLOC) != 0 && ((r_type != R_390_PC16 && r_type != R_390_PC16DBL && r_type != R_390_PC32) @@ -1880,7 +1909,6 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)))) || (!info->shared - && (input_section->flags & SEC_ALLOC) != 0 && h != NULL && h->dynindx != -1 && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 @@ -1895,13 +1923,13 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, boolean skip, relocate; asection *sreloc; Elf32_External_Rela *loc; - + /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ - + skip = false; - + if (elf_section_data (input_section)->stab_info == NULL) outrel.r_offset = rel->r_offset; else @@ -1914,10 +1942,10 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, skip = true; outrel.r_offset = off; } - + outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); - + if (skip) { memset (&outrel, 0, sizeof outrel); @@ -1944,15 +1972,15 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE); outrel.r_addend = relocation + rel->r_addend; } - + sreloc = elf_section_data (input_section)->sreloc; if (sreloc == NULL) abort (); - + loc = (Elf32_External_Rela *) sreloc->contents; loc += sreloc->reloc_count++; bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); - + /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we need to include the symbol value so that it becomes @@ -1960,13 +1988,12 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, if (! relocate) continue; } - break; - + default: break; } - + if (unresolved_reloc && !(info->shared && (input_section->flags & SEC_DEBUGGING) != 0 @@ -1977,15 +2004,15 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, bfd_get_section_name (input_bfd, input_section), (long) rel->r_offset, h->root.root.string); - + r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, rel->r_addend); - + if (r != bfd_reloc_ok) { const char *name; - + if (h != NULL) name = h->root.root.string; else @@ -1998,10 +2025,10 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, if (*name == '\0') name = bfd_section_name (input_bfd, sec); } - + if (r == bfd_reloc_overflow) { - + if (! ((*info->callbacks->reloc_overflow) (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset))) @@ -2018,7 +2045,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, } } } - + return true; } @@ -2033,9 +2060,9 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) Elf_Internal_Sym *sym; { struct elf_s390_link_hash_table *htab; - + htab = elf_s390_hash_table (info); - + if (h->plt.offset != (bfd_vma) -1) { bfd_vma plt_index; @@ -2043,10 +2070,10 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) Elf_Internal_Rela rela; Elf32_External_Rela *loc; bfd_vma relative_offset; - + /* This symbol has an entry in the procedure linkage table. Set it up. */ - + if (h->dynindx == -1 || htab->splt == NULL || htab->sgotplt == NULL @@ -2163,18 +2190,18 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) rela.r_addend = 0; loc = (Elf32_External_Rela *) htab->srelplt->contents + plt_index; bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); - + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value alone. This is a clue for the dynamic linker, to make function pointer comparisons work between an application and shared - library. */ + library. */ sym->st_shndx = SHN_UNDEF; } } - + if (h->got.offset != (bfd_vma) -1) { Elf_Internal_Rela rela; @@ -2300,18 +2327,18 @@ elf_s390_finish_dynamic_sections (output_bfd, info) { Elf_Internal_Dyn dyn; asection *s; - + bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); - + switch (dyn.d_tag) { default: continue; - + case DT_PLTGOT: dyn.d_un.d_ptr = htab->sgot->output_section->vma; break; - + case DT_JMPREL: dyn.d_un.d_ptr = htab->srelplt->output_section->vma; break; diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index eec9642d099..35ebf1ab6e6 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -3216,6 +3216,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_SH_DIR32: case R_SH_REL32: if (info->shared + && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0 && (r_type != R_SH_REL32 || (h != NULL diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index 889d83fccc0..96fc3e9c8d9 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -1409,7 +1409,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_LO10: case R_SPARC_UA16: case R_SPARC_UA32: - if (info->shared && (input_section->flags & SEC_ALLOC)) + if (info->shared + && r_symndx != 0 + && (input_section->flags & SEC_ALLOC)) { Elf_Internal_Rela outrel; boolean skip; diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index ee78d1ff27b..69cfef9797b 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -3516,7 +3516,9 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, outrel.r_addend = addend; addend = 0, relocation = 0; } - else if (info->shared && (input_section->flags & SEC_ALLOC)) + else if (info->shared + && r_symndx != 0 + && (input_section->flags & SEC_ALLOC)) { outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); outrel.r_addend = relocation + addend; diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 418b38684e6..97aa485c9d9 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -1639,6 +1639,9 @@ struct ppc_link_hash_table asection *sdynbss; asection *srelbss; asection *sglink; + + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; }; /* Get the ppc64 ELF linker hash table from a link_info structure. */ @@ -1701,6 +1704,7 @@ ppc64_elf_link_hash_table_create (abfd) htab->sdynbss = NULL; htab->srelbss = NULL; htab->sglink = NULL; + htab->sym_sec.abfd = NULL; return &htab->elf.root; } @@ -2035,6 +2039,9 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { + struct ppc_dyn_relocs *p; + struct ppc_dyn_relocs **head; + /* We must copy these reloc types into the output file. Create a reloc section in dynobj and make room for this reloc. */ @@ -2085,35 +2092,42 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) relocations we need for this symbol. */ if (h != NULL) { - struct ppc_link_hash_entry *eh; - struct ppc_dyn_relocs *p; - - eh = (struct ppc_link_hash_entry *) h; - p = eh->dyn_relocs; - - if (p == NULL || p->sec != sec) - { - p = ((struct ppc_dyn_relocs *) - bfd_alloc (htab->elf.dynobj, - (bfd_size_type) sizeof *p)); - if (p == NULL) - return false; - p->next = eh->dyn_relocs; - eh->dyn_relocs = p; - p->sec = sec; - p->count = 0; - p->pc_count = 0; - } - - p->count += 1; - if (!IS_ABSOLUTE_RELOC (r_type)) - p->pc_count += 1; + head = &((struct ppc_link_hash_entry *) h)->dyn_relocs; } else { - /* Track dynamic relocs needed for local syms too. */ - elf_section_data (sec)->local_dynrel += 1; + /* Track dynamic relocs needed for local syms too. + We really need local syms available to do this + easily. Oh well. */ + + asection *s; + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, + sec, r_symndx); + if (s == NULL) + return false; + + head = ((struct ppc_dyn_relocs **) + &elf_section_data (s)->local_dynrel); } + + p = *head; + if (p == NULL || p->sec != sec) + { + p = ((struct ppc_dyn_relocs *) + bfd_alloc (htab->elf.dynobj, + (bfd_size_type) sizeof *p)); + if (p == NULL) + return false; + p->next = *head; + *head = p; + p->sec = sec; + p->count = 0; + p->pc_count = 0; + } + + p->count += 1; + if (!IS_ABSOLUTE_RELOC (r_type)) + p->pc_count += 1; } break; @@ -2190,6 +2204,8 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; + elf_section_data (sec)->local_dynrel = NULL; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_got_refcounts = elf_local_got_refcounts (abfd); @@ -2660,7 +2676,7 @@ allocate_dynrelocs (h, inf) if (h->dynindx == -1 && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + if (! bfd_elf64_link_record_dynamic_symbol (info, h)) return false; } @@ -2672,7 +2688,7 @@ allocate_dynrelocs (h, inf) eh->dyn_relocs = NULL; - keep: + keep: ; } /* Finally, allocate space. */ @@ -2759,12 +2775,26 @@ ppc64_elf_size_dynamic_sections (output_bfd, info) for (s = ibfd->sections; s != NULL; s = s->next) { - bfd_size_type count = elf_section_data (s)->local_dynrel; + struct ppc_dyn_relocs *p; - if (count != 0) + for (p = *((struct ppc_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + p != NULL; + p = p->next) { - srel = elf_section_data (s)->sreloc; - srel->_raw_size += count * sizeof (Elf64_External_Rela); + if (!bfd_is_abs_section (p->sec) + && bfd_is_abs_section (p->sec->output_section)) + { + /* Input section has been discarded, either because + it is a copy of a linkonce section or due to + linker script /DISCARD/, so we'll be discarding + the relocs too. */ + } + else + { + srel = elf_section_data (p->sec)->sreloc; + srel->_raw_size += p->count * sizeof (Elf64_External_Rela); + } } } @@ -3429,8 +3459,14 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_PPC64_UADDR32: case R_PPC64_UADDR64: case R_PPC64_TOC: + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + if (r_symndx == 0 + || (input_section->flags & SEC_ALLOC) == 0) + break; + if ((info->shared - && (input_section->flags & SEC_ALLOC) != 0 && (IS_ABSOLUTE_RELOC (r_type) || (h != NULL && h->dynindx != -1 @@ -3438,7 +3474,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)))) || (!info->shared - && (input_section->flags & SEC_ALLOC) != 0 && h != NULL && h->dynindx != -1 && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index 3bba1b35438..e0a18cdbbe3 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -374,6 +374,9 @@ struct elf_s390_link_hash_table asection *srelplt; asection *sdynbss; asection *srelbss; + + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; }; /* Get the s390 ELF linker hash table from a link_info structure. */ @@ -438,6 +441,7 @@ elf_s390_link_hash_table_create (abfd) ret->srelplt = NULL; ret->sdynbss = NULL; ret->srelbss = NULL; + ret->sym_sec.abfd = NULL; return &ret->elf.root; } @@ -620,7 +624,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (local_got_refcounts == NULL) { bfd_size_type size; - + size = symtab_hdr->sh_info; size *= sizeof (bfd_signed_vma); local_got_refcounts = ((bfd_signed_vma *) @@ -644,7 +648,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) return false; } break; - + case R_390_PLT16DBL: case R_390_PLT32: case R_390_PLT32DBL: @@ -655,16 +659,16 @@ elf_s390_check_relocs (abfd, info, sec, relocs) never referenced by a dynamic object, in which case we don't need to generate a procedure linkage table entry after all. */ - + /* If this is a local symbol, we resolve it directly without creating a procedure linkage table entry. */ if (h == NULL) continue; - + h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; h->plt.refcount += 1; break; - + case R_390_8: case R_390_16: case R_390_32: @@ -683,12 +687,12 @@ elf_s390_check_relocs (abfd, info, sec, relocs) Tentatively set the flag for now, and correct in adjust_dynamic_symbol. */ h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; - + /* We may need a .plt entry if the function this reloc refers to is in a shared lib. */ h->plt.refcount += 1; } - + /* If we are creating a shared library, and this is a reloc against a global symbol, or a non PC relative reloc against a local symbol, then we need to copy the reloc @@ -729,6 +733,9 @@ elf_s390_check_relocs (abfd, info, sec, relocs) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { + struct elf_s390_dyn_relocs *p; + struct elf_s390_dyn_relocs **head; + /* We must copy these reloc types into the output file. Create a reloc section in dynobj and make room for this reloc. */ @@ -736,14 +743,14 @@ elf_s390_check_relocs (abfd, info, sec, relocs) { const char *name; bfd *dynobj; - + name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader (abfd)->e_shstrndx, elf_section_data (sec)->rel_hdr.sh_name)); if (name == NULL) return false; - + if (strncmp (name, ".rela", 5) != 0 || strcmp (bfd_get_section_name (abfd, sec), name + 5) != 0) @@ -752,7 +759,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) (_("%s: bad relocation section name `%s\'"), bfd_archive_filename (abfd), name); } - + if (htab->elf.dynobj == NULL) htab->elf.dynobj = abfd; @@ -761,7 +768,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (sreloc == NULL) { flagword flags; - + sreloc = bfd_make_section (dynobj, name); flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED); @@ -774,61 +781,68 @@ elf_s390_check_relocs (abfd, info, sec, relocs) } elf_section_data (sec)->sreloc = sreloc; } - + /* If this is a global symbol, we count the number of relocations we need for this symbol. */ if (h != NULL) { - struct elf_s390_link_hash_entry *eh; - struct elf_s390_dyn_relocs *p; - - eh = (struct elf_s390_link_hash_entry *) h; - p = eh->dyn_relocs; - - if (p == NULL || p->sec != sec) - { - bfd_size_type amt = sizeof *p; - p = ((struct elf_s390_dyn_relocs *) - bfd_alloc (htab->elf.dynobj, amt)); - if (p == NULL) - return false; - p->next = eh->dyn_relocs; - eh->dyn_relocs = p; - p->sec = sec; - p->count = 0; - p->pc_count = 0; - } - - p->count += 1; - if (ELF64_R_TYPE (rel->r_info) == R_390_PC16 - || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL - || ELF64_R_TYPE (rel->r_info) == R_390_PC32 - || ELF64_R_TYPE (rel->r_info) == R_390_PC32DBL - || ELF64_R_TYPE (rel->r_info) == R_390_PC64) - p->pc_count += 1; + head = &((struct elf_s390_link_hash_entry *) h)->dyn_relocs; } else { - /* Track dynamic relocs needed for local syms too. */ - elf_section_data (sec)->local_dynrel += 1; + /* Track dynamic relocs needed for local syms too. + We really need local syms available to do this + easily. Oh well. */ + + asection *s; + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, + sec, r_symndx); + if (s == NULL) + return false; + + head = ((struct elf_s390_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + } + + p = *head; + if (p == NULL || p->sec != sec) + { + bfd_size_type amt = sizeof *p; + p = ((struct elf_s390_dyn_relocs *) + bfd_alloc (htab->elf.dynobj, amt)); + if (p == NULL) + return false; + p->next = *head; + *head = p; + p->sec = sec; + p->count = 0; + p->pc_count = 0; } + + p->count += 1; + if (ELF64_R_TYPE (rel->r_info) == R_390_PC16 + || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL + || ELF64_R_TYPE (rel->r_info) == R_390_PC32 + || ELF64_R_TYPE (rel->r_info) == R_390_PC32DBL + || ELF64_R_TYPE (rel->r_info) == R_390_PC64) + p->pc_count += 1; } break; - + /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_390_GNU_VTINHERIT: if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return false; break; - + /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_390_GNU_VTENTRY: if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_offset)) return false; break; - + default: break; } @@ -900,13 +914,8 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) const Elf_Internal_Rela *rel, *relend; unsigned long r_symndx; struct elf_link_hash_entry *h; - bfd *dynobj; - elf_section_data (sec)->local_dynrel = 0; - - dynobj = elf_hash_table (info)->dynobj; - if (dynobj == NULL) - return true; + elf_section_data (sec)->local_dynrel = NULL; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -1205,10 +1214,10 @@ allocate_dynrelocs (h, inf) h->root.u.def.section = s; h->root.u.def.value = h->plt.offset; } - + /* Make room for this entry. */ s->_raw_size += PLT_ENTRY_SIZE; - + /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ htab->sgotplt->_raw_size += GOT_ENTRY_SIZE; @@ -1311,7 +1320,7 @@ allocate_dynrelocs (h, inf) eh->dyn_relocs = NULL; - keep: + keep: ; } /* Finally, allocate space. */ @@ -1398,12 +1407,26 @@ elf_s390_size_dynamic_sections (output_bfd, info) for (s = ibfd->sections; s != NULL; s = s->next) { - bfd_size_type count = elf_section_data (s)->local_dynrel; + struct elf_s390_dyn_relocs *p; - if (count != 0) + for (p = *((struct elf_s390_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + p != NULL; + p = p->next) { - srela = elf_section_data (s)->sreloc; - srela->_raw_size += count * sizeof (Elf64_External_Rela); + if (!bfd_is_abs_section (p->sec) + && bfd_is_abs_section (p->sec->output_section)) + { + /* Input section has been discarded, either because + it is a copy of a linkonce section or due to + linker script /DISCARD/, so we'll be discarding + the relocs too. */ + } + else + { + srela = elf_section_data (p->sec)->sreloc; + srela->_raw_size += p->count * sizeof (Elf64_External_Rela); + } } } @@ -1453,7 +1476,7 @@ elf_s390_size_dynamic_sections (output_bfd, info) { if (s->_raw_size != 0 && s != htab->srelplt) relocs = true; - + /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ s->reloc_count = 0; @@ -1521,11 +1544,11 @@ elf_s390_size_dynamic_sections (output_bfd, info) || !add_dynamic_entry (DT_RELASZ, 0) || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) return false; - + /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, (PTR) info); - + if ((info->flags & DF_TEXTREL) != 0) { if (!add_dynamic_entry (DT_TEXTREL, 0)) @@ -1875,8 +1898,14 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, case R_390_PC32: case R_390_PC32DBL: case R_390_PC64: + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + if (r_symndx == 0 + || (input_section->flags & SEC_ALLOC) == 0) + break; + if ((info->shared - && (input_section->flags & SEC_ALLOC) != 0 && ((r_type != R_390_PC16 && r_type != R_390_PC16DBL && r_type != R_390_PC32 @@ -1888,7 +1917,6 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)))) || (!info->shared - && (input_section->flags & SEC_ALLOC) != 0 && h != NULL && h->dynindx != -1 && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 @@ -1995,7 +2023,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, if (r != bfd_reloc_ok) { const char *name; - + if (h != NULL) name = h->root.root.string; else @@ -2008,10 +2036,10 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, if (*name == '\0') name = bfd_section_name (input_bfd, sec); } - + if (r == bfd_reloc_overflow) { - + if (! ((*info->callbacks->reloc_overflow) (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset))) @@ -2255,22 +2283,22 @@ elf_s390_finish_dynamic_sections (output_bfd, info) { Elf_Internal_Dyn dyn; asection *s; - + bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); - + switch (dyn.d_tag) { default: continue; - + case DT_PLTGOT: dyn.d_un.d_ptr = htab->sgot->output_section->vma; break; - + case DT_JMPREL: dyn.d_un.d_ptr = htab->srelplt->output_section->vma; break; - + case DT_PLTRELSZ: s = htab->srelplt->output_section; if (s->_cooked_size != 0) @@ -2278,7 +2306,7 @@ elf_s390_finish_dynamic_sections (output_bfd, info) else dyn.d_un.d_val = s->_raw_size; break; - + case DT_RELASZ: /* The procedure linkage table relocs (DT_JMPREL) should not be included in the overall relocs (DT_RELA). diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index cd0d914de5c..eef19aad5db 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -2103,7 +2103,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ - if (info->shared && (input_section->flags & SEC_ALLOC)) + if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC)) { switch (r_type) { diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 9be552d4181..df303e7e034 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1442,7 +1442,9 @@ elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section, case R_X86_64_64: /* FIXME: The ABI says the linker should make sure the value is the same when it's zeroextended to 64 bit. */ - if (info->shared && (input_section->flags & SEC_ALLOC) != 0) + if (info->shared + && r_symndx != 0 + && (input_section->flags & SEC_ALLOC) != 0) { Elf_Internal_Rela outrel; boolean skip, relocate; diff --git a/bfd/elflink.h b/bfd/elflink.h index d1db64a4664..a4fb88d5be5 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -6277,117 +6277,121 @@ elf_link_input_bfd (finfo, input_bfd) && o->reloc_count > 0) return false; - { - Elf_Internal_Rela *rel, *relend; - /* Run through the relocs looking for any against symbols - from discarded sections and section symbols from - removed link-once sections. Complain about relocs - against discarded sections. Zero relocs against removed - link-once sections. We should really complain if - anything in the final link tries to use it, but - DWARF-based exception handling might have an entry in - .eh_frame to describe a routine in the linkonce section, - and it turns out to be hard to remove the .eh_frame - entry too. FIXME. */ - rel = internal_relocs; - relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel; - for ( ; rel < relend; rel++) - { - unsigned long r_symndx = ELF_R_SYM (rel->r_info); + /* Run through the relocs looking for any against symbols + from discarded sections and section symbols from + removed link-once sections. Complain about relocs + against discarded sections. Zero relocs against removed + link-once sections. We should really complain if + anything in the final link tries to use it, but + DWARF-based exception handling might have an entry in + .eh_frame to describe a routine in the linkonce section, + and it turns out to be hard to remove the .eh_frame + entry too. FIXME. */ + if (!finfo->info->relocateable) + { + Elf_Internal_Rela *rel, *relend; - if (r_symndx >= locsymcount - || (elf_bad_symtab (input_bfd) - && finfo->sections[r_symndx] == NULL)) - { - struct elf_link_hash_entry *h; - - h = sym_hashes[r_symndx - extsymoff]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - /* Complain if the definition comes from a - discarded section. */ - if ((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && ! bfd_is_abs_section (h->root.u.def.section) - && bfd_is_abs_section (h->root.u.def.section - ->output_section)) - { + rel = internal_relocs; + relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel; + for ( ; rel < relend; rel++) + { + unsigned long r_symndx = ELF_R_SYM (rel->r_info); + + if (r_symndx >= locsymcount + || (elf_bad_symtab (input_bfd) + && finfo->sections[r_symndx] == NULL)) + { + struct elf_link_hash_entry *h; + + h = sym_hashes[r_symndx - extsymoff]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + /* Complain if the definition comes from a + discarded section. */ + if ((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && ! bfd_is_abs_section (h->root.u.def.section) + && bfd_is_abs_section (h->root.u.def.section + ->output_section)) + { #if BFD_VERSION_DATE < 20031005 - if ((o->flags & SEC_DEBUGGING) != 0) - { + if ((o->flags & SEC_DEBUGGING) != 0) + { #if BFD_VERSION_DATE > 20021005 - (*finfo->info->callbacks->warning) - (finfo->info, - _("warning: relocation against removed section; zeroing"), - NULL, input_bfd, o, rel->r_offset); + (*finfo->info->callbacks->warning) + (finfo->info, + _("warning: relocation against removed section; zeroing"), + NULL, input_bfd, o, rel->r_offset); #endif memset (rel, 0, sizeof (*rel)); - } - else + } + else #endif - { - if (! ((*finfo->info->callbacks->undefined_symbol) - (finfo->info, h->root.root.string, - input_bfd, o, rel->r_offset, - true))) - return false; - } - } - } - else - { - isym = finfo->internal_syms + r_symndx; - if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) - { - asection *sec = finfo->sections[r_symndx]; + { + if (! ((*finfo->info->callbacks->undefined_symbol) + (finfo->info, h->root.root.string, + input_bfd, o, rel->r_offset, + true))) + return false; + } + } + } + else + { + isym = finfo->internal_syms + r_symndx; + if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) + { + asection *sec = finfo->sections[r_symndx]; - if (sec != NULL - && ! bfd_is_abs_section (sec) - && bfd_is_abs_section (sec->output_section)) - { + if (sec != NULL + && ! bfd_is_abs_section (sec) + && bfd_is_abs_section (sec->output_section)) + { #if BFD_VERSION_DATE < 20031005 - if ((o->flags & SEC_DEBUGGING) != 0 - || (sec->flags & SEC_LINK_ONCE) != 0) - { + if ((o->flags & SEC_DEBUGGING) != 0 + || (sec->flags & SEC_LINK_ONCE) != 0) + { #if BFD_VERSION_DATE > 20021005 - (*finfo->info->callbacks->warning) - (finfo->info, - _("warning: relocation against removed section"), - NULL, input_bfd, o, rel->r_offset); + (*finfo->info->callbacks->warning) + (finfo->info, + _("warning: relocation against removed section"), + NULL, input_bfd, o, rel->r_offset); #endif - memset (rel, 0, sizeof (*rel)); - } - else + rel->r_info + = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info)); + rel->r_addend = 0; + } + else #endif - { - boolean ok; - const char *msg - = _("local symbols in discarded section %s"); - bfd_size_type amt - = strlen (sec->name) + strlen (msg) - 1; - char *buf = (char *) bfd_malloc (amt); - - if (buf != NULL) - sprintf (buf, msg, sec->name); - else - buf = (char *) sec->name; - ok = (*finfo->info->callbacks - ->undefined_symbol) (finfo->info, buf, - input_bfd, o, - rel->r_offset, - true); - if (buf != sec->name) - free (buf); - if (!ok) - return false; - } - } - } - } - } - } + { + boolean ok; + const char *msg + = _("local symbols in discarded section %s"); + bfd_size_type amt + = strlen (sec->name) + strlen (msg) - 1; + char *buf = (char *) bfd_malloc (amt); + + if (buf != NULL) + sprintf (buf, msg, sec->name); + else + buf = (char *) sec->name; + ok = (*finfo->info->callbacks + ->undefined_symbol) (finfo->info, buf, + input_bfd, o, + rel->r_offset, + true); + if (buf != sec->name) + free (buf); + if (!ok) + return false; + } + } + } + } + } + } /* Relocate the section by invoking a back end routine. diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index fbd264d2ce5..7f4a9910873 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -3560,6 +3560,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, /* Don't emit relocs for __GLOB_DATA_PTR on AIX. */ && (!h || strcmp (h->root.root.string, "__GLOB_DATA_PTR") != 0))) + && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0) { unsigned int dyn_r_type; @@ -3754,8 +3755,9 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_PCREL64MSB: case R_IA64_PCREL64LSB: /* Install a dynamic relocation for this reloc. */ - if (dynamic_symbol_p - || elfNN_ia64_aix_vec (info->hash->creator)) + if ((dynamic_symbol_p + || elfNN_ia64_aix_vec (info->hash->creator)) + && r_symndx != 0) { BFD_ASSERT (srel != NULL);