X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-ppc.c;h=89c069b3c51f4a1c1f46978ff9af4f5f9e59e4c4;hb=8df017996f662ce6ab23aea4abeb8f7ac1f62651;hp=593ef475926be71f0e277390be1d9809cfc30ddf;hpb=482f3505d1b62cbcf46ffed54807fad0d91c8f09;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 593ef47592..89c069b3c5 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-2019 Free Software Foundation, Inc. + Copyright (C) 1994-2020 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -37,6 +37,9 @@ #include "dwarf2.h" #include "opcode/ppc.h" +/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ +#define OCTETS_PER_BYTE(ABFD, SEC) 1 + typedef enum split16_format_type { split16a_type = 0, @@ -956,7 +959,7 @@ ppc_elf_addr16_ha_reloc (bfd *abfd, + input_section->output_section->vma); value >>= 16; - octets = reloc_entry->address * bfd_octets_per_byte (abfd); + octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section); insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); insn &= ~0x1fffc1; insn |= (value & 0xffc1) | ((value & 0x3e) << 15); @@ -1077,7 +1080,9 @@ _bfd_elf_ppc_set_arch (bfd *abfd) if (mach == 0) { s = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); - if (s != NULL && bfd_malloc_and_get_section (abfd, s, &contents)) + if (s != NULL + && s->size >= 24 + && bfd_malloc_and_get_section (abfd, s, &contents)) { unsigned int apuinfo_size = bfd_get_32 (abfd, contents + 4); unsigned int i; @@ -1327,15 +1332,21 @@ ppc_elf_section_from_shdr (bfd *abfd, return FALSE; newsect = hdr->bfd_section; - flags = bfd_get_section_flags (abfd, newsect); + flags = 0; 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); - return TRUE; + if (strncmp (name, ".PPC.EMB", 8) == 0) + name += 8; + if (strncmp (name, ".sbss", 5) == 0 + || strncmp (name, ".sdata", 6) == 0) + flags |= SEC_SMALL_DATA; + + return (flags == 0 + || bfd_set_section_flags (newsect, newsect->flags | flags)); } /* Set up any other section flags and such that may be necessary. */ @@ -1389,7 +1400,7 @@ ppc_elf_modify_segment_map (bfd *abfd, for (m = elf_seg_map (abfd); m != NULL; m = m->next) { struct elf_segment_map *n; - bfd_size_type amt; + size_t amt; unsigned int j, k; unsigned int p_flags; @@ -1622,8 +1633,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) apuinfo_set = TRUE; if (largest_input_size < asec->size) { - if (buffer) - free (buffer); + free (buffer); largest_input_size = asec->size; buffer = bfd_malloc (largest_input_size); if (!buffer) @@ -1672,7 +1682,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 */ @@ -1681,8 +1691,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) } fail: - if (buffer) - free (buffer); + free (buffer); if (error_message) _bfd_error_handler (error_message, APUINFO_SECTION_NAME, ibfd); @@ -1703,7 +1712,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; @@ -1754,6 +1763,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) @@ -1790,7 +1806,7 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, bfd_vma stub_off; asymbol *s; arelent *p; - long count, i, stub_delta; + size_t count, i, stub_delta; size_t size; char *names; bfd_byte buf[4]; @@ -2100,18 +2116,13 @@ struct ppc_elf_link_hash_entry from the beginning of the section. */ elf_linker_section_pointers_t *linker_section_pointer; - /* Track dynamic relocs copied for this symbol. */ - struct elf_dyn_relocs *dyn_relocs; - /* Contexts in which symbol is used in the GOT. Bits are or'd into the mask as the corresponding relocs are encountered during check_relocs, with TLS_TLS being set when any of the other TLS bits are set. tls_optimize clears bits when optimizing to indicate the corresponding GOT entry type is not needed. If set, TLS_TLS is never cleared. tls_optimize may also - set TLS_TPRELGD when a GD reloc turns into a TPREL one. We use a - separate flag rather than setting TPREL just for convenience in - distinguishing the two cases. + set TLS_GDIE when a GD reloc turns into an IE one. These flags are also kept for local symbols. */ #define TLS_TLS 1 /* Any TLS reloc. */ #define TLS_GD 2 /* GD reloc. */ @@ -2119,7 +2130,7 @@ struct ppc_elf_link_hash_entry #define TLS_TPREL 8 /* TPREL reloc, => IE. */ #define TLS_DTPREL 16 /* DTPREL reloc, => LD. */ #define TLS_MARK 32 /* __tls_get_addr call marked. */ -#define TLS_TPRELGD 64 /* TPREL reloc resulting from GD->IE. */ +#define TLS_GDIE 64 /* GOT TPREL reloc resulting from GD->IE. */ unsigned char tls_mask; /* The above field is also used to mark function symbols. In which @@ -2184,9 +2195,6 @@ struct ppc_elf_link_hash_table /* The type of PLT we have chosen to use. */ enum ppc_elf_plt_type plt_type; - /* True if the target system is VxWorks. */ - unsigned int is_vxworks:1; - /* Whether there exist local gnu indirect function resolvers, referenced by dynamic relocations. */ unsigned int local_ifunc_resolver:1; @@ -2215,8 +2223,9 @@ struct ppc_elf_link_hash_table /* Nonzero if this section has TLS related relocations. */ #define has_tls_reloc sec_flg0 -/* Nonzero if this section has a call to __tls_get_addr. */ -#define has_tls_get_addr_call sec_flg1 +/* Nonzero if this section has a call to __tls_get_addr lacking marker + relocs. */ +#define nomark_tls_get_addr sec_flg1 /* Flag set when PLTCALL relocs are detected. */ #define has_pltcall sec_flg2 @@ -2249,7 +2258,6 @@ ppc_elf_link_hash_newfunc (struct bfd_hash_entry *entry, if (entry != NULL) { ppc_elf_hash_entry (entry)->linker_section_pointer = NULL; - ppc_elf_hash_entry (entry)->dyn_relocs = NULL; ppc_elf_hash_entry (entry)->tls_mask = 0; ppc_elf_hash_entry (entry)->has_sda_refs = 0; } @@ -2324,13 +2332,13 @@ ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info) return FALSE; htab = ppc_elf_hash_table (info); - if (!htab->is_vxworks) + if (htab->elf.target_os != is_vxworks) { /* The powerpc .got has a blrl instruction in it. Mark it 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 +2391,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 +2401,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 +2409,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 +2417,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 +2426,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 +2436,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,11 +2488,11 @@ 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; } - if (htab->is_vxworks + if (htab->elf.target_os == is_vxworks && !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2)) return FALSE; @@ -2493,7 +2501,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. */ @@ -2523,20 +2531,20 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info, if (eind->elf.root.type != bfd_link_hash_indirect) return; - if (eind->dyn_relocs != NULL) + if (ind->dyn_relocs != NULL) { - if (edir->dyn_relocs != NULL) + if (dir->dyn_relocs != NULL) { struct elf_dyn_relocs **pp; struct elf_dyn_relocs *p; /* Add reloc counts against the indirect sym to the direct sym list. Merge any entries against the same section. */ - for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &ind->dyn_relocs; (p = *pp) != NULL; ) { struct elf_dyn_relocs *q; - for (q = edir->dyn_relocs; q != NULL; q = q->next) + for (q = dir->dyn_relocs; q != NULL; q = q->next) if (q->sec == p->sec) { q->pc_count += p->pc_count; @@ -2547,11 +2555,11 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info, if (q == NULL) pp = &p->next; } - *pp = edir->dyn_relocs; + *pp = dir->dyn_relocs; } - edir->dyn_relocs = eind->dyn_relocs; - eind->dyn_relocs = NULL; + dir->dyn_relocs = ind->dyn_relocs; + ind->dyn_relocs = NULL; } /* Copy over the GOT refcount entries that we may have already seen to @@ -2732,7 +2740,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; @@ -2791,7 +2799,7 @@ update_plt_info (bfd *abfd, struct plt_entry **plist, break; if (ent == NULL) { - bfd_size_type amt = sizeof (*ent); + size_t amt = sizeof (*ent); ent = bfd_alloc (abfd, amt); if (ent == NULL) return FALSE; @@ -2877,15 +2885,6 @@ ppc_elf_check_relocs (bfd *abfd, if (bfd_link_relocatable (info)) return TRUE; - /* Don't do anything special with non-loaded, non-alloced sections. - In particular, any relocs in such sections should not affect GOT - and PLT reference counting (ie. we don't allow them to create GOT - or PLT entries), there's no possibility or desire to optimize TLS - relocs, and there's not much point in propagating relocs to shared - libs that the dynamic linker won't relocate. */ - if ((sec->flags & SEC_ALLOC) == 0) - return TRUE; - #ifdef DEBUG _bfd_error_handler ("ppc_elf_check_relocs called for section %pA in %pB", sec, abfd); @@ -2951,7 +2950,7 @@ ppc_elf_check_relocs (bfd *abfd, tls_type = 0; r_type = ELF32_R_TYPE (rel->r_info); ifunc = NULL; - if (h == NULL && !htab->is_vxworks) + if (h == NULL && htab->elf.target_os != is_vxworks) { Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx); @@ -2990,7 +2989,7 @@ ppc_elf_check_relocs (bfd *abfd, } } - if (!htab->is_vxworks + if (htab->elf.target_os != is_vxworks && is_branch_reloc (r_type) && h != NULL && h == tga) @@ -3003,7 +3002,7 @@ ppc_elf_check_relocs (bfd *abfd, ; else /* Mark this section as having an old-style call. */ - sec->has_tls_get_addr_call = 1; + sec->nomark_tls_get_addr = 1; } switch (r_type) @@ -3089,11 +3088,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 +3101,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 +3147,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 +3164,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 +3176,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; @@ -3316,9 +3300,7 @@ ppc_elf_check_relocs (bfd *abfd, /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_PPC_GNU_VTENTRY: - BFD_ASSERT (h != NULL); - if (h != NULL - && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return FALSE; break; @@ -3484,7 +3466,7 @@ ppc_elf_check_relocs (bfd *abfd, struct elf_dyn_relocs *p; struct elf_dyn_relocs **rel_head; - rel_head = &ppc_elf_hash_entry (h)->dyn_relocs; + rel_head = &h->dyn_relocs; p = *rel_head; if (p == NULL || p->sec != sec) { @@ -3559,6 +3541,17 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) obj_attribute *in_attr, *in_attrs; obj_attribute *out_attr, *out_attrs; bfd_boolean ret = TRUE; + bfd_boolean warn_only; + + /* We only warn about shared library mismatches, because common + libraries advertise support for a particular long double variant + but actually support more than one variant. For example, glibc + typically supports 128-bit IBM long double in the shared library + but has a compatibility static archive for 64-bit long double. + The linker doesn't have the smarts to see that an app using + object files marked as 64-bit long double call the compatibility + layer objects and only from there call into the shared library. */ + warn_only = (ibfd->flags & DYNAMIC) != 0; in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU]; out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU]; @@ -3576,9 +3569,12 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) ; else if (out_fp == 0) { - out_attr->type = ATTR_TYPE_FLAG_INT_VAL; - out_attr->i ^= in_fp; - last_fp = ibfd; + if (!warn_only) + { + out_attr->type = ATTR_TYPE_FLAG_INT_VAL; + out_attr->i ^= in_fp; + last_fp = ibfd; + } } else if (out_fp != 2 && in_fp == 2) { @@ -3586,7 +3582,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses hard float, %pB uses soft float"), last_fp, ibfd); - ret = FALSE; + ret = warn_only; } else if (out_fp == 2 && in_fp != 2) { @@ -3594,7 +3590,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses hard float, %pB uses soft float"), ibfd, last_fp); - ret = FALSE; + ret = warn_only; } else if (out_fp == 1 && in_fp == 3) { @@ -3602,7 +3598,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses double-precision hard float, " "%pB uses single-precision hard float"), last_fp, ibfd); - ret = FALSE; + ret = warn_only; } else if (out_fp == 3 && in_fp == 1) { @@ -3610,7 +3606,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses double-precision hard float, " "%pB uses single-precision hard float"), ibfd, last_fp); - ret = FALSE; + ret = warn_only; } in_fp = in_attr->i & 0xc; @@ -3619,9 +3615,12 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) ; else if (out_fp == 0) { - out_attr->type = ATTR_TYPE_FLAG_INT_VAL; - out_attr->i ^= in_fp; - last_ld = ibfd; + if (!warn_only) + { + out_attr->type = ATTR_TYPE_FLAG_INT_VAL; + out_attr->i ^= in_fp; + last_ld = ibfd; + } } else if (out_fp != 2 * 4 && in_fp == 2 * 4) { @@ -3629,7 +3628,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses 64-bit long double, " "%pB uses 128-bit long double"), ibfd, last_ld); - ret = FALSE; + ret = warn_only; } else if (in_fp != 2 * 4 && out_fp == 2 * 4) { @@ -3637,7 +3636,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses 64-bit long double, " "%pB uses 128-bit long double"), last_ld, ibfd); - ret = FALSE; + ret = warn_only; } else if (out_fp == 1 * 4 && in_fp == 3 * 4) { @@ -3645,7 +3644,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses IBM long double, " "%pB uses IEEE long double"), last_ld, ibfd); - ret = FALSE; + ret = warn_only; } else if (out_fp == 3 * 4 && in_fp == 1 * 4) { @@ -3653,7 +3652,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses IBM long double, " "%pB uses IEEE long double"), ibfd, last_ld); - ret = FALSE; + ret = warn_only; } } @@ -3802,6 +3801,9 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) if (!ppc_elf_merge_obj_attributes (ibfd, info)) return FALSE; + if ((ibfd->flags & DYNAMIC) != 0) + return TRUE; + new_flags = elf_elfheader (ibfd)->e_flags; old_flags = elf_elfheader (obfd)->e_flags; if (!elf_flags_init (obfd)) @@ -4039,19 +4041,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; @@ -4260,8 +4262,7 @@ ppc_elf_inline_plt (struct bfd_link_info *info) { if (elf_section_data (sec)->relocs != relstart) free (relstart); - if (local_syms != NULL - && symtab_hdr->contents != (unsigned char *) local_syms) + if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); return FALSE; } @@ -4465,11 +4466,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 @@ -4478,7 +4475,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, setup insn. If we don't find matching arg setup relocs, don't do any tls optimization. */ if (pass == 0 - && sec->has_tls_get_addr_call + && sec->nomark_tls_get_addr && h != NULL && h == htab->tls_get_addr && !expecting_tls_get_addr @@ -4525,7 +4522,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, tls_set = 0; else /* GD -> IE */ - tls_set = TLS_TLS | TLS_TPRELGD; + tls_set = TLS_TLS | TLS_GDIE; tls_clear = TLS_GD; break; @@ -4543,8 +4540,11 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, else continue; - case R_PPC_TLSGD: case R_PPC_TLSLD: + if (!is_local) + continue; + /* Fall through. */ + case R_PPC_TLSGD: if (rel + 1 < relend && is_plt_seq_reloc (ELF32_R_TYPE (rel[1].r_info))) { @@ -4591,7 +4591,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, if (pass == 0) { if (!expecting_tls_get_addr - || !sec->has_tls_get_addr_call) + || !sec->nomark_tls_get_addr) continue; if (rel + 1 < relend @@ -4641,12 +4641,12 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, indirect call to __tls_get_addr without a marker. Disable optimization in this case. */ if ((tls_clear & (TLS_GD | TLS_LD)) != 0 - && !sec->has_tls_get_addr_call + && !sec->nomark_tls_get_addr && ((*tls_mask & (TLS_TLS | TLS_MARK)) != (TLS_TLS | TLS_MARK))) continue; - if (expecting_tls_get_addr) + if (expecting_tls_get_addr == 1 + !sec->nomark_tls_get_addr) { struct plt_entry *ent; bfd_vma addend = 0; @@ -4659,10 +4659,9 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, got2, addend); if (ent != NULL && ent->plt.refcount > 0) ent->plt.refcount -= 1; - - if (expecting_tls_get_addr == 2) - continue; } + if (tls_clear == 0) + continue; if (tls_set == 0) { @@ -4683,23 +4682,6 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, return TRUE; } -/* Find dynamic relocs for H that apply to read-only sections. */ - -static asection * -readonly_dynrelocs (struct elf_link_hash_entry *h) -{ - struct elf_dyn_relocs *p; - - for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) - { - asection *s = p->sec->output_section; - - if (s != NULL && (s->flags & SEC_READONLY) != 0) - return p->sec; - } - return NULL; -} - /* Return true if we have dynamic relocs against H or any of its weak aliases, that apply to read-only sections. Cannot be used after size_dynamic_sections. */ @@ -4710,7 +4692,7 @@ alias_readonly_dynrelocs (struct elf_link_hash_entry *h) struct ppc_elf_link_hash_entry *eh = ppc_elf_hash_entry (h); do { - if (readonly_dynrelocs (&eh->elf)) + if (_bfd_elf_readonly_dynrelocs (&eh->elf)) return TRUE; eh = ppc_elf_hash_entry (eh->elf.u.alias); } while (eh != NULL && &eh->elf != h); @@ -4725,7 +4707,7 @@ pc_dynrelocs (struct elf_link_hash_entry *h) { struct elf_dyn_relocs *p; - for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) + for (p = h->dyn_relocs; p != NULL; p = p->next) if (p->pc_count != 0) return TRUE; return FALSE; @@ -4769,7 +4751,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* Discard dyn_relocs when non-pic if we've decided that a function symbol is local. */ if (!bfd_link_pic (info) && local) - ppc_elf_hash_entry (h)->dyn_relocs = NULL; + h->dyn_relocs = NULL; /* Clear procedure linkage table information for any symbol that won't need a .plt entry. */ @@ -4813,9 +4795,9 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, || (h->non_got_ref && !h->ref_regular_nonweak && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))) - && !htab->is_vxworks + && htab->elf.target_os != is_vxworks && !ppc_elf_hash_entry (h)->has_sda_refs - && !readonly_dynrelocs (h)) + && !_bfd_elf_readonly_dynrelocs (h)) { h->pointer_equality_needed = 0; /* If we haven't seen a branch reloc and the symbol @@ -4826,7 +4808,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, else if (!bfd_link_pic (info)) /* We are going to be defining the function symbol on the plt stub, so no dyn_relocs needed when non-pic. */ - ppc_elf_hash_entry (h)->dyn_relocs = NULL; + h->dyn_relocs = NULL; } h->protected_def = 0; /* Function symbols can't have copy relocs. */ @@ -4847,7 +4829,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, if (def->root.u.def.section == htab->elf.sdynbss || def->root.u.def.section == htab->elf.sdynrelro || def->root.u.def.section == htab->dynsbss) - ppc_elf_hash_entry (h)->dyn_relocs = NULL; + h->dyn_relocs = NULL; return TRUE; } @@ -4899,7 +4881,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, executable. */ if (ELIMINATE_COPY_RELOCS && !ppc_elf_hash_entry (h)->has_sda_refs - && !htab->is_vxworks + && htab->elf.target_os != is_vxworks && !h->def_regular && !alias_readonly_dynrelocs (h)) return TRUE; @@ -4943,7 +4925,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, } /* We no longer want dyn_relocs. */ - ppc_elf_hash_entry (h)->dyn_relocs = NULL; + h->dyn_relocs = NULL; return _bfd_elf_adjust_dynamic_copy (info, h, s); } @@ -5051,7 +5033,7 @@ got_entries_needed (int tls_mask) need = 0; if ((tls_mask & TLS_GD) != 0) need += 8; - if ((tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0) + if ((tls_mask & (TLS_TPREL | TLS_GDIE)) != 0) need += 4; if ((tls_mask & TLS_DTPREL) != 0) need += 4; @@ -5059,24 +5041,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_TPRELGD)) != 0) - need -= 4; - return need * sizeof (Elf32_External_Rela) / 4; -} - /* If H is undefined, make it dynamic if that makes sense. */ static bfd_boolean @@ -5129,7 +5093,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. */ @@ -5143,20 +5107,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) @@ -5172,19 +5135,19 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) IFUNCs which are handled even in static executables. */ if (!htab->elf.dynamic_sections_created && h->type != STT_GNU_IFUNC) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; /* Discard relocs on undefined symbols that must be local. */ else if (h->root.type == bfd_link_hash_undefined && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; /* Also discard relocs on undefined weak syms with non-default visibility, or when dynamic_undefined_weak says so. */ else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; - if (eh->dyn_relocs == NULL) + if (h->dyn_relocs == NULL) ; /* In the shared -Bsymbolic case, discard space allocated for @@ -5204,7 +5167,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { p->count -= p->pc_count; p->pc_count = 0; @@ -5215,11 +5178,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } } - if (htab->is_vxworks) + if (htab->elf.target_os == is_vxworks) { struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { if (strcmp (p->sec->output_section->name, ".tls_vars") == 0) *pp = p->next; @@ -5228,7 +5191,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } } - if (eh->dyn_relocs != NULL) + if (h->dyn_relocs != NULL) { /* Make sure this symbol is output as a dynamic symbol. */ if (!ensure_undef_dynamic (info, h)) @@ -5253,14 +5216,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return FALSE; if (h->dynindx == -1) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; } else - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; } /* Allocate space. */ - for (p = eh->dyn_relocs; p != NULL; p = p->next) + for (p = h->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; if (eh->elf.type == STT_GNU_IFUNC) @@ -5448,33 +5411,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return TRUE; } -/* Set DF_TEXTREL if we find any dynamic relocs that apply to - read-only sections. */ - -static bfd_boolean -maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) -{ - asection *sec; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - sec = readonly_dynrelocs (h); - if (sec != NULL) - { - struct bfd_link_info *info = (struct bfd_link_info *) info_p; - - info->flags |= DF_TEXTREL; - info->callbacks->minfo - (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"), - sec->owner, h->root.root.string, sec); - - /* Not an error, just cut short the traversal. */ - return FALSE; - } - return TRUE; -} - static const unsigned char glink_eh_frame_cie[] = { 0, 0, 0, 16, /* length. */ @@ -5556,7 +5492,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, linker script /DISCARD/, so we'll be discarding the relocs too. */ } - else if (htab->is_vxworks + else if (htab->elf.target_os == is_vxworks && strcmp (p->sec->output_section->name, ".tls_vars") == 0) { @@ -5604,12 +5540,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; @@ -5620,7 +5557,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, else *local_got = (bfd_vma) -1; - if (htab->is_vxworks) + if (htab->elf.target_os == is_vxworks) continue; /* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt. */ @@ -5686,7 +5623,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 @@ -5833,8 +5770,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) { @@ -5925,7 +5861,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (elf_hash_table (info), maybe_set_textrel, + elf_link_hash_traverse (elf_hash_table (info), + _bfd_elf_maybe_set_textrel, info); if ((info->flags & DF_TEXTREL) != 0) @@ -5933,7 +5870,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, if (!add_dynamic_entry (DT_TEXTREL, 0)) return FALSE; } - if (htab->is_vxworks + if (htab->elf.target_os == is_vxworks && !elf_vxworks_add_dynamic_entries (output_bfd, info)) return FALSE; } @@ -6669,8 +6606,7 @@ ppc_elf_relax_section (bfd *abfd, rel_hdr = _bfd_elf_single_rel_hdr (isec); rel_hdr->sh_size += changes * rel_hdr->sh_entsize; } - else if (internal_relocs != NULL - && elf_section_data (isec)->relocs != internal_relocs) + else if (elf_section_data (isec)->relocs != internal_relocs) free (internal_relocs); *again = changes != 0 || workaround_change; @@ -6683,13 +6619,11 @@ ppc_elf_relax_section (bfd *abfd, branch_fixups = branch_fixups->next; free (f); } - if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) + if ((unsigned char *) isymbuf != symtab_hdr->contents) free (isymbuf); - if (contents != NULL - && elf_section_data (isec)->this_hdr.contents != contents) + if (elf_section_data (isec)->this_hdr.contents != contents) free (contents); - if (internal_relocs != NULL - && elf_section_data (isec)->relocs != internal_relocs) + if (elf_section_data (isec)->relocs != internal_relocs) free (internal_relocs); return FALSE; } @@ -6870,7 +6804,7 @@ _bfd_elf_ppc_at_tls_transform (unsigned int insn, unsigned int reg) { unsigned int rtra; - if ((insn & (0x3f << 26)) != 31 << 26) + if ((insn & (0x3fu << 26)) != 31 << 26) return 0; if (reg == 0 || ((insn >> 11) & 0x1f) == reg) @@ -6888,13 +6822,13 @@ _bfd_elf_ppc_at_tls_transform (unsigned int insn, unsigned int reg) || ((insn & (0x1f << 6)) >= 16 << 6 && (insn & (0x1f << 6)) < 24 << 6))) /* load and store indexed -> dform. */ - insn = (32 | ((insn >> 6) & 0x1f)) << 26; + insn = (32u | ((insn >> 6) & 0x1f)) << 26; else if ((insn & (((0x1a << 5) | 0x1f) << 1)) == 21 << 1) /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */ - insn = ((58 | ((insn >> 6) & 4)) << 26) | ((insn >> 6) & 1); + insn = ((58u | ((insn >> 6) & 4)) << 26) | ((insn >> 6) & 1); else if ((insn & (((0x1f << 5) | 0x1f) << 1)) == 341 << 1) /* lwax -> lwa. */ - insn = (58 << 26) | 2; + insn = (58u << 26) | 2; else return 0; insn |= rtra; @@ -6909,36 +6843,36 @@ unsigned int _bfd_elf_ppc_at_tprel_transform (unsigned int insn, unsigned int reg) { if ((insn & (0x1f << 16)) == reg << 16 - && ((insn & (0x3f << 26)) == 14u << 26 /* addi */ - || (insn & (0x3f << 26)) == 15u << 26 /* addis */ - || (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 & (0x3fu << 26)) == 14u << 26 /* addi */ + || (insn & (0x3fu << 26)) == 15u << 26 /* addis */ + || (insn & (0x3fu << 26)) == 32u << 26 /* lwz */ + || (insn & (0x3fu << 26)) == 34u << 26 /* lbz */ + || (insn & (0x3fu << 26)) == 36u << 26 /* stw */ + || (insn & (0x3fu << 26)) == 38u << 26 /* stb */ + || (insn & (0x3fu << 26)) == 40u << 26 /* lhz */ + || (insn & (0x3fu << 26)) == 42u << 26 /* lha */ + || (insn & (0x3fu << 26)) == 44u << 26 /* sth */ + || (insn & (0x3fu << 26)) == 46u << 26 /* lmw */ + || (insn & (0x3fu << 26)) == 47u << 26 /* stmw */ + || (insn & (0x3fu << 26)) == 48u << 26 /* lfs */ + || (insn & (0x3fu << 26)) == 50u << 26 /* lfd */ + || (insn & (0x3fu << 26)) == 52u << 26 /* stfs */ + || (insn & (0x3fu << 26)) == 54u << 26 /* stfd */ + || ((insn & (0x3fu << 26)) == 58u << 26 /* lwa,ld,lmd */ && (insn & 3) != 1) - || ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */ + || ((insn & (0x3fu << 26)) == 62u << 26 /* std, stmd */ && ((insn & 3) == 0 || (insn & 3) == 3)))) { insn &= ~(0x1f << 16); } else if ((insn & (0x1f << 21)) == reg << 21 - && ((insn & (0x3e << 26)) == 24u << 26 /* ori, oris */ - || (insn & (0x3e << 26)) == 26u << 26 /* xori,xoris */ - || (insn & (0x3e << 26)) == 28u << 26 /* andi,andis */)) + && ((insn & (0x3eu << 26)) == 24u << 26 /* ori, oris */ + || (insn & (0x3eu << 26)) == 26u << 26 /* xori,xoris */ + || (insn & (0x3eu << 26)) == 28u << 26 /* andi,andis */)) { insn &= ~(0x1f << 21); insn |= (insn & (0x1f << 16)) << 5; - if ((insn & (0x3e << 26)) == 26 << 26 /* xori,xoris */) + if ((insn & (0x3eu << 26)) == 26u << 26 /* xori,xoris */) insn -= 2 >> 26; /* convert to ori,oris */ } else @@ -6949,17 +6883,17 @@ _bfd_elf_ppc_at_tprel_transform (unsigned int insn, unsigned int reg) static bfd_boolean is_insn_ds_form (unsigned int insn) { - return ((insn & (0x3f << 26)) == 58u << 26 /* ld,ldu,lwa */ - || (insn & (0x3f << 26)) == 62u << 26 /* std,stdu,stq */ - || (insn & (0x3f << 26)) == 57u << 26 /* lfdp */ - || (insn & (0x3f << 26)) == 61u << 26 /* stfdp */); + return ((insn & (0x3fu << 26)) == 58u << 26 /* ld,ldu,lwa */ + || (insn & (0x3fu << 26)) == 62u << 26 /* std,stdu,stq */ + || (insn & (0x3fu << 26)) == 57u << 26 /* lfdp */ + || (insn & (0x3fu << 26)) == 61u << 26 /* stfdp */); } static bfd_boolean is_insn_dq_form (unsigned int insn) { - return ((insn & (0x3f << 26)) == 56u << 26 /* lq */ - || ((insn & (0x3f << 26)) == (61u << 26) /* lxv, stxv */ + return ((insn & (0x3fu << 26)) == 56u << 26 /* lq */ + || ((insn & (0x3fu << 26)) == (61u << 26) /* lxv, stxv */ && (insn & 3) == 1)); } @@ -7043,7 +6977,7 @@ 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 && bfd_link_pic (info) + is_vxworks_tls = (htab->elf.target_os == is_vxworks && bfd_link_pic (info) && !strcmp (input_section->output_section->name, ".tls_vars")); if (input_section->sec_info_type == SEC_INFO_TYPE_TARGET) @@ -7213,7 +7147,7 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_GOT_TLSGD16_HI: case R_PPC_GOT_TLSGD16_HA: - tls_gd = TLS_TPRELGD; + tls_gd = TLS_GDIE; if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) goto tls_gdld_hi; break; @@ -7238,7 +7172,7 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_GOT_TLSGD16: case R_PPC_GOT_TLSGD16_LO: - tls_gd = TLS_TPRELGD; + tls_gd = TLS_GDIE; if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) goto tls_ldgd_opt; break; @@ -7257,7 +7191,7 @@ ppc_elf_relocate_section (bfd *output_bfd, stays with its arg setup insns, ie. that the next reloc is the __tls_get_addr call associated with the current reloc. Edit both insns. */ - if (input_section->has_tls_get_addr_call + if (input_section->nomark_tls_get_addr && rel + 1 < relend && branch_reloc_hash_match (input_bfd, rel + 1, htab->tls_get_addr)) @@ -7272,7 +7206,7 @@ ppc_elf_relocate_section (bfd *output_bfd, { /* IE */ insn1 &= (0x1f << 21) | (0x1f << 16); - insn1 |= 32 << 26; /* lwz */ + insn1 |= 32u << 26; /* lwz */ if (offset != (bfd_vma) -1) { rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE); @@ -7340,7 +7274,7 @@ ppc_elf_relocate_section (bfd *output_bfd, break; } - if ((tls_mask & TLS_TPRELGD) != 0) + if ((tls_mask & TLS_GDIE) != 0) { /* IE */ r_type = R_PPC_NONE; @@ -7441,7 +7375,7 @@ ppc_elf_relocate_section (bfd *output_bfd, insn = bfd_get_32 (input_bfd, contents + rel->r_offset - d_offset); - if ((insn & (0x3f << 26)) == 15u << 26 + if ((insn & (0x3fu << 26)) == 15u << 26 && (insn & (0x1f << 16)) != 0) { if (!bfd_link_pic (info)) @@ -7477,7 +7411,7 @@ ppc_elf_relocate_section (bfd *output_bfd, { insn = bfd_get_32 (input_bfd, contents + rel->r_offset - d_offset); - if ((insn & (0x3f << 26)) == (15u << 26) + if ((insn & (0x3fu << 26)) == (15u << 26) && (insn & (0x1f << 16)) == 0 /* lis */) { bfd_byte *p; @@ -7540,23 +7474,23 @@ ppc_elf_relocate_section (bfd *output_bfd, { insn = bfd_get_32 (input_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 */ + if ((insn & (0x3fu << 26)) == 14u << 26 /* addi */ + || (insn & (0x3fu << 26)) == 32u << 26 /* lwz */ + || (insn & (0x3fu << 26)) == 34u << 26 /* lbz */ + || (insn & (0x3fu << 26)) == 36u << 26 /* stw */ + || (insn & (0x3fu << 26)) == 38u << 26 /* stb */ + || (insn & (0x3fu << 26)) == 40u << 26 /* lhz */ + || (insn & (0x3fu << 26)) == 42u << 26 /* lha */ + || (insn & (0x3fu << 26)) == 44u << 26 /* sth */ + || (insn & (0x3fu << 26)) == 46u << 26 /* lmw */ + || (insn & (0x3fu << 26)) == 47u << 26 /* stmw */ + || (insn & (0x3fu << 26)) == 48u << 26 /* lfs */ + || (insn & (0x3fu << 26)) == 50u << 26 /* lfd */ + || (insn & (0x3fu << 26)) == 52u << 26 /* stfs */ + || (insn & (0x3fu << 26)) == 54u << 26 /* stfd */ + || ((insn & (0x3fu << 26)) == 58u << 26 /* lwa,ld,lmd */ && (insn & 3) != 1) - || ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */ + || ((insn & (0x3fu << 26)) == 62u << 26 /* std, stmd */ && ((insn & 3) == 0 || (insn & 3) == 3))) { /* Arrange to apply the reloc addend, if any. */ @@ -7575,7 +7509,7 @@ ppc_elf_relocate_section (bfd *output_bfd, } ifunc = NULL; - if (!htab->is_vxworks) + if (htab->elf.target_os != is_vxworks) { struct plt_entry *ent; @@ -7666,7 +7600,7 @@ ppc_elf_relocate_section (bfd *output_bfd, { bfd_byte *p = contents + (rel->r_offset & ~3); unsigned int insn = bfd_get_32 (input_bfd, p); - if ((insn & ((0x3f << 26) | 0x1f << 16)) + if ((insn & ((0x3fu << 26) | 0x1f << 16)) != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */) /* xgettext:c-format */ info->callbacks->minfo @@ -7760,8 +7694,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) { @@ -7798,13 +7731,13 @@ ppc_elf_relocate_section (bfd *output_bfd, { unsigned int tls_m = ((tls_mask & TLS_TLS) != 0 ? tls_mask & (TLS_LD | TLS_GD | TLS_DTPREL - | TLS_TPREL | TLS_TPRELGD) + | TLS_TPREL | TLS_GDIE) : 0); 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. @@ -7828,7 +7761,7 @@ ppc_elf_relocate_section (bfd *output_bfd, tls_ty = TLS_TLS | TLS_DTPREL; tls_m &= ~TLS_DTPREL; } - else if ((tls_m & (TLS_TPREL | TLS_TPRELGD)) != 0) + else if ((tls_m & (TLS_TPREL | TLS_GDIE)) != 0) { tls_ty = TLS_TLS | TLS_TPREL; tls_m = 0; @@ -7838,9 +7771,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)))) { @@ -7950,8 +7882,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)) { @@ -8121,11 +8052,11 @@ ppc_elf_relocate_section (bfd *output_bfd, if (bfd_link_pic (info) ? ((h == NULL - || ppc_elf_hash_entry (h)->dyn_relocs != NULL) + || h->dyn_relocs != NULL) && ((h != NULL && pc_dynrelocs (h)) || must_be_dyn_reloc (info, r_type))) : (h != NULL - && ppc_elf_hash_entry (h)->dyn_relocs != NULL)) + && h->dyn_relocs != NULL)) { int skip; bfd_byte *loc; @@ -8152,6 +8083,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)) @@ -8209,19 +8148,27 @@ ppc_elf_relocate_section (bfd *output_bfd, but ld.so expects buggy relocs. FIXME: Why not always use a zero index? */ osec = sec->output_section; - indx = elf_section_data (osec)->dynindx; - if (indx == 0) + if ((osec->flags & SEC_THREAD_LOCAL) != 0) + { + osec = htab->elf.tls_sec; + indx = 0; + } + else { - osec = htab->elf.text_index_section; indx = elf_section_data (osec)->dynindx; + if (indx == 0) + { + osec = htab->elf.text_index_section; + indx = elf_section_data (osec)->dynindx; + } + BFD_ASSERT (indx != 0); } - BFD_ASSERT (indx != 0); -#ifdef DEBUG - if (indx == 0) - printf ("indx=%ld section=%s flags=%08x name=%s\n", - indx, osec->name, osec->flags, - h->root.root.string); -#endif + + /* ld.so doesn't expect buggy TLS relocs. + Don't leave the symbol value in the + addend for them. */ + if (IS_PPC_TLS_RELOC (r_type)) + outrel.r_addend -= osec->vma; } outrel.r_info = ELF32_R_INFO (indx, r_type); @@ -8388,10 +8335,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; @@ -8506,7 +8451,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)) { @@ -8537,7 +8482,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)) { @@ -8612,7 +8557,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) { @@ -8656,6 +8601,19 @@ ppc_elf_relocate_section (bfd *output_bfd, addend -= SYM_VAL (sda); } + if (r_type == R_PPC_EMB_RELSDA) + break; + + /* The PowerPC Embedded Application Binary Interface + version 1.0 insanely chose to specify R_PPC_EMB_SDA21 + operating on a 24-bit field at r_offset. GNU as and + GNU ld have always assumed R_PPC_EMB_SDA21 operates on + a 32-bit bit insn at r_offset. Cope with object file + producers that possibly comply with the EABI in + generating an odd r_offset for big-endian objects. */ + if (r_type == R_PPC_EMB_SDA21) + rel->r_offset &= ~1; + insn = bfd_get_32 (input_bfd, contents + rel->r_offset); if (reg == 0 && (r_type == R_PPC_VLE_SDA21 @@ -8683,13 +8641,8 @@ ppc_elf_relocate_section (bfd *output_bfd, goto overflow; goto copy_reloc; } - else if (r_type == R_PPC_EMB_SDA21 - || r_type == R_PPC_VLE_SDA21 - || r_type == R_PPC_VLE_SDA21_LO) - { - /* Fill in register field. */ - insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); - } + /* Fill in register field. */ + insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); bfd_put_32 (input_bfd, insn, contents + rel->r_offset); } break; @@ -8711,7 +8664,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; @@ -8788,7 +8741,7 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_VLE_ADDR20: ppc_elf_vle_split20 (output_bfd, contents + rel->r_offset, relocation); - continue; + goto copy_reloc; /* Relocate against the beginning of the section. */ case R_PPC_SECTOFF: @@ -9001,11 +8954,11 @@ ppc_elf_relocate_section (bfd *output_bfd, unsigned int insn; insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3)); - if ((insn & (0x3f << 26)) == 10u << 26 /* cmpli */) + if ((insn & (0x3fu << 26)) == 10u << 26 /* cmpli */) complain = complain_overflow_bitfield; - else if ((insn & (0x3f << 26)) == 28u << 26 /* andi */ - || (insn & (0x3f << 26)) == 24u << 26 /* ori */ - || (insn & (0x3f << 26)) == 26u << 26 /* xori */) + else if ((insn & (0x3fu << 26)) == 28u << 26 /* andi */ + || (insn & (0x3fu << 26)) == 24u << 26 /* ori */ + || (insn & (0x3fu << 26)) == 26u << 26 /* xori */) complain = complain_overflow_unsigned; } if (howto->complain_on_overflow != complain) @@ -9229,10 +9182,10 @@ ppc_elf_relocate_section (bfd *output_bfd, . new_page: new_page: . */ insn = bfd_get_32 (input_bfd, contents + offset); - if ((insn & (0x3f << 26)) == (18u << 26) /* b,bl,ba,bla */ - || ((insn & (0x3f << 26)) == (16u << 26) /* bc,bcl,bca,bcla*/ + if ((insn & (0x3fu << 26)) == (18u << 26) /* b,bl,ba,bla */ + || ((insn & (0x3fu << 26)) == (16u << 26) /* bc,bcl,bca,bcla*/ && (insn & (0x14 << 21)) == (0x14 << 21)) /* with BO=0x14 */ - || ((insn & (0x3f << 26)) == (19u << 26) + || ((insn & (0x3fu << 26)) == (19u << 26) && (insn & (0x3ff << 1)) == (16u << 1) /* bclr,bclrl */ && (insn & (0x14 << 21)) == (0x14 << 21)))/* with BO=0x14 */ continue; @@ -9316,7 +9269,7 @@ ppc_elf_relocate_section (bfd *output_bfd, else rel = NULL; - if ((insn & (0x3f << 26)) == (16u << 26) /* bc */ + if ((insn & (0x3fu << 26)) == (16u << 26) /* bc */ && (insn & 2) == 0 /* relative */) { bfd_vma delta = ((insn & 0xfffc) ^ 0x8000) - 0x8000; @@ -9704,12 +9657,12 @@ ppc_finish_symbols (struct bfd_link_info *info) bfd_byte *loc; bfd_vma val; Elf_Internal_Rela rela; + unsigned char *p; if (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms, lplt - local_plt, ibfd)) { - if (local_syms != NULL - && symtab_hdr->contents != (unsigned char *) local_syms) + if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); return FALSE; } @@ -9748,14 +9701,9 @@ ppc_finish_symbols (struct bfd_link_info *info) loc = relplt->contents + (relplt->reloc_count++ * sizeof (Elf32_External_Rela)); bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc); - } - if ((ent->glink_offset & 1) == 0) - { - unsigned char *p = ((unsigned char *) htab->glink->contents - + ent->glink_offset); + p = (unsigned char *) htab->glink->contents + ent->glink_offset; write_glink_stub (NULL, ent, htab->elf.iplt, p, info); - ent->glink_offset |= 1; } } @@ -9933,7 +9881,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, switch (dyn.d_tag) { case DT_PLTGOT: - if (htab->is_vxworks) + if (htab->elf.target_os == is_vxworks) s = htab->elf.sgotplt; else s = htab->elf.splt; @@ -9965,7 +9913,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, continue; default: - if (htab->is_vxworks + if (htab->elf.target_os == is_vxworks && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) break; continue; @@ -10017,7 +9965,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, } /* Fill in the first entry in the VxWorks procedure linkage table. */ - if (htab->is_vxworks + if (htab->elf.target_os == is_vxworks && htab->elf.splt != NULL && htab->elf.splt->size != 0 && htab->elf.splt->output_section != bfd_abs_section_ptr) @@ -10426,6 +10374,9 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, #undef ELF_OSABI +#undef ELF_TARGET_OS +#define ELF_TARGET_OS is_vxworks + /* VxWorks uses the elf default section flags for .plt. */ static const struct bfd_elf_special_section * ppc_elf_vxworks_get_sec_type_attr (bfd *abfd, asection *sec) @@ -10451,7 +10402,6 @@ ppc_elf_vxworks_link_hash_table_create (bfd *abfd) { struct ppc_elf_link_hash_table *htab = (struct ppc_elf_link_hash_table *)ret; - htab->is_vxworks = 1; htab->plt_type = PLT_VXWORKS; htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE; htab->plt_slot_size = VXWORKS_PLT_ENTRY_SIZE; @@ -10477,11 +10427,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 @@ -10524,6 +10474,5 @@ ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker) #undef elf32_bed #define elf32_bed ppc_elf_vxworks_bed -#undef elf_backend_post_process_headers #include "elf32-target.h"