gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / elf32-xtensa.c
index 19a162eebbbadc88c833708a83bd6c3cb76c940c..05c4f8430a2046a9c48546c815f0eb2ebdb2f728 100644 (file)
@@ -1,5 +1,5 @@
 /* Xtensa-specific support for 32-bit ELF.
-   Copyright (C) 2003-2017 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
@@ -154,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.  */
@@ -214,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.  */
@@ -315,6 +325,20 @@ static reloc_howto_type elf_howto_table[] =
   HOWTO (R_XTENSA_TLS_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
         bfd_elf_xtensa_reloc, "R_XTENSA_TLS_CALL",
         FALSE, 0, 0, FALSE),
+
+  HOWTO (R_XTENSA_PDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF8", FALSE, 0, 0xff, FALSE),
+  HOWTO (R_XTENSA_PDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF16", FALSE, 0, 0xffff, FALSE),
+  HOWTO (R_XTENSA_PDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF32", FALSE, 0, 0xffffffff, FALSE),
+
+  HOWTO (R_XTENSA_NDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF8", FALSE, 0, 0xff, FALSE),
+  HOWTO (R_XTENSA_NDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF16", FALSE, 0, 0xffff, FALSE),
+  HOWTO (R_XTENSA_NDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF32", FALSE, 0, 0xffffffff, FALSE),
 };
 
 #if DEBUG_GEN_RELOC
@@ -354,6 +378,30 @@ elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       TRACE ("BFD_RELOC_XTENSA_DIFF32");
       return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];
 
+    case BFD_RELOC_XTENSA_PDIFF8:
+      TRACE ("BFD_RELOC_XTENSA_PDIFF8");
+      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF8 ];
+
+    case BFD_RELOC_XTENSA_PDIFF16:
+      TRACE ("BFD_RELOC_XTENSA_PDIFF16");
+      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF16 ];
+
+    case BFD_RELOC_XTENSA_PDIFF32:
+      TRACE ("BFD_RELOC_XTENSA_PDIFF32");
+      return &elf_howto_table[(unsigned) R_XTENSA_PDIFF32 ];
+
+    case BFD_RELOC_XTENSA_NDIFF8:
+      TRACE ("BFD_RELOC_XTENSA_NDIFF8");
+      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF8 ];
+
+    case BFD_RELOC_XTENSA_NDIFF16:
+      TRACE ("BFD_RELOC_XTENSA_NDIFF16");
+      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF16 ];
+
+    case BFD_RELOC_XTENSA_NDIFF32:
+      TRACE ("BFD_RELOC_XTENSA_NDIFF32");
+      return &elf_howto_table[(unsigned) R_XTENSA_NDIFF32 ];
+
     case BFD_RELOC_XTENSA_RTLD:
       TRACE ("BFD_RELOC_XTENSA_RTLD");
       return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
@@ -450,6 +498,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;
 }
@@ -472,8 +523,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 +533,13 @@ elf_xtensa_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   if (r_type >= (unsigned int) R_XTENSA_max)
     {
       /* xgettext:c-format */
-      _bfd_error_handler (_("%B: invalid XTENSA reloc number: %d"), abfd, r_type);
-      r_type = 0;
+      _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;
 }
 
 \f
@@ -670,7 +724,7 @@ elf_xtensa_link_hash_table_create (bfd *abfd)
 {
   struct elf_link_hash_entry *tlsbase;
   struct elf_xtensa_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct elf_xtensa_link_hash_table);
+  size_t amt = sizeof (struct elf_xtensa_link_hash_table);
 
   ret = bfd_zmalloc (amt);
   if (ret == NULL)
@@ -791,7 +845,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,
@@ -912,7 +966,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
@@ -923,7 +977,7 @@ xtensa_read_table_entries (bfd *abfd,
              blocks[blk - 1].size != 0)
            {
              /* xgettext:c-format */
-             _bfd_error_handler (_("%B(%A): invalid property table"),
+             _bfd_error_handler (_("%pB(%pA): invalid property table"),
                                  abfd, section);
              bfd_set_error (bfd_error_bad_value);
              free (blocks);
@@ -1015,7 +1069,7 @@ elf_xtensa_check_relocs (bfd *abfd,
       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
        {
          /* xgettext:c-format */
-         _bfd_error_handler (_("%B: bad symbol index: %d"),
+         _bfd_error_handler (_("%pB: bad symbol index: %d"),
                              abfd, r_symndx);
          return FALSE;
        }
@@ -1026,10 +1080,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_regular = 1;
        }
       eh = elf_xtensa_hash_entry (h);
 
@@ -1095,9 +1145,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;
 
@@ -1193,7 +1241,7 @@ elf_xtensa_check_relocs (bfd *abfd,
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: `%s' accessed both as normal and thread local symbol"),
+               (_("%pB: `%s' accessed both as normal and thread local symbol"),
                 abfd,
                 h ? h->root.root.string : "<local>");
              return FALSE;
@@ -1215,19 +1263,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
     {
@@ -1240,8 +1288,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.  */
@@ -1286,137 +1334,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
@@ -1444,21 +1361,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;
@@ -1490,14 +1407,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;
     }
 
@@ -1518,12 +1435,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;
     }
 
@@ -1561,6 +1478,10 @@ 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->elf.srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela));
 
@@ -1746,7 +1667,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"))
        {
@@ -1968,6 +1889,12 @@ elf_xtensa_do_reloc (reloc_howto_type *howto,
     case R_XTENSA_DIFF8:
     case R_XTENSA_DIFF16:
     case R_XTENSA_DIFF32:
+    case R_XTENSA_PDIFF8:
+    case R_XTENSA_PDIFF16:
+    case R_XTENSA_PDIFF32:
+    case R_XTENSA_NDIFF8:
+    case R_XTENSA_NDIFF16:
+    case R_XTENSA_NDIFF32:
     case R_XTENSA_TLS_FUNC:
     case R_XTENSA_TLS_ARG:
     case R_XTENSA_TLS_CALL:
@@ -1994,7 +1921,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);
@@ -2077,8 +2004,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
@@ -2222,7 +2150,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;
@@ -2535,7 +2464,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;
 }
@@ -2578,7 +2507,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)
@@ -2787,8 +2720,10 @@ elf_xtensa_relocate_section (bfd *output_bfd,
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+%#Lx): relocation offset out of range (size=%#Lx)"),
-            input_bfd, input_section, rel->r_offset, input_size);
+           (_("%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;
        }
@@ -2800,7 +2735,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
@@ -2813,12 +2748,12 @@ elf_xtensa_relocate_section (bfd *output_bfd,
          _bfd_error_handler
            ((sym_type == STT_TLS
              /* xgettext:c-format */
-             ? _("%B(%A+%#Lx): %s used with TLS symbol %s")
+             ? _("%pB(%pA+%#" PRIx64 "): %s used with TLS symbol %s")
              /* xgettext:c-format */
-             : _("%B(%A+%#Lx): %s used with non-TLS symbol %s")),
+             : _("%pB(%pA+%#" PRIx64 "): %s used with non-TLS symbol %s")),
             input_bfd,
             input_section,
-            rel->r_offset,
+            (uint64_t) rel->r_offset,
             howto->name,
             name);
        }
@@ -2899,12 +2834,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
@@ -3071,10 +3010,11 @@ elf_xtensa_relocate_section (bfd *output_bfd,
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
+           (_("%pB(%pA+%#" PRIx64 "): "
+              "unresolvable %s relocation against symbol `%s'"),
             input_bfd,
             input_section,
-            rel->r_offset,
+            (uint64_t) rel->r_offset,
             howto->name,
             name);
          return FALSE;
@@ -3108,9 +3048,7 @@ elf_xtensa_relocate_section (bfd *output_bfd,
        }
     }
 
-  if (lit_table)
-    free (lit_table);
-
+  free (lit_table);
   input_section->reloc_done = TRUE;
 
   return TRUE;
@@ -3190,8 +3128,7 @@ elf_xtensa_combine_prop_entries (bfd *output_bfd,
 
   if (!bfd_malloc_and_get_section (output_bfd, sxtlit, &contents))
     {
-      if (contents != 0)
-       free (contents);
+      free (contents);
       free (table);
       return -1;
     }
@@ -3269,7 +3206,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;
 
@@ -3299,15 +3236,15 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
     }
 
   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->elf.srelgot;
       spltlittbl = htab->spltlittbl;
       BFD_ASSERT (srelgot != NULL && spltlittbl != NULL);
 
@@ -3373,14 +3310,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
@@ -3395,6 +3324,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");
@@ -3482,7 +3419,7 @@ elf_xtensa_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
     {
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: incompatible machine type. Output is 0x%x. Input is 0x%x"),
+       (_("%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;
@@ -3572,12 +3509,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))
     {
@@ -3585,11 +3521,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);
 }
 
 
@@ -3967,6 +3904,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)
 {
@@ -4167,6 +4131,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.  */
@@ -4246,6 +4232,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);
 }
 
@@ -4713,7 +4713,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;
     }
 
@@ -4721,7 +4721,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;
     }
 
@@ -5367,23 +5367,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"
@@ -5396,12 +5396,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
 };
@@ -6080,7 +6080,7 @@ elf_xtensa_new_section_hook (bfd *abfd, asection *sec)
   if (!sec->used_by_bfd)
     {
       struct elf_xtensa_section_data *sdata;
-      bfd_size_type amt = sizeof (*sdata);
+      size_t amt = sizeof (*sdata);
 
       sdata = bfd_zalloc (abfd, amt);
       if (sdata == NULL)
@@ -6292,8 +6292,7 @@ free_section_cache (section_cache_t *sec_cache)
     {
       release_contents (sec_cache->sec, sec_cache->contents);
       release_internal_relocs (sec_cache->sec, sec_cache->relocs);
-      if (sec_cache->ptbl)
-       free (sec_cache->ptbl);
+      free (sec_cache->ptbl);
     }
 }
 
@@ -6350,8 +6349,7 @@ section_cache_section (section_cache_t *sec_cache,
  err:
   release_contents (sec, contents);
   release_internal_relocs (sec, internal_relocs);
-  if (prop_table)
-    free (prop_table);
+  free (prop_table);
   return FALSE;
 }
 
@@ -6470,8 +6468,7 @@ init_ebb_constraint (ebb_constraint *c)
 static void
 free_ebb_constraint (ebb_constraint *c)
 {
-  if (c->actions)
-    free (c->actions);
+  free (c->actions);
 }
 
 
@@ -6549,9 +6546,10 @@ extend_ebb_bounds_forward (ebb_t *ebb)
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+%#Lx): could not decode instruction; "
+           (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; "
               "possible configuration mismatch"),
-            ebb->sec->owner, ebb->sec, ebb->end_offset + insn_block_len);
+            ebb->sec->owner, ebb->sec,
+            (uint64_t) (ebb->end_offset + insn_block_len));
          return FALSE;
        }
       ebb->end_offset += insn_block_len;
@@ -6627,9 +6625,10 @@ extend_ebb_bounds_backward (ebb_t *ebb)
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+%#Lx): could not decode instruction; "
+           (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; "
               "possible configuration mismatch"),
-            ebb->sec->owner, ebb->sec, ebb->end_offset + insn_block_len);
+            ebb->sec->owner, ebb->sec,
+            (uint64_t) (ebb->end_offset + insn_block_len));
          return FALSE;
        }
       ebb->start_offset -= insn_block_len;
@@ -6703,8 +6702,7 @@ ebb_propose_action (ebb_constraint *c,
 
       for (i = 0; i < c->action_count; i++)
        new_actions[i] = c->actions[i];
-      if (c->actions)
-       free (c->actions);
+      free (c->actions);
       c->actions = new_actions;
       c->action_allocated = new_allocated;
     }
@@ -6756,8 +6754,7 @@ pin_internal_relocs (asection *sec, Elf_Internal_Rela *internal_relocs)
 static void
 release_internal_relocs (asection *sec, Elf_Internal_Rela *internal_relocs)
 {
-  if (internal_relocs
-      && elf_section_data (sec)->relocs != internal_relocs)
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
 }
 
@@ -6775,8 +6772,7 @@ retrieve_contents (bfd *abfd, asection *sec, bfd_boolean keep_memory)
     {
       if (!bfd_malloc_and_get_section (abfd, sec, &contents))
        {
-         if (contents)
-           free (contents);
+         free (contents);
          return NULL;
        }
       if (keep_memory)
@@ -6796,7 +6792,7 @@ pin_contents (asection *sec, bfd_byte *contents)
 static void
 release_contents (asection *sec, bfd_byte *contents)
 {
-  if (contents && elf_section_data (sec)->this_hdr.contents != contents)
+  if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
 }
 
@@ -6849,7 +6845,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
@@ -7099,7 +7094,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)))
@@ -7302,6 +7297,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;
@@ -7390,6 +7390,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);
 
@@ -7546,7 +7596,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,
@@ -7742,10 +7792,10 @@ compute_text_actions (bfd *abfd,
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+%#Lx): could not decode instruction for "
+           (_("%pB(%pA+%#" PRIx64 "): could not decode instruction for "
               "XTENSA_ASM_SIMPLIFY relocation; "
               "possible configuration mismatch"),
-            sec->owner, sec, r_offset);
+            sec->owner, sec, (uint64_t) r_offset);
          continue;
        }
 
@@ -7824,13 +7874,11 @@ compute_text_actions (bfd *abfd,
     print_action_list (stderr, &relax_info->action_list);
 #endif
 
-error_return:
+ error_return:
   release_contents (sec, contents);
   release_internal_relocs (sec, internal_relocs);
-  if (prop_table)
-    free (prop_table);
-  if (reloc_opcodes)
-    free (reloc_opcodes);
+  free (prop_table);
+  free (reloc_opcodes);
 
   return ok;
 }
@@ -8003,9 +8051,9 @@ compute_ebb_proposed_actions (ebb_constraint *ebb_table)
  decode_error:
   _bfd_error_handler
     /* xgettext:c-format */
-    (_("%B(%A+%#Lx): could not decode instruction; "
+    (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; "
        "possible configuration mismatch"),
-     ebb->sec->owner, ebb->sec, offset);
+     ebb->sec->owner, ebb->sec, (uint64_t) offset);
   return FALSE;
 }
 
@@ -8255,7 +8303,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);
 
@@ -8274,8 +8322,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;
 };
 
@@ -8306,6 +8354,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);
@@ -8313,10 +8362,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;
@@ -8420,10 +8478,11 @@ build_xlate_map (asection *sec, xtensa_relax_info *relax_info)
 static void
 free_xlate_map (xlate_map_t *map)
 {
-  if (map && map->entry)
-    free (map->entry);
   if (map)
-    free (map);
+    {
+      free (map->entry);
+      free (map);
+    }
 }
 
 
@@ -8607,8 +8666,7 @@ check_section_ebb_pcrels_fit (bfd *abfd,
        }
     }
 
-  if (xmap)
-    free_xlate_map (xmap);
+  free_xlate_map (xmap);
 
   return ok;
 }
@@ -8669,7 +8727,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;
 
@@ -8819,9 +8877,8 @@ compute_removed_literals (bfd *abfd,
   print_action_list (stderr, &relax_info->action_list);
 #endif /* DEBUG */
 
-error_return:
-  if (prop_table)
-    free (prop_table);
+ error_return:
+  free (prop_table);
   free_section_cache (&target_sec_cache);
 
   release_contents (sec, contents);
@@ -8950,7 +9007,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,
@@ -9126,7 +9183,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;
@@ -9496,7 +9553,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.  */
@@ -9579,7 +9636,13 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
 
              if (r_type == R_XTENSA_DIFF8
                  || r_type == R_XTENSA_DIFF16
-                 || r_type == R_XTENSA_DIFF32)
+                 || r_type == R_XTENSA_DIFF32
+                 || r_type == R_XTENSA_PDIFF8
+                 || r_type == R_XTENSA_PDIFF16
+                 || r_type == R_XTENSA_PDIFF32
+                 || r_type == R_XTENSA_NDIFF8
+                 || r_type == R_XTENSA_NDIFF16
+                 || r_type == R_XTENSA_NDIFF32)
                {
                  bfd_signed_vma diff_value = 0;
                  bfd_vma new_end_offset, diff_mask = 0;
@@ -9595,19 +9658,45 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
                  switch (r_type)
                    {
                    case R_XTENSA_DIFF8:
+                     diff_mask = 0x7f;
                      diff_value =
                        bfd_get_signed_8 (abfd, &contents[old_source_offset]);
                      break;
                    case R_XTENSA_DIFF16:
+                     diff_mask = 0x7fff;
                      diff_value =
                        bfd_get_signed_16 (abfd, &contents[old_source_offset]);
                      break;
                    case R_XTENSA_DIFF32:
+                     diff_mask = 0x7fffffff;
                      diff_value =
                        bfd_get_signed_32 (abfd, &contents[old_source_offset]);
                      break;
+                   case R_XTENSA_PDIFF8:
+                   case R_XTENSA_NDIFF8:
+                     diff_mask = 0xff;
+                     diff_value =
+                       bfd_get_8 (abfd, &contents[old_source_offset]);
+                     break;
+                   case R_XTENSA_PDIFF16:
+                   case R_XTENSA_NDIFF16:
+                     diff_mask = 0xffff;
+                     diff_value =
+                       bfd_get_16 (abfd, &contents[old_source_offset]);
+                     break;
+                   case R_XTENSA_PDIFF32:
+                   case R_XTENSA_NDIFF32:
+                     diff_mask = 0xffffffff;
+                     diff_value =
+                       bfd_get_32 (abfd, &contents[old_source_offset]);
+                     break;
                    }
 
+                 if (r_type >= R_XTENSA_NDIFF8
+                     && r_type <= R_XTENSA_NDIFF32
+                     && diff_value)
+                   diff_value |= ~diff_mask;
+
                  new_end_offset = offset_with_removed_text_map
                    (&target_relax_info->action_list,
                     r_rel.target_offset + diff_value);
@@ -9616,25 +9705,40 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
                  switch (r_type)
                    {
                    case R_XTENSA_DIFF8:
-                     diff_mask = 0x7f;
                      bfd_put_signed_8 (abfd, diff_value,
                                 &contents[old_source_offset]);
                      break;
                    case R_XTENSA_DIFF16:
-                     diff_mask = 0x7fff;
                      bfd_put_signed_16 (abfd, diff_value,
                                  &contents[old_source_offset]);
                      break;
                    case R_XTENSA_DIFF32:
-                     diff_mask = 0x7fffffff;
                      bfd_put_signed_32 (abfd, diff_value,
                                  &contents[old_source_offset]);
                      break;
+                   case R_XTENSA_PDIFF8:
+                   case R_XTENSA_NDIFF8:
+                     bfd_put_8 (abfd, diff_value,
+                                &contents[old_source_offset]);
+                     break;
+                   case R_XTENSA_PDIFF16:
+                   case R_XTENSA_NDIFF16:
+                     bfd_put_16 (abfd, diff_value,
+                                 &contents[old_source_offset]);
+                     break;
+                   case R_XTENSA_PDIFF32:
+                   case R_XTENSA_NDIFF32:
+                     bfd_put_32 (abfd, diff_value,
+                                 &contents[old_source_offset]);
+                     break;
                    }
 
-                 /* Check for overflow. Sign bits must be all zeroes or all ones */
-                 if ((diff_value & ~diff_mask) != 0 &&
-                     (diff_value & ~diff_mask) != (-1 & ~diff_mask))
+                 /* Check for overflow. Sign bits must be all zeroes or
+                    all ones.  When sign bits are all ones diff_value
+                    may not be zero.  */
+                 if (((diff_value & ~diff_mask) != 0
+                      && (diff_value & ~diff_mask) != ~diff_mask)
+                     || (diff_value && (bfd_vma) diff_value == ~diff_mask))
                    {
                      (*link_info->callbacks->reloc_dangerous)
                        (link_info, _("overflow after relaxation"),
@@ -10123,7 +10227,9 @@ 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))))
     {
       asection *srel;
       bfd_boolean is_plt = FALSE;
@@ -10480,7 +10586,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);
 
@@ -10781,8 +10887,8 @@ do_fix_for_relocatable_link (Elf_Internal_Rela *rel,
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+%#Lx): unexpected fix for %s relocation"),
-            input_bfd, input_section, rel->r_offset,
+           (_("%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;
        }
@@ -10903,8 +11009,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)
        {
@@ -10968,10 +11074,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;
@@ -11101,10 +11207,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;
@@ -11115,11 +11241,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)
     {
@@ -11141,25 +11263,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));
@@ -11167,6 +11294,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)
@@ -11175,7 +11317,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));
@@ -11183,7 +11326,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
@@ -11320,9 +11463,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 }
 };
 \f
 #define ELF_TARGET_ID                  XTENSA_ELF_DATA
@@ -11370,7 +11513,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
@@ -11379,8 +11521,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
This page took 0.045235 seconds and 4 git commands to generate.