X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-ppc.c;h=8415f1ece2b8a6f72299e7e219372c8ca2b0caae;hb=0e1862bb401f47716446aef143b2bf7a4563f541;hp=8429e8f95b7ff23764b3118482f2c218d654205a;hpb=6cabe1ea460c54c17ac877b2541eccf91d6b4b9c;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 8429e8f95b..8415f1ece2 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -1,5 +1,5 @@ /* PowerPC-specific support for 32-bit ELF - Copyright (C) 1994-2014 Free Software Foundation, Inc. + Copyright (C) 1994-2015 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -187,8 +187,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = { /* This reloc does nothing. */ HOWTO (R_PPC_NONE, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -2019,19 +2019,28 @@ ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst) { + unsigned int r_type; + /* Initialize howto table if not already done. */ if (!ppc_elf_howto_table[R_PPC_ADDR32]) ppc_elf_howto_init (); - BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max); - cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)]; + r_type = ELF32_R_TYPE (dst->r_info); + if (r_type >= R_PPC_max) + { + (*_bfd_error_handler) (_("%B: unrecognised PPC reloc number: %d"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + r_type = R_PPC_NONE; + } + cache_ptr->howto = ppc_elf_howto_table[r_type]; /* Just because the above assert didn't trigger doesn't mean that ELF32_R_TYPE (dst->r_info) is necessarily a valid relocation. */ if (!cache_ptr->howto) { (*_bfd_error_handler) (_("%B: invalid relocation type %d"), - abfd, ELF32_R_TYPE (dst->r_info)); + abfd, r_type); bfd_set_error (bfd_error_bad_value); cache_ptr->howto = ppc_elf_howto_table[R_PPC_NONE]; @@ -2057,9 +2066,6 @@ ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED, return bfd_reloc_ok; } - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) - return bfd_reloc_outofrange; - if (bfd_is_com_section (symbol->section)) relocation = 0; else @@ -2919,7 +2925,6 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, } count = relplt->size / sizeof (Elf32_External_Rela); - stub_vma = glink_vma - (bfd_vma) count * 16; /* If the stubs are those for -shared/-pie then we might have multiple stubs for each plt entry. If that is the case then there is no way to associate stubs with their plt entries short @@ -2950,9 +2955,10 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, if (s == NULL) return -1; + stub_vma = glink_vma; names = (char *) (s + count + 1 + (resolv_vma != 0)); - p = relplt->relocation; - for (i = 0; i < count; i++, p++) + p = relplt->relocation + count - 1; + for (i = 0; i < count; i++) { size_t len; @@ -2963,6 +2969,9 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, s->flags |= BSF_GLOBAL; s->flags |= BSF_SYNTHETIC; s->section = glink; + stub_vma -= 16; + if (strcmp ((*p->sym_ptr_ptr)->name, "__tls_get_addr_opt") == 0) + stub_vma -= 32; s->value = stub_vma - glink->vma; s->name = names; s->udata.p = NULL; @@ -2979,7 +2988,7 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, memcpy (names, "@plt", sizeof ("@plt")); names += sizeof ("@plt"); ++s; - stub_vma += 16; + --p; } /* Add a symbol at the start of the glink branch table. */ @@ -3071,7 +3080,7 @@ must_be_dyn_reloc (struct bfd_link_info *info, case R_PPC_TPREL16_LO: case R_PPC_TPREL16_HI: case R_PPC_TPREL16_HA: - return !info->executable; + return !bfd_link_executable (info); } } @@ -3126,7 +3135,11 @@ struct ppc_elf_link_hash_entry /* Nonzero if we have seen a small data relocation referring to this symbol. */ - unsigned char has_sda_refs; + unsigned char has_sda_refs : 1; + + /* Flag use of given relocations. */ + unsigned char has_addr16_ha : 1; + unsigned char has_addr16_lo : 1; }; #define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent)) @@ -3250,7 +3263,7 @@ static struct bfd_link_hash_table * ppc_elf_link_hash_table_create (bfd *abfd) { struct ppc_elf_link_hash_table *ret; - static struct ppc_elf_params default_params = { PLT_OLD, 0, 1, 0, 0, 12 }; + static struct ppc_elf_params default_params = { PLT_OLD, 0, 1, 0, 0, 12, 0 }; ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table)); if (ret == NULL) @@ -3452,7 +3465,7 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (s == NULL) return FALSE; - if (! info->shared) + if (! bfd_link_pic (info)) { htab->relbss = bfd_get_linker_section (abfd, ".rela.bss"); flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS @@ -3609,7 +3622,7 @@ ppc_elf_add_symbol_hook (bfd *abfd, bfd_vma *valp) { if (sym->st_shndx == SHN_COMMON - && !info->relocatable + && !bfd_link_relocatable (info) && is_ppc_elf (info->output_bfd) && sym->st_size <= elf_gp_size (abfd)) { @@ -3640,7 +3653,7 @@ ppc_elf_add_symbol_hook (bfd *abfd, || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; + elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; return TRUE; } @@ -3863,7 +3876,7 @@ ppc_elf_check_relocs (bfd *abfd, asection *got2, *sreloc; struct elf_link_hash_entry *tga; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; /* Don't do anything special with non-loaded, non-alloced sections. @@ -3960,14 +3973,14 @@ ppc_elf_check_relocs (bfd *abfd, /* STT_GNU_IFUNC symbols must have a PLT entry; In a non-pie executable even when there are no plt calls. */ - if (!info->shared + if (!bfd_link_pic (info) || is_branch_reloc (r_type)) { bfd_vma addend = 0; if (r_type == R_PPC_PLTREL24) { ppc_elf_tdata (abfd)->makes_plt_call = 1; - if (info->shared) + if (bfd_link_pic (info)) addend = rel->r_addend; } if (!update_plt_info (abfd, ifunc, got2, addend)) @@ -4018,7 +4031,7 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_GOT_TPREL16_LO: case R_PPC_GOT_TPREL16_HI: case R_PPC_GOT_TPREL16_HA: - if (info->shared) + if (bfd_link_pic (info)) info->flags |= DF_STATIC_TLS; tls_type = TLS_TLS | TLS_TPREL; goto dogottls; @@ -4057,7 +4070,7 @@ ppc_elf_check_relocs (bfd *abfd, /* We may also need a plt entry if the symbol turns out to be an ifunc. */ - if (h != NULL && !info->shared) + if (h != NULL && !bfd_link_pic (info)) { if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) return FALSE; @@ -4066,7 +4079,7 @@ ppc_elf_check_relocs (bfd *abfd, /* Indirect .sdata relocation. */ case R_PPC_EMB_SDAI16: - if (info->shared) + if (bfd_link_pic (info)) { bad_shared_reloc (abfd, r_type); return FALSE; @@ -4084,7 +4097,7 @@ ppc_elf_check_relocs (bfd *abfd, /* Indirect .sdata2 relocation. */ case R_PPC_EMB_SDA2I16: - if (info->shared) + if (bfd_link_pic (info)) { bad_shared_reloc (abfd, r_type); return FALSE; @@ -4129,7 +4142,7 @@ ppc_elf_check_relocs (bfd *abfd, break; case R_PPC_EMB_SDA2REL: - if (info->shared) + if (bfd_link_pic (info)) { bad_shared_reloc (abfd, r_type); return FALSE; @@ -4146,7 +4159,7 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_VLE_SDA21: case R_PPC_EMB_SDA21: case R_PPC_EMB_RELSDA: - if (info->shared) + if (bfd_link_pic (info)) { bad_shared_reloc (abfd, r_type); return FALSE; @@ -4163,7 +4176,7 @@ 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 (info->shared) + if (bfd_link_pic (info)) { bad_shared_reloc (abfd, r_type); return FALSE; @@ -4207,7 +4220,7 @@ ppc_elf_check_relocs (bfd *abfd, if (r_type == R_PPC_PLTREL24) { ppc_elf_tdata (abfd)->makes_plt_call = 1; - if (info->shared) + if (bfd_link_pic (info)) addend = rel->r_addend; } h->needs_plt = 1; @@ -4273,7 +4286,7 @@ ppc_elf_check_relocs (bfd *abfd, } if (h != NULL && h->type == STT_GNU_IFUNC) { - if (info->shared) + if (bfd_link_pic (info)) { info->callbacks->einfo (_("%P: %H: @local call to ifunc %s\n"), abfd, sec, rel->r_offset, @@ -4309,7 +4322,7 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_TPREL16_LO: case R_PPC_TPREL16_HI: case R_PPC_TPREL16_HA: - if (info->shared) + if (bfd_link_pic (info)) info->flags |= DF_STATIC_TLS; goto dodyn; @@ -4322,7 +4335,7 @@ ppc_elf_check_relocs (bfd *abfd, if (h == NULL && got2 != NULL && (sec->flags & SEC_CODE) != 0 - && info->shared + && bfd_link_pic (info) && htab->plt_type == PLT_UNSET) { /* Old -fPIC gcc code has .long LCTOC1-LCFx just before @@ -4357,7 +4370,7 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_ADDR16_HA: case R_PPC_UADDR32: case R_PPC_UADDR16: - if (h != NULL && !info->shared) + if (h != NULL && !bfd_link_pic (info)) { /* We may need a plt entry if the symbol turns out to be a function defined in a dynamic object. */ @@ -4367,6 +4380,10 @@ ppc_elf_check_relocs (bfd *abfd, /* We may need a copy reloc too. */ h->non_got_ref = 1; h->pointer_equality_needed = 1; + if (r_type == R_PPC_ADDR16_HA) + ppc_elf_hash_entry (h)->has_addr16_ha = 1; + if (r_type == R_PPC_ADDR16_LO) + ppc_elf_hash_entry (h)->has_addr16_lo = 1; } goto dodyn; @@ -4391,7 +4408,7 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_ADDR14: case R_PPC_ADDR14_BRTAKEN: case R_PPC_ADDR14_BRNTAKEN: - if (h != NULL && !info->shared) + if (h != NULL && !bfd_link_pic (info)) { /* We may need a plt entry if the symbol turns out to be a function defined in a dynamic object. */ @@ -4423,14 +4440,14 @@ ppc_elf_check_relocs (bfd *abfd, may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the symbol. */ - if ((info->shared + if ((bfd_link_pic (info) && (must_be_dyn_reloc (info, r_type) || (h != NULL && (!SYMBOLIC_BIND (info, h) || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) || (ELIMINATE_COPY_RELOCS - && !info->shared + && !bfd_link_pic (info) && h != NULL && (h->root.type == bfd_link_hash_defweak || !h->def_regular))) @@ -4801,7 +4818,7 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED, if (htab->params->plt_style == PLT_OLD) htab->plt_type = PLT_OLD; - else if (info->shared + else if (bfd_link_pic (info) && htab->elf.dynamic_sections_created && (h = elf_link_hash_lookup (&htab->elf, "_mcount", FALSE, FALSE, TRUE)) != NULL @@ -4917,7 +4934,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd, const Elf_Internal_Rela *rel, *relend; asection *got2; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; if ((sec->flags & SEC_ALLOC) == 0) @@ -4963,7 +4980,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd, if (!htab->is_vxworks && h == NULL && local_got_refcounts != NULL - && (!info->shared + && (!bfd_link_pic (info) || is_branch_reloc (r_type))) { struct plt_entry **local_plt = (struct plt_entry **) @@ -4976,7 +4993,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd, bfd_vma addend = 0; struct plt_entry *ent; - if (r_type == R_PPC_PLTREL24 && info->shared) + if (r_type == R_PPC_PLTREL24 && bfd_link_pic (info)) addend = rel->r_addend; ent = find_plt_ent (ifunc, got2, addend); if (ent->plt.refcount > 0) @@ -5011,7 +5028,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd, { if (h->got.refcount > 0) h->got.refcount--; - if (!info->shared) + if (!bfd_link_pic (info)) { struct plt_entry *ent; @@ -5047,7 +5064,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd, case R_PPC_ADDR14_BRNTAKEN: case R_PPC_UADDR32: case R_PPC_UADDR16: - if (info->shared) + if (bfd_link_pic (info)) break; case R_PPC_PLT32: @@ -5061,7 +5078,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd, bfd_vma addend = 0; struct plt_entry *ent; - if (r_type == R_PPC_PLTREL24 && info->shared) + if (r_type == R_PPC_PLTREL24 && bfd_link_pic (info)) addend = rel->r_addend; ent = find_plt_ent (&h->plt.plist, got2, addend); if (ent != NULL && ent->plt.refcount > 0) @@ -5087,6 +5104,9 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) htab = ppc_elf_hash_table (info); htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", FALSE, FALSE, TRUE); + if (htab->plt_type != PLT_NEW) + htab->params->no_tls_get_addr_opt = TRUE; + if (!htab->params->no_tls_get_addr_opt) { struct elf_link_hash_entry *opt, *tga; @@ -5184,7 +5204,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct ppc_elf_link_hash_table *htab; int pass; - if (info->relocatable || !info->executable) + if (bfd_link_relocatable (info) || !bfd_link_executable (info)) return TRUE; htab = ppc_elf_hash_table (info); @@ -5357,7 +5377,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct plt_entry *ent; bfd_vma addend = 0; - if (info->shared + if (bfd_link_pic (info) && ELF32_R_TYPE (rel[1].r_info) == R_PPC_PLTREL24) addend = rel[1].r_addend; ent = find_plt_ent (&htab->tls_get_addr->plt.plist, @@ -5542,6 +5562,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, && !readonly_dynrelocs (h)) h->non_got_ref = 0; } + h->protected_def = 0; return TRUE; } else @@ -5568,13 +5589,42 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, only references to the symbol are via the global offset table. For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ - if (info->shared) - return TRUE; + if (bfd_link_pic (info)) + { + h->protected_def = 0; + return TRUE; + } /* If there are no references to this symbol that do not use the GOT, we don't need to generate a copy reloc. */ if (!h->non_got_ref) - return TRUE; + { + h->protected_def = 0; + return TRUE; + } + + /* Protected variables do not work with .dynbss. The copy in + .dynbss won't be used by the shared library with the protected + definition for the variable. Editing to PIC, or text relocations + are preferable to an incorrect program. */ + if (h->protected_def) + { + if (ELIMINATE_COPY_RELOCS + && ppc_elf_hash_entry (h)->has_addr16_ha + && ppc_elf_hash_entry (h)->has_addr16_lo + && htab->params->pic_fixup == 0 + && info->disable_target_specific_optimizations <= 1) + htab->params->pic_fixup = 1; + h->non_got_ref = 0; + return TRUE; + } + + /* If -z nocopyreloc was given, we won't generate them either. */ + if (info->nocopyreloc) + { + h->non_got_ref = 0; + return TRUE; + } /* 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. @@ -5648,7 +5698,7 @@ add_stub_sym (struct plt_entry *ent, const char *stub; struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); - if (info->shared) + if (bfd_link_pic (info)) stub = ".plt_pic32."; else stub = ".plt_call32."; @@ -5679,6 +5729,7 @@ add_stub_sym (struct plt_entry *ent, sh->ref_regular_nonweak = 1; sh->forced_local = 1; sh->non_elf = 0; + sh->root.linker_def = 1; } return TRUE; } @@ -5756,7 +5807,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } dyn = htab->elf.dynamic_sections_created; - if (info->shared + if (bfd_link_pic (info) || h->type == STT_GNU_IFUNC || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) { @@ -5774,7 +5825,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) ent->plt.offset = plt_offset; s = htab->glink; - if (!doneone || info->shared) + if (!doneone || bfd_link_pic (info)) { glink_offset = s->size; s->size += GLINK_ENTRY_SIZE; @@ -5783,7 +5834,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) s->size += TLS_GET_ADDR_GLINK_SIZE - GLINK_ENTRY_SIZE; } if (!doneone - && !info->shared + && !bfd_link_pic (info) && h->def_dynamic && !h->def_regular) { @@ -5822,7 +5873,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) relocations, and is required to make function pointers compare as equal between the normal executable and the shared library. */ - if (! info->shared + if (! bfd_link_pic (info) && h->def_dynamic && !h->def_regular) { @@ -5856,7 +5907,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (htab->plt_type == PLT_VXWORKS) { /* Allocate space for the unloaded relocations. */ - if (!info->shared + if (!bfd_link_pic (info) && htab->elf.dynamic_sections_created) { if (ent->plt.offset @@ -5899,7 +5950,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } eh = (struct ppc_elf_link_hash_entry *) h; - if (eh->elf.got.refcount > 0) + if (eh->elf.got.refcount > 0 + || (ELIMINATE_COPY_RELOCS + && !eh->elf.def_regular + && eh->elf.protected_def + && eh->has_addr16_ha + && eh->has_addr16_lo + && htab->params->pic_fixup > 0)) { bfd_boolean dyn; unsigned int need; @@ -5942,7 +5999,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { eh->elf.got.offset = allocate_got (htab, need); dyn = htab->elf.dynamic_sections_created; - if ((info->shared + if ((bfd_link_pic (info) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf)) && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT || eh->elf.root.type != bfd_link_hash_undefweak)) @@ -5973,7 +6030,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) space for relocs that have become local due to symbol visibility changes. */ - if (info->shared) + if (bfd_link_pic (info)) { /* Relocs that use pc_count are those that appear on a call insn, or certain REL relocs (see must_be_dyn_reloc) that can be @@ -6042,7 +6099,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) dynamic. */ if (!h->non_got_ref - && !h->def_regular) + && !h->def_regular + && !(h->protected_def + && eh->has_addr16_ha + && eh->has_addr16_lo + && htab->params->pic_fixup > 0)) { /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ @@ -6130,7 +6191,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, if (elf_hash_table (info)->dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ - if (info->executable) + if (bfd_link_executable (info)) { s = bfd_get_linker_section (htab->elf.dynobj, ".interp"); BFD_ASSERT (s != NULL); @@ -6230,7 +6291,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, else { *local_got = allocate_got (htab, need); - if (info->shared) + if (bfd_link_pic (info)) { asection *srel = htab->relgot; if ((*lgot_masks & PLT_IFUNC) != 0) @@ -6265,7 +6326,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, ent->plt.offset = plt_offset; s = htab->glink; - if (!doneone || info->shared) + if (!doneone || bfd_link_pic (info)) { glink_offset = s->size; s->size += GLINK_ENTRY_SIZE; @@ -6289,7 +6350,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, if (htab->tlsld_got.refcount > 0) { htab->tlsld_got.offset = allocate_got (htab, 8); - if (info->shared) + if (bfd_link_pic (info)) htab->relgot->size += sizeof (Elf32_External_Rela); } else @@ -6313,7 +6374,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, htab->elf.hgot->root.u.def.value = g_o_t; } - if (info->shared) + if (bfd_link_pic (info)) { struct elf_link_hash_entry *sda = htab->sdata[0].sym; @@ -6360,6 +6421,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, sh->ref_regular_nonweak = 1; sh->forced_local = 1; sh->non_elf = 0; + sh->root.linker_def = 1; } sh = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve", TRUE, FALSE, FALSE); @@ -6375,6 +6437,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, sh->ref_regular_nonweak = 1; sh->forced_local = 1; sh->non_elf = 0; + sh->root.linker_def = 1; } } } @@ -6387,7 +6450,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, { s = htab->glink_eh_frame; s->size = sizeof (glink_eh_frame_cie) + 20; - if (info->shared) + if (bfd_link_pic (info)) { s->size += 4; if (htab->glink->size - GLINK_PLTRESOLVE + 8 >= 256) @@ -6484,7 +6547,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) - if (info->executable) + if (bfd_link_executable (info)) { if (!add_dynamic_entry (DT_DEBUG, 0)) return FALSE; @@ -6563,7 +6626,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, /* Augmentation. */ p += 1; - if (info->shared + if (bfd_link_pic (info) && htab->elf.dynamic_sections_created) { bfd_vma adv = (htab->glink->size - GLINK_PLTRESOLVE + 8) >> 2; @@ -6681,6 +6744,7 @@ static const int stub_entry[] = struct ppc_elf_relax_info { unsigned int workaround_size; + unsigned int picfixup_size; }; /* This function implements long branch trampolines, and the ppc476 @@ -6694,9 +6758,9 @@ ppc_elf_relax_section (bfd *abfd, struct bfd_link_info *link_info, bfd_boolean *again) { - struct one_fixup + struct one_branch_fixup { - struct one_fixup *next; + struct one_branch_fixup *next; asection *tsec; /* Final link, can use the symbol offset. For a relocatable link we use the symbol's index. */ @@ -6709,12 +6773,12 @@ ppc_elf_relax_section (bfd *abfd, Elf_Internal_Sym *isymbuf = NULL; Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend = NULL; - struct one_fixup *fixups = NULL; + struct one_branch_fixup *branch_fixups = NULL; struct ppc_elf_relax_info *relax_info = NULL; unsigned changes = 0; bfd_boolean workaround_change; struct ppc_elf_link_hash_table *htab; - bfd_size_type trampbase, trampoff, newsize; + bfd_size_type trampbase, trampoff, newsize, picfixup_size; asection *got2; bfd_boolean maybe_pasted; @@ -6730,7 +6794,7 @@ ppc_elf_relax_section (bfd *abfd, /* We cannot represent the required PIC relocs in the output, so don't do anything. The linker doesn't support mixing -shared and -r anyway. */ - if (link_info->relocatable && link_info->shared) + if (bfd_link_relocatable (link_info) && bfd_link_pic (link_info)) return TRUE; htab = ppc_elf_hash_table (link_info); @@ -6746,7 +6810,8 @@ ppc_elf_relax_section (bfd *abfd, || isec->sec_info_type == SEC_INFO_TYPE_TARGET); isec->sec_info_type = SEC_INFO_TYPE_TARGET; - if (htab->params->ppc476_workaround) + if (htab->params->ppc476_workaround + || htab->params->pic_fixup > 0) { if (elf_section_data (isec)->sec_info == NULL) { @@ -6767,8 +6832,9 @@ ppc_elf_relax_section (bfd *abfd, trampoff += 4; symtab_hdr = &elf_symtab_hdr (abfd); - - if (htab->params->branch_trampolines) + picfixup_size = 0; + if (htab->params->branch_trampolines + || htab->params->pic_fixup > 0) { /* Get a copy of the native relocations. */ if (isec->reloc_count != 0) @@ -6787,9 +6853,9 @@ ppc_elf_relax_section (bfd *abfd, unsigned long r_type = ELF32_R_TYPE (irel->r_info); bfd_vma toff, roff; asection *tsec; - struct one_fixup *f; + struct one_branch_fixup *f; size_t insn_offset = 0; - bfd_vma max_branch_offset, val; + bfd_vma max_branch_offset = 0, val; bfd_byte *hit_addr; unsigned long t0; struct elf_link_hash_entry *h; @@ -6810,6 +6876,11 @@ ppc_elf_relax_section (bfd *abfd, max_branch_offset = 1 << 15; break; + case R_PPC_ADDR16_HA: + if (htab->params->pic_fixup > 0) + break; + continue; + default: continue; } @@ -6867,7 +6938,7 @@ ppc_elf_relax_section (bfd *abfd, || h->root.type == bfd_link_hash_undefweak) { tsec = bfd_und_section_ptr; - toff = link_info->relocatable ? indx : 0; + toff = bfd_link_relocatable (link_info) ? indx : 0; } else continue; @@ -6875,8 +6946,8 @@ ppc_elf_relax_section (bfd *abfd, /* If this branch is to __tls_get_addr then we may later optimise away the call. We won't be needing a long- branch stub in that case. */ - if (link_info->executable - && !link_info->relocatable + if (bfd_link_executable (link_info) + && !bfd_link_relocatable (link_info) && h == htab->tls_get_addr && irel != internal_relocs) { @@ -6931,6 +7002,17 @@ ppc_elf_relax_section (bfd *abfd, sym_type = h->type; } + if (r_type == R_PPC_ADDR16_HA) + { + if (h != NULL + && !h->def_regular + && h->protected_def + && ppc_elf_hash_entry (h)->has_addr16_ha + && ppc_elf_hash_entry (h)->has_addr16_lo) + picfixup_size += 12; + continue; + } + /* The condition here under which we call find_plt_ent must match that in relocate_section. If we call find_plt_ent here but not in relocate_section, or vice versa, then the branch @@ -6956,7 +7038,7 @@ ppc_elf_relax_section (bfd *abfd, bfd_vma addend = 0; struct plt_entry *ent; - if (r_type == R_PPC_PLTREL24 && link_info->shared) + if (r_type == R_PPC_PLTREL24 && bfd_link_pic (link_info)) addend = irel->r_addend; ent = find_plt_ent (plist, got2, addend); if (ent != NULL) @@ -7022,7 +7104,7 @@ ppc_elf_relax_section (bfd *abfd, toff += irel->r_addend; /* Attempted -shared link of non-pic code loses. */ - if ((!link_info->relocatable + if ((!bfd_link_relocatable (link_info) && tsec == bfd_und_section_ptr) || tsec->output_section == NULL || (tsec->owner != NULL @@ -7033,7 +7115,7 @@ ppc_elf_relax_section (bfd *abfd, /* If the branch is in range, no need to do anything. */ if (tsec != bfd_und_section_ptr - && (!link_info->relocatable + && (!bfd_link_relocatable (link_info) /* A relocatable link may have sections moved during final link, so do not presume they remain in range. */ || tsec->output_section == isec->output_section)) @@ -7048,7 +7130,7 @@ ppc_elf_relax_section (bfd *abfd, } /* Look for an existing fixup to this address. */ - for (f = fixups; f ; f = f->next) + for (f = branch_fixups; f ; f = f->next) if (f->tsec == tsec && f->toff == toff) break; @@ -7063,7 +7145,7 @@ ppc_elf_relax_section (bfd *abfd, one. We'll report an error later. */ continue; - if (link_info->shared) + if (bfd_link_pic (link_info)) { size = 4 * ARRAY_SIZE (shared_stub_entry); insn_offset = 12; @@ -7093,11 +7175,11 @@ ppc_elf_relax_section (bfd *abfd, /* Record the fixup so we don't do it again this section. */ f = bfd_malloc (sizeof (*f)); - f->next = fixups; + f->next = branch_fixups; f->tsec = tsec; f->toff = toff; f->trampoff = trampoff; - fixups = f; + branch_fixups = f; trampoff += size; changes++; @@ -7147,10 +7229,10 @@ ppc_elf_relax_section (bfd *abfd, } } - while (fixups != NULL) + while (branch_fixups != NULL) { - struct one_fixup *f = fixups; - fixups = fixups->next; + struct one_branch_fixup *f = branch_fixups; + branch_fixups = branch_fixups->next; free (f); } } @@ -7158,7 +7240,7 @@ ppc_elf_relax_section (bfd *abfd, workaround_change = FALSE; newsize = trampoff; if (htab->params->ppc476_workaround - && (!link_info->relocatable + && (!bfd_link_relocatable (link_info) || isec->output_section->alignment_power >= htab->params->pagesize_p2)) { bfd_vma addr, end_addr; @@ -7187,7 +7269,15 @@ ppc_elf_relax_section (bfd *abfd, newsize = trampoff + relax_info->workaround_size; } - if (changes || workaround_change) + if (htab->params->pic_fixup > 0) + { + picfixup_size -= relax_info->picfixup_size; + if (picfixup_size != 0) + relax_info->picfixup_size += picfixup_size; + newsize += relax_info->picfixup_size; + } + + if (changes != 0 || picfixup_size != 0 || workaround_change) isec->size = newsize; if (isymbuf != NULL @@ -7214,6 +7304,7 @@ ppc_elf_relax_section (bfd *abfd, } } + changes += picfixup_size; if (changes != 0) { /* Append sufficient NOP relocs so we can write out relocation @@ -7248,10 +7339,10 @@ ppc_elf_relax_section (bfd *abfd, return TRUE; error_return: - while (fixups != NULL) + while (branch_fixups != NULL) { - struct one_fixup *f = fixups; - fixups = fixups->next; + struct one_branch_fixup *f = branch_fixups; + branch_fixups = branch_fixups->next; free (f); } if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) @@ -7357,7 +7448,7 @@ write_glink_stub (struct plt_entry *ent, asection *plt_sec, unsigned char *p, + plt_sec->output_section->vma + plt_sec->output_offset); - if (info->shared) + if (bfd_link_pic (info)) { bfd_vma got = 0; @@ -7567,13 +7658,15 @@ ppc_elf_relocate_section (bfd *output_bfd, bfd_boolean ret = TRUE; bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0); bfd_boolean is_vxworks_tls; + unsigned int picfixup_size = 0; + struct ppc_elf_relax_info *relax_info = NULL; #ifdef DEBUG _bfd_error_handler ("ppc_elf_relocate_section called for %B section %A, " "%ld relocations%s", input_bfd, input_section, (long) input_section->reloc_count, - (info->relocatable) ? " (relocatable)" : ""); + (bfd_link_relocatable (info)) ? " (relocatable)" : ""); #endif got2 = bfd_get_section_by_name (input_bfd, ".got2"); @@ -7588,9 +7681,11 @@ ppc_elf_relocate_section (bfd *output_bfd, sym_hashes = elf_sym_hashes (input_bfd); /* We have to handle relocations in vxworks .tls_vars sections specially, because the dynamic loader is 'weird'. */ - is_vxworks_tls = (htab->is_vxworks && info->shared + is_vxworks_tls = (htab->is_vxworks && bfd_link_pic (info) && !strcmp (input_section->output_section->name, ".tls_vars")); + if (input_section->sec_info_type == SEC_INFO_TYPE_TARGET) + relax_info = elf_section_data (input_section)->sec_info; rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) @@ -7652,7 +7747,7 @@ ppc_elf_relocate_section (bfd *output_bfd, rel, 1, relend, howto, 0, contents); } - if (info->relocatable) + if (bfd_link_relocatable (info)) { if (got2 != NULL && r_type == R_PPC_PLTREL24 @@ -7754,8 +7849,8 @@ ppc_elf_relocate_section (bfd *output_bfd, + R_PPC_GOT_TPREL16); else { - bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); rel->r_offset -= d_offset; + bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); r_type = R_PPC_NONE; } rel->r_info = ELF32_R_INFO (r_symndx, r_type); @@ -7788,12 +7883,16 @@ ppc_elf_relocate_section (bfd *output_bfd, && branch_reloc_hash_match (input_bfd, rel + 1, htab->tls_get_addr)) offset = rel[1].r_offset; + /* We read the low GOT_TLS insn because we need to keep + the destination reg. It may be something other than + the usual r3, and moved to r3 before the call by + intervening code. */ + insn1 = bfd_get_32 (output_bfd, + contents + rel->r_offset - d_offset); if ((tls_mask & tls_gd) != 0) { /* IE */ - insn1 = bfd_get_32 (output_bfd, - contents + rel->r_offset - d_offset); - insn1 &= (1 << 26) - 1; + insn1 &= (0x1f << 21) | (0x1f << 16); insn1 |= 32 << 26; /* lwz */ if (offset != (bfd_vma) -1) { @@ -7808,7 +7907,8 @@ ppc_elf_relocate_section (bfd *output_bfd, else { /* LE */ - insn1 = 0x3c620000; /* addis 3,2,0 */ + insn1 &= 0x1f << 21; + insn1 |= 0x3c020000; /* addis r,2,0 */ if (tls_gd == 0) { /* Was an LD reloc. */ @@ -7943,6 +8043,114 @@ ppc_elf_relocate_section (bfd *output_bfd, } } + if (ELIMINATE_COPY_RELOCS + && h != NULL + && !h->def_regular + && h->protected_def + && ppc_elf_hash_entry (h)->has_addr16_ha + && ppc_elf_hash_entry (h)->has_addr16_lo + && htab->params->pic_fixup > 0) + { + /* Convert lis;addi or lis;load/store accessing a protected + variable defined in a shared library to PIC. */ + unsigned int insn; + + if (r_type == R_PPC_ADDR16_HA) + { + insn = bfd_get_32 (output_bfd, + contents + rel->r_offset - d_offset); + if ((insn & (0x3f << 26)) == (15u << 26) + && (insn & (0x1f << 16)) == 0 /* lis */) + { + bfd_byte *p; + bfd_vma off; + bfd_vma got_addr; + + p = (contents + input_section->size + - relax_info->workaround_size + - relax_info->picfixup_size + + picfixup_size); + off = (p - contents) - (rel->r_offset - d_offset); + if (off > 0x1fffffc || (off & 3) != 0) + info->callbacks->einfo + (_("%P: %H: fixup branch overflow\n"), + input_bfd, input_section, rel->r_offset); + + bfd_put_32 (output_bfd, B | off, + contents + rel->r_offset - d_offset); + got_addr = (htab->got->output_section->vma + + htab->got->output_offset + + (h->got.offset & ~1)); + rel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_HA); + rel->r_addend = got_addr; + rel->r_offset = (p - contents) + d_offset; + insn &= ~0xffff; + insn |= ((unsigned int )(got_addr + 0x8000) >> 16) & 0xffff; + bfd_put_32 (output_bfd, insn, p); + + /* Convert lis to lwz, loading address from GOT. */ + insn &= ~0xffff; + insn ^= (32u ^ 15u) << 26; + insn |= (insn & (0x1f << 21)) >> 5; + insn |= got_addr & 0xffff; + bfd_put_32 (output_bfd, insn, p + 4); + + bfd_put_32 (output_bfd, B | ((-4 - off) & 0x3ffffff), p + 8); + picfixup_size += 12; + + /* Use one of the spare relocs, so --emit-relocs + output is reasonable. */ + memmove (rel + 1, rel, (relend - rel - 1) * sizeof (*rel)); + rel++; + rel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_LO); + rel->r_offset += 4; + + /* Continue on as if we had a got reloc, to output + dynamic reloc. */ + r_type = R_PPC_GOT16_LO; + } + else + info->callbacks->einfo + (_("%P: %H: error: %s with unexpected instruction %x\n"), + input_bfd, input_section, rel->r_offset, + "R_PPC_ADDR16_HA", insn); + } + else if (r_type == R_PPC_ADDR16_LO) + { + insn = bfd_get_32 (output_bfd, + contents + rel->r_offset - d_offset); + if ((insn & (0x3f << 26)) == 14u << 26 /* addi */ + || (insn & (0x3f << 26)) == 32u << 26 /* lwz */ + || (insn & (0x3f << 26)) == 34u << 26 /* lbz */ + || (insn & (0x3f << 26)) == 36u << 26 /* stw */ + || (insn & (0x3f << 26)) == 38u << 26 /* stb */ + || (insn & (0x3f << 26)) == 40u << 26 /* lhz */ + || (insn & (0x3f << 26)) == 42u << 26 /* lha */ + || (insn & (0x3f << 26)) == 44u << 26 /* sth */ + || (insn & (0x3f << 26)) == 46u << 26 /* lmw */ + || (insn & (0x3f << 26)) == 47u << 26 /* stmw */ + || (insn & (0x3f << 26)) == 48u << 26 /* lfs */ + || (insn & (0x3f << 26)) == 50u << 26 /* lfd */ + || (insn & (0x3f << 26)) == 52u << 26 /* stfs */ + || (insn & (0x3f << 26)) == 54u << 26 /* stfd */ + || ((insn & (0x3f << 26)) == 58u << 26 /* lwa,ld,lmd */ + && (insn & 3) != 1) + || ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */ + && ((insn & 3) == 0 || (insn & 3) == 3))) + { + /* Arrange to apply the reloc addend, if any. */ + relocation = 0; + unresolved_reloc = FALSE; + rel->r_info = ELF32_R_INFO (0, r_type); + } + else + info->callbacks->einfo + (_("%P: %H: error: %s with unexpected instruction %x\n"), + input_bfd, input_section, rel->r_offset, + "R_PPC_ADDR16_LO", insn); + } + } + ifunc = NULL; if (!htab->is_vxworks) { @@ -7965,11 +8173,11 @@ ppc_elf_relocate_section (bfd *output_bfd, ent = NULL; if (ifunc != NULL - && (!info->shared + && (!bfd_link_pic (info) || is_branch_reloc (r_type))) { addend = 0; - if (r_type == R_PPC_PLTREL24 && info->shared) + if (r_type == R_PPC_PLTREL24 && bfd_link_pic (info)) addend = rel->r_addend; ent = find_plt_ent (ifunc, got2, addend); } @@ -8097,8 +8305,8 @@ ppc_elf_relocate_section (bfd *output_bfd, { bfd_boolean dyn; dyn = htab->elf.dynamic_sections_created; - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) - || (info->shared + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) + || (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))) /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined @@ -8166,7 +8374,7 @@ ppc_elf_relocate_section (bfd *output_bfd, } /* Generate relocs for the dynamic linker. */ - if ((info->shared || indx != 0) + if ((bfd_link_pic (info) || indx != 0) && (offp == &htab->tlsld_got.offset || h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT @@ -8210,7 +8418,12 @@ ppc_elf_relocate_section (bfd *output_bfd, { outrel.r_addend += relocation; if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL)) - outrel.r_addend -= htab->elf.tls_sec->vma; + { + if (htab->elf.tls_sec == NULL) + outrel.r_addend = 0; + else + outrel.r_addend -= htab->elf.tls_sec->vma; + } } loc = rsec->contents; loc += (rsec->reloc_count++ @@ -8228,9 +8441,14 @@ ppc_elf_relocate_section (bfd *output_bfd, value = 1; else if (tls_ty != 0) { - value -= htab->elf.tls_sec->vma + DTP_OFFSET; - if (tls_ty == (TLS_TLS | TLS_TPREL)) - value += DTP_OFFSET - TP_OFFSET; + if (htab->elf.tls_sec == NULL) + value = 0; + else + { + value -= htab->elf.tls_sec->vma + DTP_OFFSET; + if (tls_ty == (TLS_TLS | TLS_TPREL)) + value += DTP_OFFSET - TP_OFFSET; + } if (tls_ty == (TLS_TLS | TLS_GD)) { @@ -8277,6 +8495,10 @@ ppc_elf_relocate_section (bfd *output_bfd, } } + /* If here for a picfixup, we're done. */ + if (r_type != ELF32_R_TYPE (rel->r_info)) + continue; + relocation = (htab->got->output_section->vma + htab->got->output_offset + off @@ -8316,7 +8538,8 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_DTPREL16_LO: case R_PPC_DTPREL16_HI: case R_PPC_DTPREL16_HA: - addend -= htab->elf.tls_sec->vma + DTP_OFFSET; + if (htab->elf.tls_sec != NULL) + addend -= htab->elf.tls_sec->vma + DTP_OFFSET; break; /* Relocations that may need to be propagated if this is a shared @@ -8340,18 +8563,21 @@ ppc_elf_relocate_section (bfd *output_bfd, bfd_put_32 (output_bfd, insn, p); break; } - addend -= htab->elf.tls_sec->vma + TP_OFFSET; + if (htab->elf.tls_sec != NULL) + addend -= htab->elf.tls_sec->vma + TP_OFFSET; /* The TPREL16 relocs shouldn't really be used in shared libs as they will result in DT_TEXTREL being set, but support them anyway. */ goto dodyn; case R_PPC_TPREL32: - addend -= htab->elf.tls_sec->vma + TP_OFFSET; + if (htab->elf.tls_sec != NULL) + addend -= htab->elf.tls_sec->vma + TP_OFFSET; goto dodyn; case R_PPC_DTPREL32: - addend -= htab->elf.tls_sec->vma + DTP_OFFSET; + if (htab->elf.tls_sec != NULL) + addend -= htab->elf.tls_sec->vma + DTP_OFFSET; goto dodyn; case R_PPC_DTPMOD32: @@ -8397,7 +8623,7 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_ADDR14: case R_PPC_ADDR14_BRTAKEN: case R_PPC_ADDR14_BRNTAKEN: - if (h != NULL && !info->shared) + if (h != NULL && !bfd_link_pic (info)) break; /* fall through */ @@ -8406,7 +8632,7 @@ ppc_elf_relocate_section (bfd *output_bfd, || is_vxworks_tls) break; - if ((info->shared + if ((bfd_link_pic (info) && !(h != NULL && ((h->root.type == bfd_link_hash_undefined && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN @@ -8416,11 +8642,15 @@ ppc_elf_relocate_section (bfd *output_bfd, && (must_be_dyn_reloc (info, r_type) || !SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS - && !info->shared + && !bfd_link_pic (info) && h != NULL && h->dynindx != -1 && !h->non_got_ref - && !h->def_regular)) + && !h->def_regular + && !(h->protected_def + && ppc_elf_hash_entry (h)->has_addr16_ha + && ppc_elf_hash_entry (h)->has_addr16_lo + && htab->params->pic_fixup > 0))) { int skip; bfd_byte *loc; @@ -8563,7 +8793,7 @@ ppc_elf_relocate_section (bfd *output_bfd, if (r_type == R_PPC_RELAX_PLTREL24) { - if (info->shared) + if (bfd_link_pic (info)) got2_addend = addend; addend = 0; } @@ -8586,7 +8816,7 @@ ppc_elf_relocate_section (bfd *output_bfd, size_t insn_offset = rel->r_offset; unsigned int insn; - if (info->shared) + if (bfd_link_pic (info)) { relocation -= (input_section->output_section->vma + input_section->output_offset @@ -8605,7 +8835,7 @@ ppc_elf_relocate_section (bfd *output_bfd, } relocation += addend; - if (info->relocatable) + if (bfd_link_relocatable (info)) relocation = 0; /* First insn is HA, second is LO. */ @@ -8691,7 +8921,7 @@ ppc_elf_relocate_section (bfd *output_bfd, if (h != NULL && ifunc == NULL) { struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2, - info->shared ? addend : 0); + bfd_link_pic (info) ? addend : 0); if (ent == NULL || htab->plt == NULL) { @@ -9199,30 +9429,20 @@ ppc_elf_relocate_section (bfd *output_bfd, if (r == bfd_reloc_overflow) { overflow: - if (warned) - continue; - if (h != NULL - && h->root.type == bfd_link_hash_undefweak - && howto->pc_relative) + /* On code like "if (foo) foo();" don't report overflow + on a branch to zero when foo is undefined. */ + if (!warned + && !(h != NULL + && (h->root.type == bfd_link_hash_undefweak + || h->root.type == bfd_link_hash_undefined) + && is_branch_reloc (r_type))) { - /* Assume this is a call protected by other code that - detect the symbol is undefined. If this is the case, - we can safely ignore the overflow. If not, the - program is hosed anyway, and a little warning isn't - going to help. */ - - continue; + if (!((*info->callbacks->reloc_overflow) + (info, (h ? &h->root : NULL), sym_name, + howto->name, rel->r_addend, + input_bfd, input_section, rel->r_offset))) + return FALSE; } - - if (! (*info->callbacks->reloc_overflow) (info, - (h ? &h->root : NULL), - sym_name, - howto->name, - rel->r_addend, - input_bfd, - input_section, - rel->r_offset)) - return FALSE; } else { @@ -9251,15 +9471,13 @@ ppc_elf_relocate_section (bfd *output_bfd, if (htab->params->ppc476_workaround && input_section->sec_info_type == SEC_INFO_TYPE_TARGET - && (!info->relocatable + && (!bfd_link_relocatable (info) || (input_section->output_section->alignment_power >= htab->params->pagesize_p2))) { - struct ppc_elf_relax_info *relax_info; bfd_vma start_addr, end_addr, addr; bfd_vma pagesize = (bfd_vma) 1 << htab->params->pagesize_p2; - relax_info = elf_section_data (input_section)->sec_info; if (relax_info->workaround_size != 0) { bfd_byte *p; @@ -9363,13 +9581,13 @@ ppc_elf_relocate_section (bfd *output_bfd, prevent the bad prefetch from happening in the first place: . - . lis 9,new_page@ha lis 9,new_page@ha - . addi 9,9,new_page@l addi 9,9,new_page@l - . mtctr 9 mtctr 9 - . bctr bctr + . lis 9,new_page@ha lis 9,new_page@ha + . addi 9,9,new_page@l addi 9,9,new_page@l + . mtctr 9 mtctr 9 + . bctr bctr . nop b somewhere_else - . b somewhere_else nop - . new_page: new_page: + . b somewhere_else nop + . new_page: new_page: . */ insn = bfd_get_32 (input_bfd, contents + offset); if ((insn & (0x3f << 26)) == (18u << 26) /* b,bl,ba,bla */ @@ -9390,6 +9608,8 @@ ppc_elf_relocate_section (bfd *output_bfd, && rel->r_offset >= offset && rel->r_offset < offset + 4) { + asection *sreloc; + /* If the insn we are patching had a reloc, adjust the reloc r_offset so that the reloc applies to the moved location. This matters for -r and --emit-relocs. */ @@ -9402,6 +9622,57 @@ ppc_elf_relocate_section (bfd *output_bfd, relend[-1] = tmp; } relend[-1].r_offset += patch_off - offset; + + /* Adjust REL16 addends too. */ + switch (ELF32_R_TYPE (relend[-1].r_info)) + { + case R_PPC_REL16: + case R_PPC_REL16_LO: + case R_PPC_REL16_HI: + case R_PPC_REL16_HA: + relend[-1].r_addend += patch_off - offset; + break; + default: + break; + } + + /* If we are building a PIE or shared library with + non-PIC objects, perhaps we had a dynamic reloc too? + If so, the dynamic reloc must move with the insn. */ + sreloc = elf_section_data (input_section)->sreloc; + if (sreloc != NULL) + { + Elf32_External_Rela *slo, *shi, *srelend; + bfd_vma soffset; + + slo = (Elf32_External_Rela *) sreloc->contents; + shi = srelend = slo + sreloc->reloc_count; + soffset = (offset + input_section->output_section->vma + + input_section->output_offset); + while (slo < shi) + { + Elf32_External_Rela *srel = slo + (shi - slo) / 2; + bfd_elf32_swap_reloca_in (output_bfd, (bfd_byte *) srel, + &outrel); + if (outrel.r_offset < soffset) + slo = srel + 1; + else if (outrel.r_offset > soffset + 3) + shi = srel; + else + { + if (srel + 1 != srelend) + { + memmove (srel, srel + 1, + (srelend - (srel + 1)) * sizeof (*srel)); + srel = srelend - 1; + } + outrel.r_offset += patch_off - offset; + bfd_elf32_swap_reloca_out (output_bfd, &outrel, + (bfd_byte *) srel); + break; + } + } + } } else rel = NULL; @@ -9412,9 +9683,9 @@ ppc_elf_relocate_section (bfd *output_bfd, bfd_vma delta = ((insn & 0xfffc) ^ 0x8000) - 0x8000; delta += offset - patch_off; - if (info->relocatable && rel != NULL) + if (bfd_link_relocatable (info) && rel != NULL) delta = 0; - if (!info->relocatable && rel != NULL) + if (!bfd_link_relocatable (info) && rel != NULL) { enum elf_ppc_reloc_type r_type; @@ -9540,11 +9811,11 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, got_offset = (reloc_index + 3) * 4; /* Use the right PLT. */ - plt_entry = info->shared ? ppc_elf_vxworks_pic_plt_entry + plt_entry = bfd_link_pic (info) ? ppc_elf_vxworks_pic_plt_entry : ppc_elf_vxworks_plt_entry; /* Fill in the .plt on VxWorks. */ - if (info->shared) + if (bfd_link_pic (info)) { bfd_put_32 (output_bfd, plt_entry[0] | PPC_HA (got_offset), @@ -9602,7 +9873,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, + ent->plt.offset + 16), htab->sgotplt->contents + got_offset); - if (!info->shared) + if (!bfd_link_pic (info)) { /* Fill in a couple of entries in .rela.plt.unloaded. */ loc = htab->srelplt2->contents @@ -9724,7 +9995,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, } } else if (h->type == STT_GNU_IFUNC - && !info->shared) + && !bfd_link_pic (info)) { /* Set the value of ifunc symbols in a non-pie executable to the glink entry. This is to avoid @@ -9776,7 +10047,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, write_glink_stub (ent, splt, p, info); - if (!info->shared) + if (!bfd_link_pic (info)) /* We only need one non-PIC glink stub. */ break; } @@ -9971,11 +10242,11 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, if (splt && splt->size > 0) { /* Use the right PLT. */ - const bfd_vma *plt_entry = (info->shared + const bfd_vma *plt_entry = (bfd_link_pic (info) ? ppc_elf_vxworks_pic_plt0_entry : ppc_elf_vxworks_plt0_entry); - if (!info->shared) + if (!bfd_link_pic (info)) { bfd_vma got_value = SYM_VAL (htab->elf.hgot); @@ -9996,7 +10267,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, bfd_put_32 (output_bfd, plt_entry[6], splt->contents + 24); bfd_put_32 (output_bfd, plt_entry[7], splt->contents + 28); - if (! info->shared) + if (! bfd_link_pic (info)) { Elf_Internal_Rela rela; bfd_byte *loc; @@ -10213,7 +10484,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, } /* Last comes the PLTresolve stub. */ - if (info->shared) + if (bfd_link_pic (info)) { bfd_vma bcl; @@ -10327,11 +10598,12 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, #define ELF_MACHINE_CODE EM_PPC #ifdef __QNXTARGET__ #define ELF_MAXPAGESIZE 0x1000 +#define ELF_COMMONPAGESIZE 0x1000 #else #define ELF_MAXPAGESIZE 0x10000 +#define ELF_COMMONPAGESIZE 0x10000 #endif #define ELF_MINPAGESIZE 0x1000 -#define ELF_COMMONPAGESIZE 0x1000 #define elf_info_to_howto ppc_elf_info_to_howto #ifdef EM_CYGNUS_POWERPC