X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-xtensa.c;h=12ff9f772aafaa577f1ac582e3cc9c9205dd9625;hb=f3f8ece4b1c77c925d1f1566df0bf632790a4d24;hp=af9618dbfc23f91b881920d12f775f515b3e6d13;hpb=1a72702bb30ec3f94627cfcae684823b413f20b9;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index af9618dbfc..12ff9f772a 100644 --- a/bfd/elf32-xtensa.c +++ b/bfd/elf32-xtensa.c @@ -1,5 +1,5 @@ /* Xtensa-specific support for 32-bit ELF. - Copyright (C) 2003-2016 Free Software Foundation, Inc. + Copyright (C) 2003-2020 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -32,6 +32,9 @@ #include "xtensa-isa.h" #include "xtensa-config.h" +/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ +#define OCTETS_PER_BYTE(ABFD, SEC) 1 + #define XTENSA_NO_NOP_REMOVAL 0 /* Local helper functions. */ @@ -63,6 +66,8 @@ static bfd_boolean is_alt_relocation (int); static bfd_boolean is_operand_relocation (int); static bfd_size_type insn_decode_len (bfd_byte *, bfd_size_type, bfd_size_type); +static int insn_num_slots + (bfd_byte *, bfd_size_type, bfd_size_type); static xtensa_opcode insn_decode_opcode (bfd_byte *, bfd_size_type, bfd_size_type, int); static bfd_boolean check_branch_target_aligned @@ -110,7 +115,6 @@ static bfd_boolean xtensa_is_proptable_section (asection *); static int internal_reloc_compare (const void *, const void *); static int internal_reloc_matches (const void *, const void *); static asection *xtensa_get_property_section (asection *, const char *); -extern asection *xtensa_make_property_section (asection *, const char *); static flagword xtensa_get_property_predef_flags (asection *); /* Other functions called directly by the linker. */ @@ -155,6 +159,11 @@ static bfd_boolean relaxing_section = FALSE; int elf32xtensa_no_literal_movement = 1; +/* Place property records for a section into individual property section + with xt.prop. prefix. */ + +bfd_boolean elf32xtensa_separate_props = FALSE; + /* Rename one of the generic section flags to better document how it is used here. */ /* Whether relocations have been processed. */ @@ -215,11 +224,11 @@ static reloc_howto_type elf_howto_table[] = /* GNU extension to record C++ vtable hierarchy. */ HOWTO (R_XTENSA_GNU_VTINHERIT, 0, 2, 0, FALSE, 0, complain_overflow_dont, - NULL, "R_XTENSA_GNU_VTINHERIT", + NULL, "R_XTENSA_GNU_VTINHERIT", FALSE, 0, 0, FALSE), /* GNU extension to record C++ vtable member usage. */ HOWTO (R_XTENSA_GNU_VTENTRY, 0, 2, 0, FALSE, 0, complain_overflow_dont, - _bfd_elf_rel_vtable_reloc_fn, "R_XTENSA_GNU_VTENTRY", + _bfd_elf_rel_vtable_reloc_fn, "R_XTENSA_GNU_VTENTRY", FALSE, 0, 0, FALSE), /* Relocations for supporting difference of symbols. */ @@ -451,6 +460,9 @@ elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, break; } + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, (int) code); + bfd_set_error (bfd_error_bad_value); TRACE ("Unknown"); return NULL; } @@ -473,8 +485,8 @@ elf_xtensa_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, /* Given an ELF "rela" relocation, find the corresponding howto and record it in the BFD internal arelent representation of the relocation. */ -static void -elf_xtensa_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, +static bfd_boolean +elf_xtensa_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) { @@ -482,10 +494,14 @@ elf_xtensa_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, if (r_type >= (unsigned int) R_XTENSA_max) { - _bfd_error_handler (_("%B: invalid XTENSA reloc number: %d"), abfd, r_type); - r_type = 0; + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return FALSE; } cache_ptr->howto = &elf_howto_table[r_type]; + return TRUE; } @@ -519,28 +535,42 @@ elf_xtensa_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, invoked. Note: the 32-byte frame size used here cannot be changed without a corresponding change in the runtime linker. */ -static const bfd_byte elf_xtensa_be_plt_entry[PLT_ENTRY_SIZE] = +static const bfd_byte elf_xtensa_be_plt_entry[][PLT_ENTRY_SIZE] = { -#if XSHAL_ABI == XTHAL_ABI_WINDOWED - 0x6c, 0x10, 0x04, /* entry sp, 32 */ -#endif - 0x18, 0x00, 0x00, /* l32r a8, [got entry for rtld's resolver] */ - 0x1a, 0x00, 0x00, /* l32r a10, [got entry for rtld's link map] */ - 0x1b, 0x00, 0x00, /* l32r a11, [literal for reloc index] */ - 0x0a, 0x80, 0x00, /* jx a8 */ - 0 /* unused */ + { + 0x6c, 0x10, 0x04, /* entry sp, 32 */ + 0x18, 0x00, 0x00, /* l32r a8, [got entry for rtld's resolver] */ + 0x1a, 0x00, 0x00, /* l32r a10, [got entry for rtld's link map] */ + 0x1b, 0x00, 0x00, /* l32r a11, [literal for reloc index] */ + 0x0a, 0x80, 0x00, /* jx a8 */ + 0 /* unused */ + }, + { + 0x18, 0x00, 0x00, /* l32r a8, [got entry for rtld's resolver] */ + 0x1a, 0x00, 0x00, /* l32r a10, [got entry for rtld's link map] */ + 0x1b, 0x00, 0x00, /* l32r a11, [literal for reloc index] */ + 0x0a, 0x80, 0x00, /* jx a8 */ + 0 /* unused */ + } }; -static const bfd_byte elf_xtensa_le_plt_entry[PLT_ENTRY_SIZE] = +static const bfd_byte elf_xtensa_le_plt_entry[][PLT_ENTRY_SIZE] = { -#if XSHAL_ABI == XTHAL_ABI_WINDOWED - 0x36, 0x41, 0x00, /* entry sp, 32 */ -#endif - 0x81, 0x00, 0x00, /* l32r a8, [got entry for rtld's resolver] */ - 0xa1, 0x00, 0x00, /* l32r a10, [got entry for rtld's link map] */ - 0xb1, 0x00, 0x00, /* l32r a11, [literal for reloc index] */ - 0xa0, 0x08, 0x00, /* jx a8 */ - 0 /* unused */ + { + 0x36, 0x41, 0x00, /* entry sp, 32 */ + 0x81, 0x00, 0x00, /* l32r a8, [got entry for rtld's resolver] */ + 0xa1, 0x00, 0x00, /* l32r a10, [got entry for rtld's link map] */ + 0xb1, 0x00, 0x00, /* l32r a11, [literal for reloc index] */ + 0xa0, 0x08, 0x00, /* jx a8 */ + 0 /* unused */ + }, + { + 0x81, 0x00, 0x00, /* l32r a8, [got entry for rtld's resolver] */ + 0xa1, 0x00, 0x00, /* l32r a10, [got entry for rtld's link map] */ + 0xb1, 0x00, 0x00, /* l32r a11, [literal for reloc index] */ + 0xa0, 0x08, 0x00, /* jx a8 */ + 0 /* unused */ + } }; /* The size of the thread control block. */ @@ -600,11 +630,6 @@ struct elf_xtensa_link_hash_table struct elf_link_hash_table elf; /* Short-cuts to get to dynamic linker sections. */ - asection *sgot; - asection *sgotplt; - asection *srelgot; - asection *splt; - asection *srelplt; asection *sgotloc; asection *spltlittbl; @@ -782,7 +807,7 @@ property_table_matches (const void *ap, const void *bp) section. Sets TABLE_P and returns the number of entries. On error, returns a negative value. */ -static int +int xtensa_read_table_entries (bfd *abfd, asection *section, property_table_entry **table_p, @@ -903,7 +928,7 @@ xtensa_read_table_entries (bfd *abfd, property_table_compare); /* Check that the table contents are valid. Problems may occur, - for example, if an unrelocated object file is stripped. */ + for example, if an unrelocated object file is stripped. */ for (blk = 1; blk < block_count; blk++) { /* The only circumstance where two entries may legitimately @@ -913,8 +938,9 @@ xtensa_read_table_entries (bfd *abfd, if (blocks[blk - 1].address == blocks[blk].address && blocks[blk - 1].size != 0) { - (*_bfd_error_handler) (_("%B(%A): invalid property table"), - abfd, section); + /* xgettext:c-format */ + _bfd_error_handler (_("%pB(%pA): invalid property table"), + abfd, section); bfd_set_error (bfd_error_bad_value); free (blocks); return -1; @@ -991,7 +1017,7 @@ elf_xtensa_check_relocs (bfd *abfd, for (rel = relocs; rel < rel_end; rel++) { unsigned int r_type; - unsigned long r_symndx; + unsigned r_symndx; struct elf_link_hash_entry *h = NULL; struct elf_xtensa_link_hash_entry *eh; int tls_type, old_tls_type; @@ -1004,8 +1030,9 @@ elf_xtensa_check_relocs (bfd *abfd, if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { - (*_bfd_error_handler) (_("%B: bad symbol index: %d"), - abfd, r_symndx); + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: bad symbol index: %d"), + abfd, r_symndx); return FALSE; } @@ -1015,10 +1042,6 @@ elf_xtensa_check_relocs (bfd *abfd, while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - - /* PR15323, ref flags aren't set for references in the same - object. */ - h->root.non_ir_ref = 1; } eh = elf_xtensa_hash_entry (h); @@ -1084,9 +1107,7 @@ elf_xtensa_check_relocs (bfd *abfd, case R_XTENSA_GNU_VTENTRY: /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ - 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; continue; @@ -1180,8 +1201,9 @@ elf_xtensa_check_relocs (bfd *abfd, tls_type |= old_tls_type; else { - (*_bfd_error_handler) - (_("%B: `%s' accessed both as normal and thread local symbol"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: `%s' accessed both as normal and thread local symbol"), abfd, h ? h->root.root.string : ""); return FALSE; @@ -1203,19 +1225,19 @@ elf_xtensa_check_relocs (bfd *abfd, static void elf_xtensa_make_sym_local (struct bfd_link_info *info, - struct elf_link_hash_entry *h) + struct elf_link_hash_entry *h) { if (bfd_link_pic (info)) { if (h->plt.refcount > 0) - { + { /* For shared objects, there's no need for PLT entries for local symbols (use RELATIVE relocs instead of JMP_SLOT relocs). */ - if (h->got.refcount < 0) - h->got.refcount = 0; - h->got.refcount += h->plt.refcount; - h->plt.refcount = 0; - } + if (h->got.refcount < 0) + h->got.refcount = 0; + h->got.refcount += h->plt.refcount; + h->plt.refcount = 0; + } } else { @@ -1228,8 +1250,8 @@ elf_xtensa_make_sym_local (struct bfd_link_info *info, static void elf_xtensa_hide_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *h, - bfd_boolean force_local) + struct elf_link_hash_entry *h, + bfd_boolean force_local) { /* For a shared link, move the plt refcount to the got refcount to leave space for RELATIVE relocs. */ @@ -1274,137 +1296,6 @@ elf_xtensa_gc_mark_hook (asection *sec, } -/* Update the GOT & PLT entry reference counts - for the section being removed. */ - -static bfd_boolean -elf_xtensa_gc_sweep_hook (bfd *abfd, - struct bfd_link_info *info, - asection *sec, - const Elf_Internal_Rela *relocs) -{ - Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes; - const Elf_Internal_Rela *rel, *relend; - struct elf_xtensa_link_hash_table *htab; - - htab = elf_xtensa_hash_table (info); - if (htab == NULL) - return FALSE; - - if (bfd_link_relocatable (info)) - return TRUE; - - if ((sec->flags & SEC_ALLOC) == 0) - return TRUE; - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - sym_hashes = elf_sym_hashes (abfd); - - relend = relocs + sec->reloc_count; - for (rel = relocs; rel < relend; rel++) - { - unsigned long r_symndx; - unsigned int r_type; - struct elf_link_hash_entry *h = NULL; - struct elf_xtensa_link_hash_entry *eh; - bfd_boolean is_got = FALSE; - bfd_boolean is_plt = FALSE; - bfd_boolean is_tlsfunc = FALSE; - - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - } - eh = elf_xtensa_hash_entry (h); - - r_type = ELF32_R_TYPE (rel->r_info); - switch (r_type) - { - case R_XTENSA_TLSDESC_FN: - if (bfd_link_pic (info)) - { - is_got = TRUE; - is_tlsfunc = TRUE; - } - break; - - case R_XTENSA_TLSDESC_ARG: - if (bfd_link_pic (info)) - is_got = TRUE; - else - { - if (h && elf_xtensa_hash_entry (h) != htab->tlsbase) - is_got = TRUE; - } - break; - - case R_XTENSA_TLS_TPOFF: - if (bfd_link_pic (info) || h) - is_got = TRUE; - break; - - case R_XTENSA_32: - is_got = TRUE; - break; - - case R_XTENSA_PLT: - is_plt = TRUE; - break; - - default: - continue; - } - - if (h) - { - if (is_plt) - { - /* If the symbol has been localized its plt.refcount got moved - to got.refcount. Handle it as GOT. */ - if (h->plt.refcount > 0) - h->plt.refcount--; - else - is_got = TRUE; - } - if (is_got) - { - if (h->got.refcount > 0) - h->got.refcount--; - } - if (is_tlsfunc) - { - if (eh->tlsfunc_refcount > 0) - eh->tlsfunc_refcount--; - } - } - else - { - if (is_got || is_plt) - { - bfd_signed_vma *got_refcount - = &elf_local_got_refcounts (abfd) [r_symndx]; - if (*got_refcount > 0) - *got_refcount -= 1; - } - if (is_tlsfunc) - { - bfd_signed_vma *tlsfunc_refcount - = &elf_xtensa_local_tlsfunc_refcounts (abfd) [r_symndx]; - if (*tlsfunc_refcount > 0) - *tlsfunc_refcount -= 1; - } - } - } - - return TRUE; -} - - /* Create all the dynamic sections. */ static bfd_boolean @@ -1420,11 +1311,6 @@ elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) /* First do all the standard stuff. */ if (! _bfd_elf_create_dynamic_sections (dynobj, info)) return FALSE; - htab->splt = bfd_get_linker_section (dynobj, ".plt"); - htab->srelplt = bfd_get_linker_section (dynobj, ".rela.plt"); - htab->sgot = bfd_get_linker_section (dynobj, ".got"); - htab->sgotplt = bfd_get_linker_section (dynobj, ".got.plt"); - htab->srelgot = bfd_get_linker_section (dynobj, ".rela.got"); /* Create any extra PLT sections in case check_relocs has already been called on all the non-dynamic input files. */ @@ -1436,22 +1322,22 @@ elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) flags = noalloc_flags | SEC_ALLOC | SEC_LOAD; /* Mark the ".got.plt" section READONLY. */ - if (htab->sgotplt == NULL - || ! bfd_set_section_flags (dynobj, htab->sgotplt, flags)) + if (htab->elf.sgotplt == NULL + || !bfd_set_section_flags (htab->elf.sgotplt, flags)) return FALSE; /* Create ".got.loc" (literal tables for use by dynamic linker). */ htab->sgotloc = bfd_make_section_anyway_with_flags (dynobj, ".got.loc", flags); if (htab->sgotloc == NULL - || ! bfd_set_section_alignment (dynobj, htab->sgotloc, 2)) + || !bfd_set_section_alignment (htab->sgotloc, 2)) return FALSE; /* Create ".xt.lit.plt" (literal table for ".got.plt*"). */ htab->spltlittbl = bfd_make_section_anyway_with_flags (dynobj, ".xt.lit.plt", noalloc_flags); if (htab->spltlittbl == NULL - || ! bfd_set_section_alignment (dynobj, htab->spltlittbl, 2)) + || !bfd_set_section_alignment (htab->spltlittbl, 2)) return FALSE; return TRUE; @@ -1483,14 +1369,14 @@ add_extra_plt_sections (struct bfd_link_info *info, int count) sprintf (sname, ".plt.%u", chunk); s = bfd_make_section_anyway_with_flags (dynobj, sname, flags | SEC_CODE); if (s == NULL - || ! bfd_set_section_alignment (dynobj, s, 2)) + || !bfd_set_section_alignment (s, 2)) return FALSE; sname = (char *) bfd_malloc (14); sprintf (sname, ".got.plt.%u", chunk); s = bfd_make_section_anyway_with_flags (dynobj, sname, flags); if (s == NULL - || ! bfd_set_section_alignment (dynobj, s, 2)) + || !bfd_set_section_alignment (s, 2)) return FALSE; } @@ -1511,12 +1397,12 @@ elf_xtensa_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ - if (h->u.weakdef) + if (h->is_weakalias) { - BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined - || h->u.weakdef->root.type == bfd_link_hash_defweak); - h->root.u.def.section = h->u.weakdef->root.u.def.section; - h->root.u.def.value = h->u.weakdef->root.u.def.value; + struct elf_link_hash_entry *def = weakdef (h); + BFD_ASSERT (def->root.type == bfd_link_hash_defined); + h->root.u.def.section = def->root.u.def.section; + h->root.u.def.value = def->root.u.def.value; return TRUE; } @@ -1554,11 +1440,15 @@ elf_xtensa_allocate_dynrelocs (struct elf_link_hash_entry *h, void *arg) if (! elf_xtensa_dynamic_symbol_p (h, info)) elf_xtensa_make_sym_local (info, h); + if (! elf_xtensa_dynamic_symbol_p (h, info) + && h->root.type == bfd_link_hash_undefweak) + return TRUE; + if (h->plt.refcount > 0) - htab->srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela)); + htab->elf.srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela)); if (h->got.refcount > 0) - htab->srelgot->size += (h->got.refcount * sizeof (Elf32_External_Rela)); + htab->elf.srelgot->size += (h->got.refcount * sizeof (Elf32_External_Rela)); return TRUE; } @@ -1600,8 +1490,8 @@ elf_xtensa_allocate_local_got_size (struct bfd_link_info *info) } if (local_got_refcounts[j] > 0) - htab->srelgot->size += (local_got_refcounts[j] - * sizeof (Elf32_External_Rela)); + htab->elf.srelgot->size += (local_got_refcounts[j] + * sizeof (Elf32_External_Rela)); } } } @@ -1629,14 +1519,14 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, dynobj = elf_hash_table (info)->dynobj; if (dynobj == NULL) abort (); - srelgot = htab->srelgot; - srelplt = htab->srelplt; + srelgot = htab->elf.srelgot; + srelplt = htab->elf.srelplt; if (elf_hash_table (info)->dynamic_sections_created) { - BFD_ASSERT (htab->srelgot != NULL - && htab->srelplt != NULL - && htab->sgot != NULL + BFD_ASSERT (htab->elf.srelgot != NULL + && htab->elf.srelplt != NULL + && htab->elf.sgot != NULL && htab->spltlittbl != NULL && htab->sgotloc != NULL); @@ -1651,7 +1541,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, } /* Allocate room for one word in ".got". */ - htab->sgot->size = 4; + htab->elf.sgot->size = 4; /* Allocate space in ".rela.got" for literals that reference global symbols and space in ".rela.plt" for literals that have PLT @@ -1739,7 +1629,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* It's OK to base decisions on the section name, because none of the dynobj section names depend upon the input files. */ - name = bfd_get_section_name (dynobj, s); + name = bfd_section_name (s); if (CONST_STRNEQ (name, ".rela")) { @@ -1987,7 +1877,7 @@ elf_xtensa_do_reloc (reloc_howto_type *howto, case R_XTENSA_ASM_SIMPLIFY: { - /* Convert the L32R/CALLX to CALL. */ + /* Convert the L32R/CALLX to CALL. */ bfd_reloc_status_type retval = elf_xtensa_do_asm_simplify (contents, address, input_size, error_message); @@ -2070,8 +1960,9 @@ elf_xtensa_do_reloc (reloc_howto_type *howto, } else if (opcode == get_const16_opcode ()) { - /* ALT used for high 16 bits. */ - newval = relocation >> 16; + /* ALT used for high 16 bits. + Ignore 32-bit overflow. */ + newval = (relocation >> 16) & 0xffff; opnd = 1; } else @@ -2215,7 +2106,8 @@ bfd_elf_xtensa_reloc (bfd *abfd, { bfd_vma relocation; bfd_reloc_status_type flag; - bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd); + bfd_size_type octets = (reloc_entry->address + * OCTETS_PER_BYTE (abfd, input_section)); bfd_vma output_base = 0; reloc_howto_type *howto = reloc_entry->howto; asection *reloc_target_output_section; @@ -2343,8 +2235,8 @@ elf_xtensa_create_plt_entry (struct bfd_link_info *info, /* Fill in the entry in the procedure linkage table. */ memcpy (splt->contents + code_offset, (bfd_big_endian (output_bfd) - ? elf_xtensa_be_plt_entry - : elf_xtensa_le_plt_entry), + ? elf_xtensa_be_plt_entry[XSHAL_ABI != XTHAL_ABI_WINDOWED] + : elf_xtensa_le_plt_entry[XSHAL_ABI != XTHAL_ABI_WINDOWED]), PLT_ENTRY_SIZE); abi_offset = XSHAL_ABI == XTHAL_ABI_WINDOWED ? 3 : 0; bfd_put_16 (output_bfd, l32r_offset (got_base + 0, @@ -2528,7 +2420,7 @@ replace_tls_insn (Elf_Internal_Rela *rel, xtensa_format_set_slot (isa, fmt, 0, ibuff, sbuff); xtensa_insnbuf_to_chars (isa, ibuff, contents + rel->r_offset, - input_size - rel->r_offset); + input_size - rel->r_offset); return TRUE; } @@ -2571,7 +2463,11 @@ elf_xtensa_relocate_section (bfd *output_bfd, if (!xtensa_default_isa) xtensa_default_isa = xtensa_isa_init (0, 0); - BFD_ASSERT (is_xtensa_elf (input_bfd)); + if (!is_xtensa_elf (input_bfd)) + { + bfd_set_error (bfd_error_wrong_format); + return FALSE; + } htab = elf_xtensa_hash_table (info); if (htab == NULL) @@ -2778,9 +2674,12 @@ elf_xtensa_relocate_section (bfd *output_bfd, if (rel->r_offset >= input_size && ELF32_R_TYPE (rel->r_info) != R_XTENSA_NONE) { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): relocation offset out of range (size=0x%x)"), - input_bfd, input_section, rel->r_offset, input_size); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA+%#" PRIx64 "): " + "relocation offset out of range (size=%#" PRIx64 ")"), + input_bfd, input_section, (uint64_t) rel->r_offset, + (uint64_t) input_size); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -2792,7 +2691,7 @@ elf_xtensa_relocate_section (bfd *output_bfd, name = (bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name)); if (name == NULL || *name == '\0') - name = bfd_section_name (input_bfd, sec); + name = bfd_section_name (sec); } if (r_symndx != STN_UNDEF @@ -2802,13 +2701,15 @@ elf_xtensa_relocate_section (bfd *output_bfd, || h->root.type == bfd_link_hash_defweak) && IS_XTENSA_TLS_RELOC (r_type) != (sym_type == STT_TLS)) { - (*_bfd_error_handler) + _bfd_error_handler ((sym_type == STT_TLS - ? _("%B(%A+0x%lx): %s used with TLS symbol %s") - : _("%B(%A+0x%lx): %s used with non-TLS symbol %s")), + /* xgettext:c-format */ + ? _("%pB(%pA+%#" PRIx64 "): %s used with TLS symbol %s") + /* xgettext:c-format */ + : _("%pB(%pA+%#" PRIx64 "): %s used with non-TLS symbol %s")), input_bfd, input_section, - (long) rel->r_offset, + (uint64_t) rel->r_offset, howto->name, name); } @@ -2834,9 +2735,9 @@ elf_xtensa_relocate_section (bfd *output_bfd, asection *srel; if (dynamic_symbol && r_type == R_XTENSA_PLT) - srel = htab->srelplt; + srel = htab->elf.srelplt; else - srel = htab->srelgot; + srel = htab->elf.srelgot; BFD_ASSERT (srel != NULL); @@ -2889,12 +2790,16 @@ elf_xtensa_relocate_section (bfd *output_bfd, } unresolved_reloc = FALSE; } - else + else if (!is_weak_undef) { /* Generate a RELATIVE relocation. */ outrel.r_info = ELF32_R_INFO (0, R_XTENSA_RELATIVE); outrel.r_addend = 0; } + else + { + continue; + } } loc = (srel->contents @@ -2963,7 +2868,7 @@ elf_xtensa_relocate_section (bfd *output_bfd, { Elf_Internal_Rela outrel; bfd_byte *loc; - asection *srel = htab->srelgot; + asection *srel = htab->elf.srelgot; int indx; outrel.r_offset = (input_section->output_section->vma @@ -3059,11 +2964,13 @@ elf_xtensa_relocate_section (bfd *output_bfd, && _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset) != (bfd_vma) -1) { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA+%#" PRIx64 "): " + "unresolvable %s relocation against symbol `%s'"), input_bfd, input_section, - (long) rel->r_offset, + (uint64_t) rel->r_offset, howto->name, name); return FALSE; @@ -3163,7 +3070,7 @@ elf_xtensa_combine_prop_entries (bfd *output_bfd, sgotloc_size = sgotloc->size; if (sgotloc_size != section_size) { - (*_bfd_error_handler) + _bfd_error_handler (_("internal inconsistency in size of .got.loc section")); return -1; } @@ -3258,7 +3165,7 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd, { struct elf_xtensa_link_hash_table *htab; bfd *dynobj; - asection *sdyn, *srelplt, *sgot, *sxtlit, *sgotloc; + asection *sdyn, *srelplt, *srelgot, *sgot, *sxtlit, *sgotloc; Elf32_External_Dyn *dyncon, *dynconend; int num_xtlit_entries = 0; @@ -3275,7 +3182,7 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd, /* Set the first entry in the global offset table to the address of the dynamic section. */ - sgot = htab->sgot; + sgot = htab->elf.sgot; if (sgot) { BFD_ASSERT (sgot->size == 4); @@ -3287,16 +3194,16 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd, sgot->contents); } - srelplt = htab->srelplt; + srelplt = htab->elf.srelplt; + srelgot = htab->elf.srelgot; if (srelplt && srelplt->size != 0) { - asection *sgotplt, *srelgot, *spltlittbl; + asection *sgotplt, *spltlittbl; int chunk, plt_chunks, plt_entries; Elf_Internal_Rela irela; bfd_byte *loc; unsigned rtld_reloc; - srelgot = htab->srelgot; spltlittbl = htab->spltlittbl; BFD_ASSERT (srelgot != NULL && spltlittbl != NULL); @@ -3362,14 +3269,6 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd, spltlittbl->contents + (chunk * 8) + 4); } - /* All the dynamic relocations have been emitted at this point. - Make sure the relocation sections are the correct size. */ - if (srelgot->size != (sizeof (Elf32_External_Rela) - * srelgot->reloc_count) - || srelplt->size != (sizeof (Elf32_External_Rela) - * srelplt->reloc_count)) - abort (); - /* The .xt.lit.plt section has just been modified. This must happen before the code below which combines adjacent literal table entries, and the .xt.lit.plt contents have to be forced to @@ -3384,6 +3283,14 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd, spltlittbl->flags &= ~SEC_HAS_CONTENTS; } + /* All the dynamic relocations have been emitted at this point. + Make sure the relocation sections are the correct size. */ + if ((srelgot && srelgot->size != (sizeof (Elf32_External_Rela) + * srelgot->reloc_count)) + || (srelplt && srelplt->size != (sizeof (Elf32_External_Rela) + * srelplt->reloc_count))) + abort (); + /* Combine adjacent literal table entries. */ BFD_ASSERT (! bfd_link_relocatable (info)); sxtlit = bfd_get_section_by_name (output_bfd, ".xt.lit"); @@ -3420,28 +3327,17 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd, break; case DT_PLTGOT: - dyn.d_un.d_ptr = (htab->sgot->output_section->vma - + htab->sgot->output_offset); + dyn.d_un.d_ptr = (htab->elf.sgot->output_section->vma + + htab->elf.sgot->output_offset); break; case DT_JMPREL: - dyn.d_un.d_ptr = (htab->srelplt->output_section->vma - + htab->srelplt->output_offset); + dyn.d_un.d_ptr = (htab->elf.srelplt->output_section->vma + + htab->elf.srelplt->output_offset); break; case DT_PLTRELSZ: - dyn.d_un.d_val = htab->srelplt->size; - break; - - case DT_RELASZ: - /* Adjust RELASZ to not include JMPREL. This matches what - glibc expects and what is done for several other ELF - targets (e.g., i386, alpha), but the "correct" behavior - seems to be unresolved. Since the linker script arranges - for .rela.plt to follow all other relocation sections, we - don't have to worry about changing the DT_RELA entry. */ - if (htab->srelplt) - dyn.d_un.d_val -= htab->srelplt->size; + dyn.d_un.d_val = htab->elf.srelplt->size; break; } @@ -3458,13 +3354,14 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd, object file when linking. */ static bfd_boolean -elf_xtensa_merge_private_bfd_data (bfd *ibfd, bfd *obfd) +elf_xtensa_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { + bfd *obfd = info->output_bfd; unsigned out_mach, in_mach; flagword out_flag, in_flag; /* Check if we have the same endianness. */ - if (!_bfd_generic_verify_endian_match (ibfd, obfd)) + if (!_bfd_generic_verify_endian_match (ibfd, info)) return FALSE; /* Don't even pretend to support mixed-format linking. */ @@ -3479,8 +3376,9 @@ elf_xtensa_merge_private_bfd_data (bfd *ibfd, bfd *obfd) in_mach = in_flag & EF_XTENSA_MACH; if (out_mach != in_mach) { - (*_bfd_error_handler) - (_("%B: incompatible machine type. Output is 0x%x. Input is 0x%x"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: incompatible machine type; output is 0x%x; input is 0x%x"), ibfd, out_mach, in_mach); bfd_set_error (bfd_error_wrong_format); return FALSE; @@ -3570,12 +3468,11 @@ elf_xtensa_object_p (bfd *abfd) file. This gets the Xtensa architecture right based on the machine number. */ -static void -elf_xtensa_final_write_processing (bfd *abfd, - bfd_boolean linker ATTRIBUTE_UNUSED) +static bfd_boolean +elf_xtensa_final_write_processing (bfd *abfd) { int mach; - unsigned long val; + unsigned long val = elf_elfheader (abfd)->e_flags & EF_XTENSA_MACH; switch (mach = bfd_get_mach (abfd)) { @@ -3583,11 +3480,12 @@ elf_xtensa_final_write_processing (bfd *abfd, val = E_XTENSA_MACH; break; default: - return; + break; } - elf_elfheader (abfd)->e_flags &= (~ EF_XTENSA_MACH); + elf_elfheader (abfd)->e_flags &= ~EF_XTENSA_MACH; elf_elfheader (abfd)->e_flags |= val; + return _bfd_elf_final_write_processing (abfd); } @@ -3965,6 +3863,33 @@ l32r_offset (bfd_vma addr, bfd_vma pc) } +static xtensa_opcode +get_rsr_lend_opcode (void) +{ + static xtensa_opcode rsr_lend_opcode = XTENSA_UNDEFINED; + static bfd_boolean done_lookup = FALSE; + if (!done_lookup) + { + rsr_lend_opcode = xtensa_opcode_lookup (xtensa_default_isa, "rsr.lend"); + done_lookup = TRUE; + } + return rsr_lend_opcode; +} + +static xtensa_opcode +get_wsr_lbeg_opcode (void) +{ + static xtensa_opcode wsr_lbeg_opcode = XTENSA_UNDEFINED; + static bfd_boolean done_lookup = FALSE; + if (!done_lookup) + { + wsr_lbeg_opcode = xtensa_opcode_lookup (xtensa_default_isa, "wsr.lbeg"); + done_lookup = TRUE; + } + return wsr_lbeg_opcode; +} + + static int get_relocation_opnd (xtensa_opcode opcode, int r_type) { @@ -4165,6 +4090,28 @@ insn_decode_len (bfd_byte *contents, return insn_len; } +int +insn_num_slots (bfd_byte *contents, + bfd_size_type content_len, + bfd_size_type offset) +{ + xtensa_isa isa = xtensa_default_isa; + xtensa_format fmt; + static xtensa_insnbuf ibuff = NULL; + + if (offset + MIN_INSN_LENGTH > content_len) + return XTENSA_UNDEFINED; + + if (ibuff == NULL) + ibuff = xtensa_insnbuf_alloc (isa); + xtensa_insnbuf_from_chars (isa, ibuff, &contents[offset], + content_len - offset); + fmt = xtensa_format_decode (isa, ibuff); + if (fmt == XTENSA_UNDEFINED) + return XTENSA_UNDEFINED; + return xtensa_format_num_slots (isa, fmt); +} + /* Decode the opcode for a single slot instruction. Return 0 if it fails to decode or the instruction is multi-slot. */ @@ -4244,6 +4191,20 @@ check_loop_aligned (bfd_byte *contents, return FALSE; } + /* If this is relaxed loop, analyze first instruction of the actual loop + body. It must be at offset 27 from the loop instruction address. */ + if (insn_len == 3 + && insn_num_slots (contents, content_length, offset + loop_len) == 1 + && insn_decode_opcode (contents, content_length, + offset + loop_len, 0) == get_rsr_lend_opcode() + && insn_decode_len (contents, content_length, offset + loop_len + 3) == 3 + && insn_num_slots (contents, content_length, offset + loop_len + 3) == 1 + && insn_decode_opcode (contents, content_length, + offset + loop_len + 3, 0) == get_wsr_lbeg_opcode()) + { + loop_len = 27; + insn_len = insn_decode_len (contents, content_length, offset + loop_len); + } return check_branch_target_aligned_address (address + loop_len, insn_len); } @@ -4711,7 +4672,7 @@ elf_xtensa_do_asm_simplify (bfd_byte *contents, if (content_length < address) { - *error_message = _("Attempt to convert L32R/CALLX to CALL failed"); + *error_message = _("attempt to convert L32R/CALLX to CALL failed"); return bfd_reloc_other; } @@ -4719,7 +4680,7 @@ elf_xtensa_do_asm_simplify (bfd_byte *contents, direct_call_opcode = swap_callx_for_call_opcode (opcode); if (direct_call_opcode == XTENSA_UNDEFINED) { - *error_message = _("Attempt to convert L32R/CALLX to CALL failed"); + *error_message = _("attempt to convert L32R/CALLX to CALL failed"); return bfd_reloc_other; } @@ -5365,23 +5326,23 @@ add_value_map (value_map_hash_table *map, /* The following text actions are generated: - "ta_remove_insn" remove an instruction or instructions - "ta_remove_longcall" convert longcall to call + "ta_remove_insn" remove an instruction or instructions + "ta_remove_longcall" convert longcall to call "ta_convert_longcall" convert longcall to nop/call - "ta_narrow_insn" narrow a wide instruction - "ta_widen" widen a narrow instruction - "ta_fill" add fill or remove fill + "ta_narrow_insn" narrow a wide instruction + "ta_widen" widen a narrow instruction + "ta_fill" add fill or remove fill removed < 0 is a fill; branches to the fill address will be changed to address + fill size (e.g., address - removed) removed >= 0 branches to the fill address will stay unchanged - "ta_remove_literal" remove a literal; this action is + "ta_remove_literal" remove a literal; this action is indicated when a literal is removed - or replaced. - "ta_add_literal" insert a new literal; this action is - indicated when a literal has been moved. - It may use a virtual_offset because + or replaced. + "ta_add_literal" insert a new literal; this action is + indicated when a literal has been moved. + It may use a virtual_offset because multiple literals can be placed at the - same location. + same location. For each of these text actions, we also record the number of bytes removed by performing the text action. In the case of a "ta_widen" @@ -5394,12 +5355,12 @@ typedef enum text_action_enum_t text_action_t; enum text_action_enum_t { ta_none, - ta_remove_insn, /* removed = -size */ - ta_remove_longcall, /* removed = -size */ - ta_convert_longcall, /* removed = 0 */ - ta_narrow_insn, /* removed = -1 */ - ta_widen_insn, /* removed = +1 */ - ta_fill, /* removed = +size */ + ta_remove_insn, /* removed = -size */ + ta_remove_longcall, /* removed = -size */ + ta_convert_longcall, /* removed = 0 */ + ta_narrow_insn, /* removed = -1 */ + ta_widen_insn, /* removed = +1 */ + ta_fill, /* removed = +size */ ta_remove_literal, ta_add_literal }; @@ -6545,9 +6506,12 @@ extend_ebb_bounds_forward (ebb_t *ebb) entry_end - ebb->end_offset); if (insn_block_len != (entry_end - ebb->end_offset)) { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"), - ebb->sec->owner, ebb->sec, ebb->end_offset + insn_block_len); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; " + "possible configuration mismatch"), + ebb->sec->owner, ebb->sec, + (uint64_t) (ebb->end_offset + insn_block_len)); return FALSE; } ebb->end_offset += insn_block_len; @@ -6621,9 +6585,12 @@ extend_ebb_bounds_backward (ebb_t *ebb) ebb->start_offset - block_begin); if (insn_block_len != ebb->start_offset - block_begin) { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"), - ebb->sec->owner, ebb->sec, ebb->end_offset + insn_block_len); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; " + "possible configuration mismatch"), + ebb->sec->owner, ebb->sec, + (uint64_t) (ebb->end_offset + insn_block_len)); return FALSE; } ebb->start_offset -= insn_block_len; @@ -6843,7 +6810,6 @@ static bfd_boolean check_section_ebb_pcrels_fit static bfd_boolean check_section_ebb_reduces (const ebb_constraint *); static void text_action_add_proposed (text_action_list *, const ebb_constraint *, asection *); -static int compute_fill_extra_space (property_table_entry *); /* First pass: */ static bfd_boolean compute_removed_literals @@ -7093,7 +7059,7 @@ find_relaxable_sections (bfd *abfd, continue; /* Count PC-relative operand relocations against the target section. - Note: The conditions tested here must match the conditions under + Note: The conditions tested here must match the conditions under which init_source_reloc is called in collect_source_relocs(). */ is_l32r_reloc = FALSE; if (is_operand_relocation (ELF32_R_TYPE (irel->r_info))) @@ -7296,6 +7262,11 @@ is_resolvable_asm_expansion (bfd *abfd, bfd_boolean *is_reachable_p) { asection *target_sec; + asection *s; + bfd_vma first_vma; + bfd_vma last_vma; + unsigned int first_align; + unsigned int adjust; bfd_vma target_offset; r_reloc r_rel; xtensa_opcode opcode, direct_call_opcode; @@ -7384,6 +7355,56 @@ is_resolvable_asm_expansion (bfd *abfd, + target_sec->output_offset + target_offset); } + /* Adjust addresses with alignments for the worst case to see if call insn + can fit. Don't relax l32r + callx to call if the target can be out of + range due to alignment. + Caller and target addresses are highest and lowest address. + Search all sections between caller and target, looking for max alignment. + The adjustment is max alignment bytes. If the alignment at the lowest + address is less than the adjustment, apply the adjustment to highest + address. */ + + /* Start from lowest address. + Lowest address aligmnet is from input section. + Initial alignment (adjust) is from input section. */ + if (dest_address > self_address) + { + s = sec->output_section; + last_vma = dest_address; + first_align = sec->alignment_power; + adjust = target_sec->alignment_power; + } + else + { + s = target_sec->output_section; + last_vma = self_address; + first_align = target_sec->alignment_power; + adjust = sec->alignment_power; + } + + first_vma = s->vma; + + /* Find the largest alignment in output section list. */ + for (; s && s->vma >= first_vma && s->vma <= last_vma ; s = s->next) + { + if (s->alignment_power > adjust) + adjust = s->alignment_power; + } + + if (adjust > first_align) + { + /* Alignment may enlarge the range, adjust highest address. */ + adjust = 1 << adjust; + if (dest_address > self_address) + { + dest_address += adjust; + } + else + { + self_address += adjust; + } + } + *is_reachable_p = pcrel_reloc_fits (direct_call_opcode, 0, self_address, dest_address); @@ -7540,7 +7561,7 @@ build_reloc_ranges (bfd *abfd, asection *sec, reloc[i].irel = irel; /* Every relocation won't possibly be checked in the optimized version of - check_section_ebb_pcrels_fit, so this needs to be done here. */ + check_section_ebb_pcrels_fit, so this needs to be done here. */ if (is_alt_relocation (ELF32_R_TYPE (irel->r_info))) { /* None of the current alternate relocs are PC-relative, @@ -7734,9 +7755,12 @@ compute_text_actions (bfd *abfd, simplify_size = get_asm_simplify_size (contents, sec_size, r_offset); if (simplify_size == 0) { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): could not decode instruction for XTENSA_ASM_SIMPLIFY relocation; possible configuration mismatch"), - sec->owner, sec, r_offset); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA+%#" PRIx64 "): could not decode instruction for " + "XTENSA_ASM_SIMPLIFY relocation; " + "possible configuration mismatch"), + sec->owner, sec, (uint64_t) r_offset); continue; } @@ -7992,9 +8016,11 @@ compute_ebb_proposed_actions (ebb_constraint *ebb_table) return TRUE; decode_error: - (*_bfd_error_handler) - (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"), - ebb->sec->owner, ebb->sec, offset); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; " + "possible configuration mismatch"), + ebb->sec->owner, ebb->sec, (uint64_t) offset); return FALSE; } @@ -8244,7 +8270,7 @@ compute_ebb_actions (ebb_constraint *ebb_table) BFD_ASSERT (action->action == ta_fill); BFD_ASSERT (ebb->ends_unreachable->flags & XTENSA_PROP_UNREACHABLE); - extra_space = compute_fill_extra_space (ebb->ends_unreachable); + extra_space = xtensa_compute_fill_extra_space (ebb->ends_unreachable); br = action->removed_bytes + removed_bytes + extra_space; br = br & ((1 << ebb->sec->alignment_power ) - 1); @@ -8263,8 +8289,8 @@ typedef struct xlate_map xlate_map_t; struct xlate_map_entry { - unsigned orig_address; - unsigned new_address; + bfd_vma orig_address; + bfd_vma new_address; unsigned size; }; @@ -8295,6 +8321,7 @@ xlate_offset_with_removed_text (const xlate_map_t *map, { void *r; xlate_map_entry_t *e; + struct xlate_map_entry se; if (map == NULL) return offset_with_removed_text (action_list, offset); @@ -8302,10 +8329,19 @@ xlate_offset_with_removed_text (const xlate_map_t *map, if (map->entry_count == 0) return offset; - r = bsearch (&offset, map->entry, map->entry_count, + se.orig_address = offset; + r = bsearch (&se, map->entry, map->entry_count, sizeof (xlate_map_entry_t), &xlate_compare); e = (xlate_map_entry_t *) r; + /* There could be a jump past the end of the section, + allow it using the last xlate map entry to translate its address. */ + if (e == NULL) + { + e = map->entry + map->entry_count - 1; + if (xlate_compare (&se, e) <= 0) + e = NULL; + } BFD_ASSERT (e != NULL); if (e == NULL) return offset; @@ -8658,7 +8694,7 @@ text_action_add_proposed (text_action_list *l, int -compute_fill_extra_space (property_table_entry *entry) +xtensa_compute_fill_extra_space (property_table_entry *entry) { int fill_extra_space; @@ -8939,7 +8975,7 @@ remove_dead_literal (bfd *abfd, do not add fill. */ the_add_entry = elf_xtensa_find_property_entry (prop_table, ptblsize, entry_sec_offset); - fill_extra_space = compute_fill_extra_space (the_add_entry); + fill_extra_space = xtensa_compute_fill_extra_space (the_add_entry); fa = find_fill_action (&relax_info->action_list, sec, entry_sec_offset); removed_diff = compute_removed_action_diff (fa, sec, entry_sec_offset, @@ -9115,7 +9151,7 @@ relocations_reach (source_reloc *reloc, continue; /* The original and new output section for these must be the same - in order to coalesce. */ + in order to coalesce. */ if (r_reloc_get_section (&reloc[i].r_rel)->output_section != sec->output_section) return FALSE; @@ -9485,7 +9521,7 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info) /* Update the action so that the code that moves the contents will do the right thing. */ /* ta_remove_longcall and ta_remove_insn actions are - grouped together in the tree as well as + grouped together in the tree as well as ta_convert_longcall and ta_none, so that changes below can be done w/o removing and reinserting action into the tree. */ @@ -10112,18 +10148,21 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info, if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT) && (input_section->flags & SEC_ALLOC) != 0 - && (dynamic_symbol || bfd_link_pic (info))) + && (dynamic_symbol || bfd_link_pic (info)) + && (!h || h->root.type != bfd_link_hash_undefweak + || (dynamic_symbol + && (bfd_link_dll (info) || info->export_dynamic)))) { asection *srel; bfd_boolean is_plt = FALSE; if (dynamic_symbol && r_type == R_XTENSA_PLT) { - srel = htab->srelplt; + srel = htab->elf.srelplt; is_plt = TRUE; } else - srel = htab->srelgot; + srel = htab->elf.srelgot; /* Reduce size of the .rela.* section by one reloc. */ BFD_ASSERT (srel != NULL); @@ -10152,7 +10191,7 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info, if (reloc_index % PLT_ENTRIES_PER_CHUNK == 0) { /* The two magic GOT entries for that chunk can go away. */ - srelgot = htab->srelgot; + srelgot = htab->elf.srelgot; BFD_ASSERT (srelgot != NULL); srelgot->reloc_count -= 2; srelgot->size -= 2 * sizeof (Elf32_External_Rela); @@ -10469,7 +10508,7 @@ relax_property_section (bfd *abfd, predef_flags = xtensa_get_property_predef_flags (sec); /* Walk over memory and relocations at the same time. - This REQUIRES that the internal_relocs be sorted by offset. */ + This REQUIRES that the internal_relocs be sorted by offset. */ qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela), internal_reloc_compare); @@ -10768,9 +10807,10 @@ do_fix_for_relocatable_link (Elf_Internal_Rela *rel, { if (r_type != R_XTENSA_ASM_EXPAND) { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): unexpected fix for %s relocation"), - input_bfd, input_section, rel->r_offset, + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA+%#" PRIx64 "): unexpected fix for %s relocation"), + input_bfd, input_section, (uint64_t) rel->r_offset, elf_howto_table[r_type].name); return FALSE; } @@ -10828,18 +10868,11 @@ do_fix_for_final_link (Elf_Internal_Rela *rel, static asection * elf_xtensa_get_plt_section (struct bfd_link_info *info, int chunk) { - struct elf_xtensa_link_hash_table *htab; bfd *dynobj; - char plt_name[10]; + char plt_name[17]; if (chunk == 0) - { - htab = elf_xtensa_hash_table (info); - if (htab == NULL) - return NULL; - - return htab->splt; - } + return elf_hash_table (info)->splt; dynobj = elf_hash_table (info)->dynobj; sprintf (plt_name, ".plt.%u", chunk); @@ -10850,17 +10883,11 @@ elf_xtensa_get_plt_section (struct bfd_link_info *info, int chunk) static asection * elf_xtensa_get_gotplt_section (struct bfd_link_info *info, int chunk) { - struct elf_xtensa_link_hash_table *htab; bfd *dynobj; - char got_name[14]; + char got_name[21]; if (chunk == 0) - { - htab = elf_xtensa_hash_table (info); - if (htab == NULL) - return NULL; - return htab->sgotplt; - } + return elf_hash_table (info)->sgotplt; dynobj = elf_hash_table (info)->dynobj; sprintf (got_name, ".got.plt.%u", chunk); @@ -10904,8 +10931,8 @@ get_elf_r_symndx_section (bfd *abfd, unsigned long r_symndx) struct elf_link_hash_entry *h = elf_sym_hashes (abfd)[indx]; while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; switch (h->root.type) { @@ -10969,10 +10996,10 @@ get_elf_r_symndx_offset (bfd *abfd, unsigned long r_symndx) elf_sym_hashes (abfd)[indx]; while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) + || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) + || h->root.type == bfd_link_hash_defweak) offset = h->root.u.def.value; } return offset; @@ -11102,10 +11129,30 @@ match_section_group (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf) } +static char * +xtensa_add_names (const char *base, const char *suffix) +{ + if (suffix) + { + size_t base_len = strlen (base); + size_t suffix_len = strlen (suffix); + char *str = bfd_malloc (base_len + suffix_len + 1); + + memcpy (str, base, base_len); + memcpy (str + base_len, suffix, suffix_len + 1); + return str; + } + else + { + return strdup (base); + } +} + static int linkonce_len = sizeof (".gnu.linkonce.") - 1; static char * -xtensa_property_section_name (asection *sec, const char *base_name) +xtensa_property_section_name (asection *sec, const char *base_name, + bfd_boolean separate_sections) { const char *suffix, *group_name; char *prop_sec_name; @@ -11116,11 +11163,7 @@ xtensa_property_section_name (asection *sec, const char *base_name) suffix = strrchr (sec->name, '.'); if (suffix == sec->name) suffix = 0; - prop_sec_name = (char *) bfd_malloc (strlen (base_name) + 1 - + (suffix ? strlen (suffix) : 0)); - strcpy (prop_sec_name, base_name); - if (suffix) - strcat (prop_sec_name, suffix); + prop_sec_name = xtensa_add_names (base_name, suffix); } else if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0) { @@ -11142,25 +11185,30 @@ xtensa_property_section_name (asection *sec, const char *base_name) suffix = sec->name + linkonce_len; /* For backward compatibility, replace "t." instead of inserting - the new linkonce_kind (but not for "prop" sections). */ + the new linkonce_kind (but not for "prop" sections). */ if (CONST_STRNEQ (suffix, "t.") && linkonce_kind[1] == '.') - suffix += 2; + suffix += 2; strcat (prop_sec_name + linkonce_len, suffix); } else - prop_sec_name = strdup (base_name); + { + prop_sec_name = xtensa_add_names (base_name, + separate_sections ? sec->name : NULL); + } return prop_sec_name; } static asection * -xtensa_get_property_section (asection *sec, const char *base_name) +xtensa_get_separate_property_section (asection *sec, const char *base_name, + bfd_boolean separate_section) { char *prop_sec_name; asection *prop_sec; - prop_sec_name = xtensa_property_section_name (sec, base_name); + prop_sec_name = xtensa_property_section_name (sec, base_name, + separate_section); prop_sec = bfd_get_section_by_name_if (sec->owner, prop_sec_name, match_section_group, (void *) elf_group_name (sec)); @@ -11168,6 +11216,21 @@ xtensa_get_property_section (asection *sec, const char *base_name) return prop_sec; } +static asection * +xtensa_get_property_section (asection *sec, const char *base_name) +{ + asection *prop_sec; + + /* Try individual property section first. */ + prop_sec = xtensa_get_separate_property_section (sec, base_name, TRUE); + + /* Refer to a common property section if individual is not present. */ + if (!prop_sec) + prop_sec = xtensa_get_separate_property_section (sec, base_name, FALSE); + + return prop_sec; +} + asection * xtensa_make_property_section (asection *sec, const char *base_name) @@ -11176,7 +11239,8 @@ xtensa_make_property_section (asection *sec, const char *base_name) asection *prop_sec; /* Check if the section already exists. */ - prop_sec_name = xtensa_property_section_name (sec, base_name); + prop_sec_name = xtensa_property_section_name (sec, base_name, + elf32xtensa_separate_props); prop_sec = bfd_get_section_by_name_if (sec->owner, prop_sec_name, match_section_group, (void *) elf_group_name (sec)); @@ -11184,7 +11248,7 @@ xtensa_make_property_section (asection *sec, const char *base_name) if (! prop_sec) { flagword flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY); - flags |= (bfd_get_section_flags (sec->owner, sec) + flags |= (bfd_section_flags (sec) & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES)); prop_sec = bfd_make_section_anyway_with_flags @@ -11243,7 +11307,7 @@ xtensa_callback_required_dependence (bfd *abfd, /* Find the corresponding ".got.plt*" section. */ if (sec->name[4] == '\0') - sgotplt = bfd_get_linker_section (sec->owner, ".got.plt"); + sgotplt = elf_hash_table (link_info)->sgotplt; else { char got_name[14]; @@ -11321,9 +11385,9 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] = { { STRING_COMMA_LEN (".fini.literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, { STRING_COMMA_LEN (".init.literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, - { STRING_COMMA_LEN (".literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, - { STRING_COMMA_LEN (".xtensa.info"), 0, SHT_NOTE, 0 }, - { NULL, 0, 0, 0, 0 } + { STRING_COMMA_LEN (".literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, + { STRING_COMMA_LEN (".xtensa.info"), 0, SHT_NOTE, 0 }, + { NULL, 0, 0, 0, 0 } }; #define ELF_TARGET_ID XTENSA_ELF_DATA @@ -11337,11 +11401,7 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] = #define ELF_MACHINE_CODE EM_XTENSA #define ELF_MACHINE_ALT1 EM_XTENSA_OLD -#if XCHAL_HAVE_MMU -#define ELF_MAXPAGESIZE (1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE) -#else /* !XCHAL_HAVE_MMU */ -#define ELF_MAXPAGESIZE 1 -#endif /* !XCHAL_HAVE_MMU */ +#define ELF_MAXPAGESIZE 0x1000 #endif /* ELF_ARCH */ #define elf_backend_can_gc_sections 1 @@ -11350,6 +11410,7 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] = #define elf_backend_got_header_size 4 #define elf_backend_want_dynbss 0 #define elf_backend_want_got_plt 1 +#define elf_backend_dtrel_excludes_plt 1 #define elf_info_to_howto elf_xtensa_info_to_howto_rela @@ -11374,7 +11435,6 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] = #define elf_backend_finish_dynamic_sections elf_xtensa_finish_dynamic_sections #define elf_backend_finish_dynamic_symbol elf_xtensa_finish_dynamic_symbol #define elf_backend_gc_mark_hook elf_xtensa_gc_mark_hook -#define elf_backend_gc_sweep_hook elf_xtensa_gc_sweep_hook #define elf_backend_grok_prstatus elf_xtensa_grok_prstatus #define elf_backend_grok_psinfo elf_xtensa_grok_psinfo #define elf_backend_hide_symbol elf_xtensa_hide_symbol @@ -11383,8 +11443,7 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] = #define elf_backend_relocate_section elf_xtensa_relocate_section #define elf_backend_size_dynamic_sections elf_xtensa_size_dynamic_sections #define elf_backend_always_size_sections elf_xtensa_always_size_sections -#define elf_backend_omit_section_dynsym \ - ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) +#define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all #define elf_backend_special_sections elf_xtensa_special_sections #define elf_backend_action_discarded elf_xtensa_action_discarded #define elf_backend_copy_indirect_symbol elf_xtensa_copy_indirect_symbol