X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-xtensa.c;h=12ff9f772aafaa577f1ac582e3cc9c9205dd9625;hb=74375d182e992778ef8701278c02a742db6be77e;hp=93394547ce4a311c43ed3c06f4645a5c5444b06e;hpb=cc364be6ff45669150077387f22723de33d5f1b1;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index 93394547ce..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-2019 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 @@ -1318,21 +1323,21 @@ elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) /* Mark the ".got.plt" section READONLY. */ if (htab->elf.sgotplt == NULL - || ! bfd_set_section_flags (dynobj, htab->elf.sgotplt, flags)) + || !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; @@ -1364,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; } @@ -1624,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")) { @@ -2101,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; @@ -2685,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 @@ -3857,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) { @@ -4057,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. */ @@ -4136,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); } @@ -11179,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