gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / elf32-xtensa.c
index 25236707dae46e7190c646de1601fb1f6ff088fc..05c4f8430a2046a9c48546c815f0eb2ebdb2f728 100644 (file)
@@ -1,5 +1,5 @@
 /* Xtensa-specific support for 32-bit ELF.
-   Copyright (C) 2003-2015 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.  */
@@ -316,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
@@ -355,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 ];
@@ -451,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;
 }
@@ -473,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 +532,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;
 }
 
 \f
@@ -519,24 +573,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] =
 {
-  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 */
+    {
+      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] =
 {
-  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 */
+    {
+      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.  */
@@ -596,11 +668,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;
 
@@ -657,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)
@@ -778,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,
@@ -899,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
@@ -909,8 +976,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;
@@ -971,7 +1039,7 @@ elf_xtensa_check_relocs (bfd *abfd,
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
 
-  if (info->relocatable || (sec->flags & SEC_ALLOC) == 0)
+  if (bfd_link_relocatable (info) || (sec->flags & SEC_ALLOC) == 0)
     return TRUE;
 
   BFD_ASSERT (is_xtensa_elf (abfd));
@@ -987,7 +1055,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;
@@ -1000,8 +1068,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;
        }
 
@@ -1011,17 +1080,13 @@ 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);
 
       switch (r_type)
        {
        case R_XTENSA_TLSDESC_FN:
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
              tls_type = GOT_TLS_GD;
              is_got = TRUE;
@@ -1032,7 +1097,7 @@ elf_xtensa_check_relocs (bfd *abfd,
          break;
 
        case R_XTENSA_TLSDESC_ARG:
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
              tls_type = GOT_TLS_GD;
              is_got = TRUE;
@@ -1046,7 +1111,7 @@ elf_xtensa_check_relocs (bfd *abfd,
          break;
 
        case R_XTENSA_TLS_DTPOFF:
-         if (info->shared)
+         if (bfd_link_pic (info))
            tls_type = GOT_TLS_GD;
          else
            tls_type = GOT_TLS_IE;
@@ -1054,9 +1119,9 @@ elf_xtensa_check_relocs (bfd *abfd,
 
        case R_XTENSA_TLS_TPOFF:
          tls_type = GOT_TLS_IE;
-         if (info->shared)
+         if (bfd_link_pic (info))
            info->flags |= DF_STATIC_TLS;
-         if (info->shared || h)
+         if (bfd_link_pic (info) || h)
            is_got = TRUE;
          break;
 
@@ -1080,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;
 
@@ -1176,8 +1239,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 : "<local>");
              return FALSE;
@@ -1199,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 (info->shared)
+  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
     {
@@ -1224,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.  */
@@ -1270,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 (info->relocatable)
-    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 (info->shared)
-           {
-             is_got = TRUE;
-             is_tlsfunc = TRUE;
-           }
-         break;
-
-       case R_XTENSA_TLSDESC_ARG:
-         if (info->shared)
-           is_got = TRUE;
-         else
-           {
-             if (h && elf_xtensa_hash_entry (h) != htab->tlsbase)
-               is_got = TRUE;
-           }
-         break;
-
-       case R_XTENSA_TLS_TPOFF:
-         if (info->shared || 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
@@ -1416,11 +1349,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.  */
@@ -1432,22 +1360,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;
@@ -1479,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;
     }
 
@@ -1507,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;
     }
 
@@ -1550,11 +1478,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;
 }
@@ -1596,8 +1528,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));
        }
     }
 }
@@ -1625,19 +1557,19 @@ 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);
 
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
@@ -1647,7 +1579,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
@@ -1659,7 +1591,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       /* If we are generating a shared object, we also need space in
         ".rela.got" for R_XTENSA_RELATIVE relocs for literals that
         reference local symbols.  */
-      if (info->shared)
+      if (bfd_link_pic (info))
        elf_xtensa_allocate_local_got_size (info);
 
       /* Allocate space in ".plt" to match the size of ".rela.plt".  For
@@ -1735,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"))
        {
@@ -1815,7 +1747,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 #define add_dynamic_entry(TAG, VAL) \
   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
-      if (info->executable)
+      if (bfd_link_executable (info))
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
@@ -1957,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:
@@ -1983,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);
@@ -2066,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
@@ -2211,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;
@@ -2317,7 +2257,7 @@ elf_xtensa_create_plt_entry (struct bfd_link_info *info,
 {
   asection *splt, *sgotplt;
   bfd_vma plt_base, got_base;
-  bfd_vma code_offset, lit_offset;
+  bfd_vma code_offset, lit_offset, abi_offset;
   int chunk;
 
   chunk = reloc_index / PLT_ENTRIES_PER_CHUNK;
@@ -2339,18 +2279,19 @@ 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,
-                                      plt_base + code_offset + 3),
-             splt->contents + code_offset + 4);
+                                      plt_base + code_offset + abi_offset),
+             splt->contents + code_offset + abi_offset + 1);
   bfd_put_16 (output_bfd, l32r_offset (got_base + 4,
-                                      plt_base + code_offset + 6),
-             splt->contents + code_offset + 7);
+                                      plt_base + code_offset + abi_offset + 3),
+             splt->contents + code_offset + abi_offset + 4);
   bfd_put_16 (output_bfd, l32r_offset (got_base + lit_offset,
-                                      plt_base + code_offset + 9),
-             splt->contents + code_offset + 10);
+                                      plt_base + code_offset + abi_offset + 6),
+             splt->contents + code_offset + abi_offset + 7);
 
   return plt_base + code_offset;
 }
@@ -2523,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;
 }
@@ -2566,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)
@@ -2627,7 +2572,7 @@ elf_xtensa_relocate_section (bfd *output_bfd,
       unresolved_reloc = FALSE;
       warned = FALSE;
 
-      if (howto->partial_inplace && !info->relocatable)
+      if (howto->partial_inplace && !bfd_link_relocatable (info))
        {
          /* Because R_XTENSA_32 was made partial_inplace to fix some
             problems with DWARF info in partial links, there may be
@@ -2665,7 +2610,7 @@ elf_xtensa_relocate_section (bfd *output_bfd,
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
                                         rel, 1, relend, howto, 0, contents);
 
-      if (info->relocatable)
+      if (bfd_link_relocatable (info))
        {
          bfd_vma dest_addr;
          asection * sym_sec = get_elf_r_symndx_section (input_bfd, r_symndx);
@@ -2697,12 +2642,10 @@ elf_xtensa_relocate_section (bfd *output_bfd,
              r = contract_asm_expansion (contents, input_size, rel,
                                          &error_message);
              if (r != bfd_reloc_ok)
-               {
-                 if (!((*info->callbacks->reloc_dangerous)
-                       (info, error_message, input_bfd, input_section,
-                        rel->r_offset)))
-                   return FALSE;
-               }
+               (*info->callbacks->reloc_dangerous)
+                 (info, error_message,
+                  input_bfd, input_section, rel->r_offset);
+
              r_type = ELF32_R_TYPE (rel->r_info);
            }
 
@@ -2754,12 +2697,9 @@ elf_xtensa_relocate_section (bfd *output_bfd,
                }
            }
          if (r != bfd_reloc_ok)
-           {
-             if (!((*info->callbacks->reloc_dangerous)
-                   (info, error_message, input_bfd, input_section,
-                    rel->r_offset)))
-               return FALSE;
-           }
+           (*info->callbacks->reloc_dangerous)
+             (info, error_message,
+              input_bfd, input_section, rel->r_offset);
 
          /* Done with work for relocatable link; continue with next reloc.  */
          continue;
@@ -2778,9 +2718,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 +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
@@ -2802,13 +2745,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);
        }
@@ -2827,16 +2772,16 @@ elf_xtensa_relocate_section (bfd *output_bfd,
        case R_XTENSA_PLT:
          if (elf_hash_table (info)->dynamic_sections_created
              && (input_section->flags & SEC_ALLOC) != 0
-             && (dynamic_symbol || info->shared))
+             && (dynamic_symbol || bfd_link_pic (info)))
            {
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
              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);
 
@@ -2859,10 +2804,9 @@ elf_xtensa_relocate_section (bfd *output_bfd,
                    {
                      error_message =
                        _("dynamic relocation in read-only section");
-                     if (!((*info->callbacks->reloc_dangerous)
-                           (info, error_message, input_bfd, input_section,
-                            rel->r_offset)))
-                       return FALSE;
+                     (*info->callbacks->reloc_dangerous)
+                       (info, error_message,
+                        input_bfd, input_section, rel->r_offset);
                    }
 
                  if (dynamic_symbol)
@@ -2890,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
@@ -2915,7 +2863,7 @@ elf_xtensa_relocate_section (bfd *output_bfd,
 
        case R_XTENSA_TLS_TPOFF:
          /* Switch to LE model for local symbols in an executable.  */
-         if (! info->shared && ! dynamic_symbol)
+         if (! bfd_link_pic (info) && ! dynamic_symbol)
            {
              relocation = tpoff (info, relocation);
              break;
@@ -2927,12 +2875,12 @@ elf_xtensa_relocate_section (bfd *output_bfd,
          {
            if (r_type == R_XTENSA_TLSDESC_FN)
              {
-               if (! info->shared || (tls_type & GOT_TLS_IE) != 0)
+               if (! bfd_link_pic (info) || (tls_type & GOT_TLS_IE) != 0)
                  r_type = R_XTENSA_NONE;
              }
            else if (r_type == R_XTENSA_TLSDESC_ARG)
              {
-               if (info->shared)
+               if (bfd_link_pic (info))
                  {
                    if ((tls_type & GOT_TLS_IE) != 0)
                      r_type = R_XTENSA_TLS_TPOFF;
@@ -2956,16 +2904,15 @@ elf_xtensa_relocate_section (bfd *output_bfd,
              {
                error_message =
                  _("TLS relocation invalid without dynamic sections");
-               if (!((*info->callbacks->reloc_dangerous)
-                     (info, error_message, input_bfd, input_section,
-                      rel->r_offset)))
-                 return FALSE;
+               (*info->callbacks->reloc_dangerous)
+                 (info, error_message,
+                  input_bfd, input_section, rel->r_offset);
              }
            else
              {
                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
@@ -2980,10 +2927,9 @@ elf_xtensa_relocate_section (bfd *output_bfd,
                  {
                    error_message =
                      _("dynamic relocation in read-only section");
-                   if (!((*info->callbacks->reloc_dangerous)
-                         (info, error_message, input_bfd, input_section,
-                          rel->r_offset)))
-                     return FALSE;
+                   (*info->callbacks->reloc_dangerous)
+                     (info, error_message,
+                      input_bfd, input_section, rel->r_offset);
                  }
 
                indx = h && h->dynindx != -1 ? h->dynindx : 0;
@@ -3008,7 +2954,7 @@ elf_xtensa_relocate_section (bfd *output_bfd,
          break;
 
        case R_XTENSA_TLS_DTPOFF:
-         if (! info->shared)
+         if (! bfd_link_pic (info))
            /* Switch from LD model to LE model.  */
            relocation = tpoff (info, relocation);
          else
@@ -3025,12 +2971,9 @@ elf_xtensa_relocate_section (bfd *output_bfd,
                (h && elf_xtensa_hash_entry (h) == htab->tlsbase);
              if (! replace_tls_insn (rel, input_bfd, input_section, contents,
                                      is_ld_model, &error_message))
-               {
-                 if (!((*info->callbacks->reloc_dangerous)
-                       (info, error_message, input_bfd, input_section,
-                        rel->r_offset)))
-                   return FALSE;
-               }
+               (*info->callbacks->reloc_dangerous)
+                 (info, error_message,
+                  input_bfd, input_section, rel->r_offset);
 
              if (r_type != R_XTENSA_TLS_ARG || is_ld_model)
                {
@@ -3049,10 +2992,8 @@ elf_xtensa_relocate_section (bfd *output_bfd,
              error_message =
                vsprint_msg ("invalid relocation for dynamic symbol", ": %s",
                             strlen (name) + 2, name);
-             if (!((*info->callbacks->reloc_dangerous)
-                   (info, error_message, input_bfd, input_section,
-                    rel->r_offset)))
-               return FALSE;
+             (*info->callbacks->reloc_dangerous)
+               (info, error_message, input_bfd, input_section, rel->r_offset);
              continue;
            }
          break;
@@ -3067,11 +3008,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;
@@ -3100,16 +3043,12 @@ elf_xtensa_relocate_section (bfd *output_bfd,
                                         strlen (name) + 22,
                                         name, (int) rel->r_addend);
 
-         if (!((*info->callbacks->reloc_dangerous)
-               (info, error_message, input_bfd, input_section,
-                rel->r_offset)))
-           return FALSE;
+         (*info->callbacks->reloc_dangerous)
+           (info, error_message, input_bfd, input_section, rel->r_offset);
        }
     }
 
-  if (lit_table)
-    free (lit_table);
-
+  free (lit_table);
   input_section->reloc_done = TRUE;
 
   return TRUE;
@@ -3173,7 +3112,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;
     }
@@ -3189,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;
     }
@@ -3268,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;
 
@@ -3285,7 +3223,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);
@@ -3297,16 +3235,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);
 
@@ -3372,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
@@ -3394,8 +3324,16 @@ 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 (! info->relocatable);
+  BFD_ASSERT (! bfd_link_relocatable (info));
   sxtlit = bfd_get_section_by_name (output_bfd, ".xt.lit");
   sgotloc = htab->sgotloc;
   BFD_ASSERT (sgotloc);
@@ -3425,30 +3363,22 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
          break;
 
        case DT_XTENSA_GOT_LOC_OFF:
-         dyn.d_un.d_ptr = htab->sgotloc->output_section->vma;
+         dyn.d_un.d_ptr = (htab->sgotloc->output_section->vma
+                           + htab->sgotloc->output_offset);
          break;
 
        case DT_PLTGOT:
-         dyn.d_un.d_ptr = htab->sgot->output_section->vma;
+         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;
+         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->output_section->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->output_section->size;
+         dyn.d_un.d_val = htab->elf.srelplt->size;
          break;
        }
 
@@ -3465,13 +3395,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.  */
@@ -3486,8 +3417,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;
@@ -3577,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))
     {
@@ -3590,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);
 }
 
 
@@ -3972,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)
 {
@@ -4172,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.  */
@@ -4251,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);
 }
 
@@ -4718,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;
     }
 
@@ -4726,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;
     }
 
@@ -5372,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"
@@ -5401,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
 };
@@ -6085,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)
@@ -6297,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);
     }
 }
 
@@ -6355,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;
 }
 
@@ -6475,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);
 }
 
 
@@ -6552,9 +6544,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;
@@ -6628,9 +6623,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;
@@ -6704,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;
     }
@@ -6757,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);
 }
 
@@ -6776,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)
@@ -6797,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);
 }
 
@@ -6850,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
@@ -7100,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)))
@@ -7303,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;
@@ -7348,7 +7347,7 @@ is_resolvable_asm_expansion (bfd *abfd,
   /* For relocatable sections, we can only simplify when the output
      section of the target is the same as the output section of the
      source.  */
-  if (link_info->relocatable
+  if (bfd_link_relocatable (link_info)
       && (target_sec->output_section != sec->output_section
          || is_reloc_sym_weak (abfd, irel)))
     return FALSE;
@@ -7391,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);
 
@@ -7547,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,
@@ -7741,9 +7790,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;
        }
 
@@ -7822,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;
 }
@@ -7999,9 +8049,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;
 }
 
@@ -8251,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);
 
@@ -8270,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;
 };
 
@@ -8302,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);
@@ -8309,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;
@@ -8416,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);
+    }
 }
 
 
@@ -8603,8 +8666,7 @@ check_section_ebb_pcrels_fit (bfd *abfd,
        }
     }
 
-  if (xmap)
-    free_xlate_map (xmap);
+  free_xlate_map (xmap);
 
   return ok;
 }
@@ -8665,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;
 
@@ -8815,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);
@@ -8946,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,
@@ -9004,7 +9065,7 @@ identify_literal_placement (bfd *abfd,
   sec_size = bfd_get_section_limit (abfd, sec);
 
   final_static_link =
-    (!link_info->relocatable
+    (!bfd_link_relocatable (link_info)
      && !elf_hash_table (link_info)->dynamic_sections_created);
 
   /* The placement algorithm first checks to see if the literal is
@@ -9043,7 +9104,7 @@ identify_literal_placement (bfd *abfd,
   /* For relocatable links, do not try to move literals.  To do it
      correctly might increase the number of relocations in an input
      section making the default relocatable linking fail.  */
-  if (!link_info->relocatable && !literal_placed
+  if (!bfd_link_relocatable (link_info) && !literal_placed
       && values->has_last_loc && !(*last_loc_is_prev_p))
     {
       asection *target_sec = r_reloc_get_section (&values->last_loc);
@@ -9122,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;
@@ -9492,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.  */
@@ -9575,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;
@@ -9591,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);
@@ -9612,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"),
@@ -10119,18 +10227,20 @@ 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 || info->shared))
+      && (dynamic_symbol
+         || (bfd_link_pic (info)
+             && (!h || h->root.type != bfd_link_hash_undefweak))))
     {
       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);
@@ -10159,7 +10269,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);
@@ -10225,7 +10335,7 @@ move_literal (bfd *abfd,
       bfd_put_32 (abfd, lit->value, contents + offset);
 
       /* Currently, we cannot move relocations during a relocatable link.  */
-      BFD_ASSERT (!link_info->relocatable);
+      BFD_ASSERT (!bfd_link_relocatable (link_info));
       fix = reloc_bfd_fix_init (sec, offset, r_type,
                                r_reloc_get_section (r_rel),
                                r_rel->target_offset + r_rel->virtual_offset,
@@ -10464,7 +10574,7 @@ relax_property_section (bfd *abfd,
      finish_dynamic_sections() but at that point it's too late to
      reclaim the space in the output section, so we do this twice.  */
 
-  if (internal_relocs && (!link_info->relocatable
+  if (internal_relocs && (!bfd_link_relocatable (link_info)
                          || xtensa_is_littable_section (sec)))
     {
       Elf_Internal_Rela *last_irel = NULL;
@@ -10476,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);
 
@@ -10775,9 +10885,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;
        }
@@ -10835,18 +10946,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);
@@ -10857,17 +10961,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);
@@ -10911,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)
        {
@@ -10976,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;
@@ -11109,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;
@@ -11123,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)
     {
@@ -11149,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));
@@ -11175,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)
@@ -11183,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));
@@ -11191,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
@@ -11250,7 +11385,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];
@@ -11328,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
@@ -11344,11 +11479,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
@@ -11357,6 +11488,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
 
@@ -11381,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
@@ -11390,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.071992 seconds and 4 git commands to generate.