X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf32-ppc.c;h=89d1e94378263ee57c7ed8d0cdb1dc731d1447be;hb=f749f26eea052459c27e21d0d15f5fac060961dc;hp=8dfeca3e3a5eea9c7cdc07f3f47757c00dedc8cf;hpb=b00a0a86c40c681cf4b22a3630f85188ac849721;p=binutils-gdb.git diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 8dfeca3e3a5..89d1e943782 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -1329,14 +1329,14 @@ ppc_elf_section_from_shdr (bfd *abfd, return FALSE; newsect = hdr->bfd_section; - flags = bfd_get_section_flags (abfd, newsect); + flags = bfd_section_flags (newsect); if (hdr->sh_flags & SHF_EXCLUDE) flags |= SEC_EXCLUDE; if (hdr->sh_type == SHT_ORDERED) flags |= SEC_SORT_ENTRIES; - bfd_set_section_flags (abfd, newsect, flags); + bfd_set_section_flags (newsect, flags); return TRUE; } @@ -1674,7 +1674,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) /* Set the output section size, if it exists. */ asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); - if (asec && ! bfd_set_section_size (abfd, asec, 20 + num_entries * 4)) + if (asec && !bfd_set_section_size (asec, 20 + num_entries * 4)) { ibfd = abfd; /* xgettext:c-format */ @@ -1705,7 +1705,7 @@ ppc_elf_write_section (bfd *abfd ATTRIBUTE_UNUSED, /* Finally we can generate the output section. */ static void -ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) +ppc_final_write_processing (bfd *abfd) { bfd_byte *buffer; asection *asec; @@ -1756,6 +1756,13 @@ ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) apuinfo_list_finish (); } + +static bfd_boolean +ppc_elf_final_write_processing (bfd *abfd) +{ + ppc_final_write_processing (abfd); + return _bfd_elf_final_write_processing (abfd); +} static bfd_boolean is_nonpic_glink_stub (bfd *abfd, asection *glink, bfd_vma off) @@ -2330,7 +2337,7 @@ ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info) executable. */ flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - if (!bfd_set_section_flags (abfd, htab->elf.sgot, flags)) + if (!bfd_set_section_flags (htab->elf.sgot, flags)) return FALSE; } @@ -2383,7 +2390,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) if (p2align < htab->params->plt_stub_align) p2align = htab->params->plt_stub_align; if (s == NULL - || !bfd_set_section_alignment (abfd, s, p2align)) + || !bfd_set_section_alignment (s, p2align)) return FALSE; if (!info->no_ld_generated_unwind_info) @@ -2393,7 +2400,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section_anyway_with_flags (abfd, ".eh_frame", flags); htab->glink_eh_frame = s; if (s == NULL - || !bfd_set_section_alignment (abfd, s, 2)) + || !bfd_set_section_alignment (s, 2)) return FALSE; } @@ -2401,7 +2408,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section_anyway_with_flags (abfd, ".iplt", flags); htab->elf.iplt = s; if (s == NULL - || !bfd_set_section_alignment (abfd, s, 4)) + || !bfd_set_section_alignment (s, 4)) return FALSE; flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS @@ -2409,7 +2416,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section_anyway_with_flags (abfd, ".rela.iplt", flags); htab->elf.irelplt = s; if (s == NULL - || ! bfd_set_section_alignment (abfd, s, 2)) + || ! bfd_set_section_alignment (s, 2)) return FALSE; /* Local plt entries. */ @@ -2418,7 +2425,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) htab->pltlocal = bfd_make_section_anyway_with_flags (abfd, ".branch_lt", flags); if (htab->pltlocal == NULL - || ! bfd_set_section_alignment (abfd, htab->pltlocal, 2)) + || !bfd_set_section_alignment (htab->pltlocal, 2)) return FALSE; if (bfd_link_pic (info)) @@ -2428,7 +2435,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) htab->relpltlocal = bfd_make_section_anyway_with_flags (abfd, ".rela.branch_lt", flags); if (htab->relpltlocal == NULL - || ! bfd_set_section_alignment (abfd, htab->relpltlocal, 2)) + || !bfd_set_section_alignment (htab->relpltlocal, 2)) return FALSE; } @@ -2480,7 +2487,7 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section_anyway_with_flags (abfd, ".rela.sbss", flags); htab->relsbss = s; if (s == NULL - || ! bfd_set_section_alignment (abfd, s, 2)) + || !bfd_set_section_alignment (s, 2)) return FALSE; } @@ -2493,7 +2500,7 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (htab->plt_type == PLT_VXWORKS) /* The VxWorks PLT is a loaded section with contents. */ flags |= SEC_HAS_CONTENTS | SEC_LOAD | SEC_READONLY; - return bfd_set_section_flags (abfd, s, flags); + return bfd_set_section_flags (s, flags); } /* Copy the extra info we tack onto an elf_link_hash_entry. */ @@ -2732,7 +2739,7 @@ elf_allocate_pointer_linker_section (bfd *abfd, linker_section_ptr->lsect = lsect; *ptr_linker_section_ptr = linker_section_ptr; - if (!bfd_set_section_alignment (lsect->section->owner, lsect->section, 2)) + if (!bfd_set_section_alignment (lsect->section, 2)) return FALSE; linker_section_ptr->offset = lsect->section->size; lsect->section->size += 4; @@ -3089,11 +3096,6 @@ ppc_elf_check_relocs (bfd *abfd, /* Indirect .sdata relocation. */ case R_PPC_EMB_SDAI16: - if (bfd_link_pic (info)) - { - bad_shared_reloc (abfd, r_type); - return FALSE; - } htab->sdata[0].sym->ref_regular = 1; if (!elf_allocate_pointer_linker_section (abfd, &htab->sdata[0], h, rel)) @@ -3107,7 +3109,7 @@ ppc_elf_check_relocs (bfd *abfd, /* Indirect .sdata2 relocation. */ case R_PPC_EMB_SDA2I16: - if (bfd_link_pic (info)) + if (!bfd_link_executable (info)) { bad_shared_reloc (abfd, r_type); return FALSE; @@ -3153,7 +3155,7 @@ ppc_elf_check_relocs (bfd *abfd, break; case R_PPC_EMB_SDA2REL: - if (bfd_link_pic (info)) + if (!bfd_link_executable (info)) { bad_shared_reloc (abfd, r_type); return FALSE; @@ -3170,11 +3172,6 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_VLE_SDA21: case R_PPC_EMB_SDA21: case R_PPC_EMB_RELSDA: - if (bfd_link_pic (info)) - { - bad_shared_reloc (abfd, r_type); - return FALSE; - } if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; @@ -3187,11 +3184,6 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_EMB_NADDR16_LO: case R_PPC_EMB_NADDR16_HI: case R_PPC_EMB_NADDR16_HA: - if (bfd_link_pic (info)) - { - bad_shared_reloc (abfd, r_type); - return FALSE; - } if (h != NULL) h->non_got_ref = TRUE; break; @@ -4037,19 +4029,19 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED, /* The new PLT is a loaded section. */ if (htab->elf.splt != NULL - && !bfd_set_section_flags (htab->elf.dynobj, htab->elf.splt, flags)) + && !bfd_set_section_flags (htab->elf.splt, flags)) return -1; /* The new GOT is not executable. */ if (htab->elf.sgot != NULL - && !bfd_set_section_flags (htab->elf.dynobj, htab->elf.sgot, flags)) + && !bfd_set_section_flags (htab->elf.sgot, flags)) return -1; } else { /* Stop an unused .glink section from affecting .text alignment. */ if (htab->glink != NULL - && !bfd_set_section_alignment (htab->elf.dynobj, htab->glink, 0)) + && !bfd_set_section_alignment (htab->glink, 0)) return -1; } return htab->plt_type == PLT_NEW; @@ -4463,11 +4455,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, h = (struct elf_link_hash_entry *) h->root.u.i.link; } - is_local = FALSE; - if (h == NULL - || !h->def_dynamic) - is_local = TRUE; - + is_local = SYMBOL_REFERENCES_LOCAL (info, h); r_type = ELF32_R_TYPE (rel->r_info); /* If this section has old-style __tls_get_addr calls without marker relocs, then check that each @@ -5057,24 +5045,6 @@ got_entries_needed (int tls_mask) return need; } -/* Calculate size of relocs needed for symbol given its TLS_MASK and - NEEDed GOT entries. KNOWN says a TPREL offset can be calculated at - link time. */ - -static inline unsigned int -got_relocs_needed (int tls_mask, unsigned int need, bfd_boolean known) -{ - /* All the entries we allocated need relocs. - Except IE in executable with a local symbol. We could also omit - the DTPREL reloc on the second word of a GD entry under the same - condition as that for IE, but ld.so needs to differentiate - LD and GD entries. */ - if (known && (tls_mask & TLS_TLS) != 0 - && (tls_mask & (TLS_TPREL | TLS_GDIE)) != 0) - need -= 4; - return need * sizeof (Elf32_External_Rela) / 4; -} - /* If H is undefined, make it dynamic if that makes sense. */ static bfd_boolean @@ -5127,7 +5097,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) need = 0; if ((eh->tls_mask & (TLS_TLS | TLS_LD)) == (TLS_TLS | TLS_LD)) { - if (!eh->elf.def_dynamic) + if (SYMBOL_REFERENCES_LOCAL (info, &eh->elf)) /* We'll just use htab->tlsld_got.offset. This should always be the case. It's a little odd if we have a local dynamic reloc against a non-local symbol. */ @@ -5141,20 +5111,19 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) else { eh->elf.got.offset = allocate_got (htab, need); - if ((bfd_link_pic (info) + if (((bfd_link_pic (info) + && !((eh->tls_mask & TLS_TLS) != 0 + && bfd_link_executable (info) + && SYMBOL_REFERENCES_LOCAL (info, &eh->elf))) || (htab->elf.dynamic_sections_created && eh->elf.dynindx != -1 && !SYMBOL_REFERENCES_LOCAL (info, &eh->elf))) && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &eh->elf)) { asection *rsec; - bfd_boolean tprel_known = (bfd_link_executable (info) - && SYMBOL_REFERENCES_LOCAL (info, - &eh->elf)); - need = got_relocs_needed (eh->tls_mask, need, tprel_known); - if ((eh->tls_mask & (TLS_TLS | TLS_LD)) == (TLS_TLS | TLS_LD) - && eh->elf.def_dynamic) + need *= sizeof (Elf32_External_Rela) / 4; + if ((eh->tls_mask & (TLS_TLS | TLS_LD)) == (TLS_TLS | TLS_LD)) need -= sizeof (Elf32_External_Rela); rsec = htab->elf.srelgot; if (eh->elf.type == STT_GNU_IFUNC) @@ -5602,12 +5571,13 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, else { *local_got = allocate_got (htab, need); - if (bfd_link_pic (info)) + if (bfd_link_pic (info) + && !((*lgot_masks & TLS_TLS) != 0 + && bfd_link_executable (info))) { asection *srel; - bfd_boolean tprel_known = bfd_link_executable (info); - need = got_relocs_needed (*lgot_masks, need, tprel_known); + need *= sizeof (Elf32_External_Rela) / 4; srel = htab->elf.srelgot; if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC) srel = htab->elf.irelplt; @@ -5684,7 +5654,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, if (htab->tlsld_got.refcount > 0) { htab->tlsld_got.offset = allocate_got (htab, 8); - if (bfd_link_pic (info)) + if (bfd_link_dll (info)) htab->elf.srelgot->size += sizeof (Elf32_External_Rela); } else @@ -5831,8 +5801,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, { strip_section = (s->flags & SEC_KEEP) == 0; } - else if (CONST_STRNEQ (bfd_get_section_name (htab->elf.dynobj, s), - ".rela")) + else if (CONST_STRNEQ (bfd_section_name (s), ".rela")) { if (s->size != 0) { @@ -7758,8 +7727,7 @@ ppc_elf_relocate_section (bfd *output_bfd, indx = 0; if (tls_type == (TLS_TLS | TLS_LD) - && (h == NULL - || !h->def_dynamic)) + && SYMBOL_REFERENCES_LOCAL (info, h)) offp = &htab->tlsld_got.offset; else if (h != NULL) { @@ -7801,8 +7769,8 @@ ppc_elf_relocate_section (bfd *output_bfd, if (offp == &htab->tlsld_got.offset) tls_m = TLS_LD; - else if (h == NULL - || !h->def_dynamic) + else if ((tls_m & TLS_LD) != 0 + && SYMBOL_REFERENCES_LOCAL (info, h)) tls_m &= ~TLS_LD; /* We might have multiple got entries for this sym. @@ -7836,9 +7804,8 @@ ppc_elf_relocate_section (bfd *output_bfd, if (indx != 0 || (bfd_link_pic (info) && (h == NULL - || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h) - || offp == &htab->tlsld_got.offset) - && !(tls_ty == (TLS_TLS | TLS_TPREL) + || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) + && !(tls_ty != 0 && bfd_link_executable (info) && SYMBOL_REFERENCES_LOCAL (info, h)))) { @@ -7948,8 +7915,7 @@ ppc_elf_relocate_section (bfd *output_bfd, if (tls_type != (TLS_TLS | TLS_LD)) { if ((tls_mask & TLS_LD) != 0 - && !(h == NULL - || !h->def_dynamic)) + && !SYMBOL_REFERENCES_LOCAL (info, h)) off += 8; if (tls_type != (TLS_TLS | TLS_GD)) { @@ -8150,6 +8116,14 @@ ppc_elf_relocate_section (bfd *output_bfd, outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); + /* Optimize unaligned reloc use. */ + if ((r_type == R_PPC_ADDR32 && (outrel.r_offset & 3) != 0) + || (r_type == R_PPC_UADDR32 && (outrel.r_offset & 3) == 0)) + r_type ^= R_PPC_ADDR32 ^ R_PPC_UADDR32; + if ((r_type == R_PPC_ADDR16 && (outrel.r_offset & 1) != 0) + || (r_type == R_PPC_UADDR16 && (outrel.r_offset & 1) == 0)) + r_type ^= R_PPC_ADDR16 ^ R_PPC_UADDR16; + if (skip) memset (&outrel, 0, sizeof outrel); else if (!SYMBOL_REFERENCES_LOCAL (info, h)) @@ -8394,10 +8368,8 @@ ppc_elf_relocate_section (bfd *output_bfd, unresolved_reloc = TRUE; break; } - BFD_ASSERT (strcmp (bfd_get_section_name (sec->owner, sec), - ".got") == 0 - || strcmp (bfd_get_section_name (sec->owner, sec), - ".cgot") == 0); + BFD_ASSERT (strcmp (bfd_section_name (sec), ".got") == 0 + || strcmp (bfd_section_name (sec), ".cgot") == 0); addend -= sec->output_section->vma + sec->output_offset + 0x8000; break; @@ -8512,7 +8484,7 @@ ppc_elf_relocate_section (bfd *output_bfd, } addend -= SYM_VAL (sda); - name = bfd_get_section_name (output_bfd, sec->output_section); + name = bfd_section_name (sec->output_section); if (!(strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)) { @@ -8543,7 +8515,7 @@ ppc_elf_relocate_section (bfd *output_bfd, } addend -= SYM_VAL (sda); - name = bfd_get_section_name (output_bfd, sec->output_section); + name = bfd_section_name (sec->output_section); if (!(strcmp (name, ".sdata2") == 0 || strcmp (name, ".sbss2") == 0)) { @@ -8618,7 +8590,7 @@ ppc_elf_relocate_section (bfd *output_bfd, break; } - name = bfd_get_section_name (output_bfd, sec->output_section); + name = bfd_section_name (sec->output_section); if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0) { @@ -8725,7 +8697,7 @@ ppc_elf_relocate_section (bfd *output_bfd, break; } - name = bfd_get_section_name (output_bfd, sec->output_section); + name = bfd_section_name (sec->output_section); if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0) sda = htab->sdata[0].sym; @@ -10487,11 +10459,11 @@ ppc_elf_vxworks_add_symbol_hook (bfd *abfd, return ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp); } -static void -ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker) +static bfd_boolean +ppc_elf_vxworks_final_write_processing (bfd *abfd) { - ppc_elf_final_write_processing (abfd, linker); - elf_vxworks_final_write_processing (abfd, linker); + ppc_final_write_processing (abfd); + return elf_vxworks_final_write_processing (abfd); } /* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so