Fix powerpc comment typo
[deliverable/binutils-gdb.git] / bfd / elf32-ppc.c
index 30998b1ade11b9576b254c103677746e267d56e3..eb8ba62557bcdf85c783311f894d30eeb7a9f4cb 100644 (file)
@@ -134,7 +134,7 @@ static const bfd_vma ppc_elf_vxworks_pic_plt0_entry
 #define VXWORKS_PLT_NON_JMP_SLOT_RELOCS 3
 /* The number of relocations in the PLTResolve slot. */
 #define VXWORKS_PLTRESOLVE_RELOCS 2
-/* The number of relocations in the PLTResolve slot when when creating
+/* The number of relocations in the PLTResolve slot when creating
    a shared library. */
 #define VXWORKS_PLTRESOLVE_RELOCS_SHLIB 0
 
@@ -1471,7 +1471,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_LO16D",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x3e007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 split16a format.  */
@@ -1501,7 +1501,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_HI16D",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x3e007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (High Adjusted) in split16a format.  */
@@ -1531,7 +1531,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_HA16D",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x3e007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i
@@ -1593,7 +1593,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_SDAREL_LO16D", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x3e007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16a format.  */
@@ -1623,7 +1623,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_SDAREL_HI16D", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x3e007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16a format.  */
@@ -1653,7 +1653,22 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_SDAREL_HA16D", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x3e007ff,             /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* e_li split20 format.  */
+  HOWTO (R_PPC_VLE_ADDR20,     /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        20,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_PPC_VLE_ADDR20",    /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x1f07ff,              /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   HOWTO (R_PPC_IRELATIVE,      /* type */
@@ -1746,6 +1761,21 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         0x1fffc1,              /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
+  /* A split-field reloc for addpcis, non-relative (gas internal use only).  */
+  HOWTO (R_PPC_16DX_HA,                /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        ppc_elf_addr16_ha_reloc, /* special_function */
+        "R_PPC_16DX_HA",       /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x1fffc1,              /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
   /* GNU extension to record C++ vtable hierarchy.  */
   HOWTO (R_PPC_GNU_VTINHERIT,  /* type */
         0,                     /* rightshift */
@@ -2002,6 +2032,7 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     case BFD_RELOC_LO16_PCREL:         r = R_PPC_REL16_LO;             break;
     case BFD_RELOC_HI16_PCREL:         r = R_PPC_REL16_HI;             break;
     case BFD_RELOC_HI16_S_PCREL:       r = R_PPC_REL16_HA;             break;
+    case BFD_RELOC_PPC_16DX_HA:                r = R_PPC_16DX_HA;              break;
     case BFD_RELOC_PPC_REL16DX_HA:     r = R_PPC_REL16DX_HA;           break;
     case BFD_RELOC_VTABLE_INHERIT:     r = R_PPC_GNU_VTINHERIT;        break;
     case BFD_RELOC_VTABLE_ENTRY:       r = R_PPC_GNU_VTENTRY;          break;
@@ -2029,7 +2060,7 @@ ppc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 /* Set the howto pointer for a PowerPC ELF reloc.  */
 
 static void
-ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+ppc_elf_info_to_howto (bfd *abfd,
                       arelent *cache_ptr,
                       Elf_Internal_Rela *dst)
 {
@@ -2066,10 +2097,10 @@ ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
 /* Handle the R_PPC_ADDR16_HA and R_PPC_REL16_HA relocs.  */
 
 static bfd_reloc_status_type
-ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ppc_elf_addr16_ha_reloc (bfd *abfd,
                         arelent *reloc_entry,
                         asymbol *symbol,
-                        void *data ATTRIBUTE_UNUSED,
+                        void *data,
                         asection *input_section,
                         bfd *output_bfd,
                         char **error_message ATTRIBUTE_UNUSED)
@@ -2593,7 +2624,7 @@ ppc_elf_modify_segment_map (bfd *abfd,
       amt += (m->count - j - 1) * sizeof (asection *);
       n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
       if (n == NULL)
-        return FALSE;
+       return FALSE;
 
       n->p_type = PT_LOAD;
       n->count = m->count - j;
@@ -2632,7 +2663,7 @@ static struct bfd_elf_special_section ppc_alt_plt =
   { STRING_COMMA_LEN (".plt"),             0, SHT_PROGBITS, SHF_ALLOC };
 
 static const struct bfd_elf_special_section *
-ppc_elf_get_sec_type_attr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+ppc_elf_get_sec_type_attr (bfd *abfd, asection *sec)
 {
   const struct bfd_elf_special_section *ssect;
 
@@ -2833,7 +2864,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info)
     free (buffer);
 
   if (error_message)
-    _bfd_error_handler (error_message, ibfd, APUINFO_SECTION_NAME);
+    _bfd_error_handler (error_message, APUINFO_SECTION_NAME, ibfd);
 }
 
 /* Prevent the output section from accumulating the input sections'
@@ -3176,9 +3207,9 @@ struct plt_entry
   bfd_vma glink_offset;
 };
 
-/* Of those relocs that might be copied as dynamic relocs, this function
-   selects those that must be copied when linking a shared library,
-   even when the symbol is local.  */
+/* Of those relocs that might be copied as dynamic relocs, this
+   function selects those that must be copied when linking a shared
+   library or PIE, even when the symbol is local.  */
 
 static int
 must_be_dyn_reloc (struct bfd_link_info *info,
@@ -3187,6 +3218,10 @@ must_be_dyn_reloc (struct bfd_link_info *info,
   switch (r_type)
     {
     default:
+      /* Only relative relocs can be resolved when the object load
+        address isn't fixed.  DTPREL32 is excluded because the
+        dynamic linker needs to differentiate global dynamic from
+        local dynamic __tls_index pairs when PPC_OPT_TLS is set.  */
       return 1;
 
     case R_PPC_REL24:
@@ -3201,10 +3236,19 @@ must_be_dyn_reloc (struct bfd_link_info *info,
     case R_PPC_TPREL16_LO:
     case R_PPC_TPREL16_HI:
     case R_PPC_TPREL16_HA:
-      return !bfd_link_executable (info);
+      /* These relocations are relative but in a shared library the
+        linker doesn't know the thread pointer base.  */
+      return bfd_link_dll (info);
     }
 }
 
+/* Whether an undefined weak symbol should resolve to its link-time
+   value, even in PIC or PIE objects.  */
+#define UNDEFWEAK_NO_DYNAMIC_RELOC(INFO, H)            \
+  ((H)->root.type == bfd_link_hash_undefweak           \
+   && (ELF_ST_VISIBILITY ((H)->other) != STV_DEFAULT   \
+       || (INFO)->dynamic_undefined_weak == 0))
+
 /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
    copying dynamic variables from a shared lib into an app's dynbss
    section, and instead use a dynamic relocation to point into the
@@ -3311,6 +3355,14 @@ struct ppc_elf_link_hash_table
   /* True if the target system is VxWorks.  */
   unsigned int is_vxworks:1;
 
+  /* Whether there exist local gnu indirect function resolvers,
+     referenced by dynamic relocations.  */
+  unsigned int local_ifunc_resolver:1;
+  unsigned int maybe_local_ifunc_resolver:1;
+
+  /* Set if tls optimization is enabled.  */
+  unsigned int do_tls_opt:1;
+
   /* The size of PLT entries.  */
   int plt_entry_size;
   /* The distance between adjacent PLT slots.  */
@@ -4027,7 +4079,7 @@ ppc_elf_check_relocs (bfd *abfd,
 
          /* PR15323, ref flags aren't set for references in the same
             object.  */
-         h->root.non_ir_ref = 1;
+         h->root.non_ir_ref_regular = 1;
        }
 
       /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
@@ -4123,7 +4175,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_GOT_TPREL16_LO:
        case R_PPC_GOT_TPREL16_HI:
        case R_PPC_GOT_TPREL16_HA:
-         if (bfd_link_pic (info))
+         if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          tls_type = TLS_TLS | TLS_TPREL;
          goto dogottls;
@@ -4231,6 +4283,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_VLE_HI16D:
        case R_PPC_VLE_HA16A:
        case R_PPC_VLE_HA16D:
+       case R_PPC_VLE_ADDR20:
          break;
 
        case R_PPC_EMB_SDA2REL:
@@ -4351,6 +4404,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_RELAX:
        case R_PPC_RELAX_PLT:
        case R_PPC_RELAX_PLTREL24:
+       case R_PPC_16DX_HA:
          break;
 
          /* These should only appear in dynamic objects.  */
@@ -4401,13 +4455,13 @@ ppc_elf_check_relocs (bfd *abfd,
            return FALSE;
          break;
 
-         /* We shouldn't really be seeing these.  */
+         /* We shouldn't really be seeing TPREL32.  */
        case R_PPC_TPREL32:
        case R_PPC_TPREL16:
        case R_PPC_TPREL16_LO:
        case R_PPC_TPREL16_HI:
        case R_PPC_TPREL16_HA:
-         if (bfd_link_pic (info))
+         if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          goto dodyn;
 
@@ -4877,9 +4931,9 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
          error = TRUE;
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: uses different e_flags (0x%lx) fields "
-              "than previous modules (0x%lx)"),
-            ibfd, (long) new_flags, (long) old_flags);
+           (_("%B: uses different e_flags (%#x) fields "
+              "than previous modules (%#x)"),
+            ibfd, new_flags, old_flags);
        }
 
       if (error)
@@ -4904,7 +4958,7 @@ ppc_elf_vle_split16 (bfd *input_bfd,
   unsigned int insn, opcode, top5;
 
   insn = bfd_get_32 (input_bfd, loc);
-  opcode = insn & 0xf300f800;
+  opcode = insn & 0xfc00f800;
   if (opcode == E_OR2I_INSN
       || opcode == E_AND2I_DOT_INSN
       || opcode == E_OR2IS_INSN
@@ -4942,12 +4996,29 @@ ppc_elf_vle_split16 (bfd *input_bfd,
        }
     }
   top5 = value & 0xf800;
-  top5 = top5 << (split16_format == split16a_type ? 5 : 9);
-  insn &= (split16_format == split16a_type ? ~0x1f07ff : ~0x1f007ff);
+  top5 = top5 << (split16_format == split16a_type ? 5 : 10);
+  insn &= (split16_format == split16a_type ? ~0x1f07ff : ~0x3e007ff);
   insn |= top5;
   insn |= value & 0x7ff;
   bfd_put_32 (input_bfd, insn, loc);
 }
+
+static void
+ppc_elf_vle_split20 (bfd *output_bfd, bfd_byte *loc, bfd_vma value)
+{
+  unsigned int insn;
+
+  insn = bfd_get_32 (output_bfd, loc);
+  /* We have an li20 field, bits 17..20, 11..15, 21..31.  */
+  /* Top 4 bits of value to 17..20.  */
+  insn |= (value & 0xf0000) >> 5;
+  /* Next 5 bits of the value to 11..15.  */
+  insn |= (value & 0xf800) << 5;
+  /* And the final 11 bits of the value to bits 21 to 31.  */
+  insn |= value & 0x7ff;
+  bfd_put_32 (output_bfd, insn, loc);
+}
+
 \f
 /* Choose which PLT scheme to use, and set .plt flags appropriately.
    Returns -1 on error, 0 for old PLT, 1 for new PLT.  */
@@ -4974,8 +5045,7 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
                   || h->needs_plt)
               && h->ref_regular
               && !(SYMBOL_CALLS_LOCAL (info, h)
-                   || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-                       && h->root.type == bfd_link_hash_undefweak)))
+                   || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
        {
          /* Profiling of shared libs (and pies) is not supported with
             secure plt, because ppc32 does profiling before a
@@ -5275,8 +5345,7 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
              && (tga->type == STT_FUNC
                  || tga->needs_plt)
              && !(SYMBOL_CALLS_LOCAL (info, tga)
-                  || (ELF_ST_VISIBILITY (tga->other) != STV_DEFAULT
-                      && tga->root.type == bfd_link_hash_undefweak)))
+                  || UNDEFWEAK_NO_DYNAMIC_RELOC (info, tga)))
            {
              struct plt_entry *ent;
              for (ent = tga->plt.plist; ent != NULL; ent = ent->next)
@@ -5598,6 +5667,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
              symtab_hdr->contents = (unsigned char *) locsyms;
          }
       }
+  htab->do_tls_opt = 1;
   return TRUE;
 }
 \f
@@ -5662,8 +5732,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       if (ent == NULL
          || (h->type != STT_GNU_IFUNC
              && (SYMBOL_CALLS_LOCAL (info, h)
-                 || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-                     && h->root.type == bfd_link_hash_undefweak))))
+                 || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))))
        {
          /* A PLT entry is not required/allowed when:
 
@@ -5916,16 +5985,18 @@ allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
   return where;
 }
 
-/* If H is undefined weak, make it dynamic if that makes sense.  */
+/* If H is undefined, make it dynamic if that makes sense.  */
 
 static bfd_boolean
-ensure_undefweak_dynamic (struct bfd_link_info *info,
-                         struct elf_link_hash_entry *h)
+ensure_undef_dynamic (struct bfd_link_info *info,
+                     struct elf_link_hash_entry *h)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
   if (htab->dynamic_sections_created
-      && h->root.type == bfd_link_hash_undefweak
+      && ((info->dynamic_undefined_weak != 0
+          && h->root.type == bfd_link_hash_undefweak)
+         || h->root.type == bfd_link_hash_undefined)
       && h->dynindx == -1
       && !h->forced_local
       && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
@@ -5959,9 +6030,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
     {
       unsigned int need;
 
-      /* Make sure this symbol is output as a dynamic symbol.
-        Undefined weak syms won't yet be marked as dynamic.  */
-      if (!ensure_undefweak_dynamic (info, &eh->elf))
+      /* Make sure this symbol is output as a dynamic symbol.  */
+      if (!ensure_undef_dynamic (info, &eh->elf))
        return FALSE;
 
       need = 0;
@@ -5995,8 +6065,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
               || (htab->elf.dynamic_sections_created
                   && eh->elf.dynindx != -1
                   && !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
-             && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
-                 || eh->elf.root.type != bfd_link_hash_undefweak))
+             && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &eh->elf))
            {
              asection *rsec = htab->elf.srelgot;
 
@@ -6014,6 +6083,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   else
     eh->elf.got.offset = (bfd_vma) -1;
 
+  /* If no dynamic sections we can't have dynamic relocs, except for
+     IFUNCs which are handled even in static executables.  */
   if (!htab->elf.dynamic_sections_created
       && h->type != STT_GNU_IFUNC)
     eh->dyn_relocs = NULL;
@@ -6028,13 +6099,23 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
      changes.  */
   else if (bfd_link_pic (info))
     {
+      /* Discard relocs on undefined symbols that must be local.  */
+      if (h->root.type == bfd_link_hash_undefined
+         && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+       eh->dyn_relocs = NULL;
+
+      /* Also discard relocs on undefined weak syms with non-default
+        visibility, or when dynamic_undefined_weak says so.  */
+      else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+       eh->dyn_relocs = NULL;
+
       /* Relocs that use pc_count are those that appear on a call insn,
         or certain REL relocs (see must_be_dyn_reloc) that can be
         generated via assembly.  We want calls to protected symbols to
         resolve directly to the function rather than going via the plt.
         If people want function pointer comparisons to work as expected
         then they should avoid writing weird assembly.  */
-      if (SYMBOL_CALLS_LOCAL (info, h))
+      else if (SYMBOL_CALLS_LOCAL (info, h))
        {
          struct elf_dyn_relocs **pp;
 
@@ -6062,24 +6143,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
            }
        }
 
-      /* Discard relocs on undefined symbols that must be local.  */
-      if (eh->dyn_relocs != NULL
-         && h->root.type == bfd_link_hash_undefined
-         && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
-             || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
-       eh->dyn_relocs = NULL;
-
-      /* Also discard relocs on undefined weak syms with non-default
-        visibility.  */
-      if (eh->dyn_relocs != NULL
-         && h->root.type == bfd_link_hash_undefweak)
+      if (eh->dyn_relocs != NULL)
        {
-         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-           eh->dyn_relocs = NULL;
-
-         /* Make sure undefined weak symbols are output as a dynamic
-            symbol in PIEs.  */
-         else if (!ensure_undefweak_dynamic (info, h))
+         /* Make sure this symbol is output as a dynamic symbol.  */
+         if (!ensure_undef_dynamic (info, h))
            return FALSE;
        }
     }
@@ -6095,9 +6162,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
               && eh->has_addr16_lo
               && htab->params->pic_fixup > 0))
        {
-         /* Make sure this symbol is output as a dynamic symbol.
-            Undefined weak syms won't yet be marked as dynamic.  */
-         if (!ensure_undefweak_dynamic (info, h))
+         /* Make sure this symbol is output as a dynamic symbol.  */
+         if (!ensure_undef_dynamic (info, h))
            return FALSE;
 
          if (h->dynindx == -1)
@@ -7885,7 +7951,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
          wrel->r_addend = 0;
 
          /* For ld -r, remove relocations in debug sections against
-            sections defined in discarded sections.  Not done for
+            symbols defined in discarded sections.  Not done for
             non-debug to preserve relocs in .eh_frame which the
             eh_frame editing code expects to be present.  */
          if (bfd_link_relocatable (info)
@@ -8233,7 +8299,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  wrel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_HA);
                  wrel->r_addend = got_addr;
                  insn &= ~0xffff;
-                 insn |= ((unsigned int )(got_addr + 0x8000) >> 16) & 0xffff;
+                 insn |= ((unsigned int(got_addr + 0x8000) >> 16) & 0xffff;
                  bfd_put_32 (input_bfd, insn, p);
 
                  /* Convert lis to lwz, loading address from GOT.  */
@@ -8259,9 +8325,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  r_type = R_PPC_GOT16_LO;
                }
              else
-               info->callbacks->einfo
+               _bfd_error_handler
                  /* xgettext:c-format */
-                 (_("%H: error: %s with unexpected instruction %x\n"),
+                 (_("%B(%A+%#Lx): error: %s with unexpected instruction %#x"),
                   input_bfd, input_section, rel->r_offset,
                   "R_PPC_ADDR16_HA", insn);
            }
@@ -8294,9 +8360,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  rel->r_info = ELF32_R_INFO (0, r_type);
                }
              else
-               info->callbacks->einfo
+               _bfd_error_handler
                  /* xgettext:c-format */
-                 (_("%H: error: %s with unexpected instruction %x\n"),
+                 (_("%B(%A+%#Lx): error: %s with unexpected instruction %#x"),
                   input_bfd, input_section, rel->r_offset,
                   "R_PPC_ADDR16_LO", insn);
            }
@@ -8369,6 +8435,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  loc += (htab->elf.irelplt->reloc_count++
                          * sizeof (Elf32_External_Rela));
                  bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
+                 htab->local_ifunc_resolver = 1;
 
                  ent->plt.offset |= 1;
                }
@@ -8396,10 +8463,44 @@ ppc_elf_relocate_section (bfd *output_bfd,
        }
 
       addend = rel->r_addend;
-      tls_type = 0;
       howto = NULL;
       if (r_type < R_PPC_max)
        howto = ppc_elf_howto_table[r_type];
+
+      switch (r_type)
+       {
+       default:
+         break;
+
+       case R_PPC_TPREL16_HA:
+         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             unsigned int insn = bfd_get_32 (input_bfd, p);
+             if ((insn & ((0x3f << 26) | 0x1f << 16))
+                 != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */)
+               /* xgettext:c-format */
+               info->callbacks->minfo
+                 (_("%H: warning: %s unexpected insn %#x.\n"),
+                  input_bfd, input_section, rel->r_offset, howto->name, insn);
+             else
+               bfd_put_32 (input_bfd, NOP, p);
+           }
+         break;
+
+       case R_PPC_TPREL16_LO:
+         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             unsigned int insn = bfd_get_32 (input_bfd, p);
+             insn &= ~(0x1f << 16);
+             insn |= 2 << 16;
+             bfd_put_32 (input_bfd, insn, p);
+           }
+         break;
+       }
+
+      tls_type = 0;
       switch (r_type)
        {
        default:
@@ -8479,8 +8580,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                if (!htab->elf.dynamic_sections_created
                    || h->dynindx == -1
                    || SYMBOL_REFERENCES_LOCAL (info, h)
-                   || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-                       && h->root.type == bfd_link_hash_undefweak))
+                   || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
                  /* This is actually a static link, or it is a
                     -Bsymbolic link and the symbol is defined
                     locally, or the symbol was forced to be local
@@ -8549,15 +8649,20 @@ ppc_elf_relocate_section (bfd *output_bfd,
                    if (indx != 0
                        || (bfd_link_pic (info)
                            && (h == NULL
-                               || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                               || h->root.type != bfd_link_hash_undefweak
+                               || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
                                || offp == &htab->tlsld_got.offset)))
                      {
                        asection *rsec = htab->elf.srelgot;
                        bfd_byte * loc;
 
                        if (ifunc != NULL)
-                         rsec = htab->elf.irelplt;
+                         {
+                           rsec = htab->elf.irelplt;
+                           if (indx == 0)
+                             htab->local_ifunc_resolver = 1;
+                           else if (is_static_defined (h))
+                             htab->maybe_local_ifunc_resolver = 1;
+                         }
                        outrel.r_offset = (htab->elf.sgot->output_section->vma
                                           + htab->elf.sgot->output_offset
                                           + off);
@@ -8609,10 +8714,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
                    else
                      {
                        bfd_vma value = relocation;
-                       int tlsopt = (htab->plt_type == PLT_NEW
-                                     && !htab->params->no_tls_get_addr_opt
-                                     && htab->tls_get_addr != NULL
-                                     && htab->tls_get_addr->plt.plist != NULL);
 
                        if (tls_ty != 0)
                          {
@@ -8624,8 +8725,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                                  value = 0;
                                else
                                  value -= htab->elf.tls_sec->vma + DTP_OFFSET;
-                               if ((tls_ty & TLS_TPREL)
-                                   || (tlsopt && !(tls_ty & TLS_DTPREL)))
+                               if (tls_ty & TLS_TPREL)
                                  value += DTP_OFFSET - TP_OFFSET;
                              }
 
@@ -8633,7 +8733,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                              {
                                bfd_put_32 (input_bfd, value,
                                            htab->elf.sgot->contents + off + 4);
-                               value = !tlsopt;
+                               value = 1;
                              }
                          }
                        bfd_put_32 (input_bfd, value,
@@ -8760,8 +8860,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
          if (htab->elf.tls_sec != NULL)
            addend -= htab->elf.tls_sec->vma + TP_OFFSET;
          /* The TPREL16 relocs shouldn't really be used in shared
-            libs as they will result in DT_TEXTREL being set, but
-            support them anyway.  */
+            libs or with non-local symbols as that will result in
+            DT_TEXTREL being set, but support them anyway.  */
          goto dodyn;
 
        case R_PPC_TPREL32:
@@ -8830,10 +8930,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
          if ((bfd_link_pic (info)
               && !(h != NULL
                    && ((h->root.type == bfd_link_hash_undefined
-                        && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
-                            || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
-                       || (h->root.type == bfd_link_hash_undefweak
-                           && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)))
+                        && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+                       || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
               && (must_be_dyn_reloc (info, r_type)
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
@@ -8850,6 +8948,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
              int skip;
              bfd_byte *loc;
              asection *sreloc;
+             long indx = 0;
+
 #ifdef DEBUG
              fprintf (stderr, "ppc_elf_relocate_section needs to "
                       "create relocation for %s\n",
@@ -8860,12 +8960,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
              /* When generating a shared object, these relocations
                 are copied into the output file to be resolved at run
                 time.  */
-             sreloc = elf_section_data (input_section)->sreloc;
-             if (ifunc)
-               sreloc = htab->elf.irelplt;
-             if (sreloc == NULL)
-               return FALSE;
-
              skip = 0;
              outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
                                                         input_section,
@@ -8878,14 +8972,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
              if (skip)
                memset (&outrel, 0, sizeof outrel);
-             else if ((h != NULL
-                       && (h->root.type == bfd_link_hash_undefined
-                           || h->root.type == bfd_link_hash_undefweak))
-                      || !SYMBOL_REFERENCES_LOCAL (info, h))
+             else if (!SYMBOL_REFERENCES_LOCAL (info, h))
                {
-                 BFD_ASSERT (h->dynindx != -1);
+                 indx = h->dynindx;
+                 BFD_ASSERT (indx != -1);
                  unresolved_reloc = FALSE;
-                 outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+                 outrel.r_info = ELF32_R_INFO (indx, r_type);
                  outrel.r_addend = rel->r_addend;
                }
              else
@@ -8894,8 +8986,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
                  if (r_type != R_PPC_ADDR32)
                    {
-                     long indx = 0;
-
                      if (ifunc != NULL)
                        {
                          /* If we get here when building a static
@@ -8960,6 +9050,18 @@ ppc_elf_relocate_section (bfd *output_bfd,
                    outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
                }
 
+             sreloc = elf_section_data (input_section)->sreloc;
+             if (ifunc)
+               {
+                 sreloc = htab->elf.irelplt;
+                 if (indx == 0)
+                   htab->local_ifunc_resolver = 1;
+                 else if (is_static_defined (h))
+                   htab->maybe_local_ifunc_resolver = 1;
+               }
+             if (sreloc == NULL)
+               return FALSE;
+
              loc = sreloc->contents;
              loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
              bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
@@ -8976,34 +9078,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  break;
                }
            }
-         else if (r_type == R_PPC_DTPMOD32
-                  && htab->plt_type == PLT_NEW
-                  && !htab->params->no_tls_get_addr_opt
-                  && htab->tls_get_addr != NULL
-                  && htab->tls_get_addr->plt.plist != NULL)
-           {
-             /* Set up for __tls_get_addr_opt stub when this entry
-                does not have dynamic relocs.  */
-             relocation = 0;
-             /* Set up the next word for local dynamic.  If it turns
-                out to be global dynamic, the reloc will overwrite
-                this value.  */
-             if (rel->r_offset + 8 <= input_section->size)
-               bfd_put_32 (input_bfd, DTP_OFFSET - TP_OFFSET,
-                           contents + rel->r_offset + 4);
-           }
-         else if (r_type == R_PPC_DTPREL32
-                  && htab->plt_type == PLT_NEW
-                  && !htab->params->no_tls_get_addr_opt
-                  && htab->tls_get_addr != NULL
-                  && htab->tls_get_addr->plt.plist != NULL
-                  && rel > relocs
-                  && rel[-1].r_info == ELF32_R_INFO (r_symndx, R_PPC_DTPMOD32)
-                  && rel[-1].r_offset + 4 == rel->r_offset)
-           {
-             /* __tls_get_addr_opt stub value.  */
-             addend += DTP_OFFSET - TP_OFFSET;
-           }
          break;
 
        case R_PPC_RELAX_PLT:
@@ -9388,7 +9462,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
          {
            bfd_vma value;
            const char *name;
-           //int reg;
            struct elf_link_hash_entry *sda = NULL;
 
            if (sec == NULL || sec->output_section == NULL)
@@ -9400,16 +9473,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
            name = bfd_get_section_name (output_bfd, sec->output_section);
            if (strcmp (name, ".sdata") == 0
                || strcmp (name, ".sbss") == 0)
-             {
-               //reg = 13;
-               sda = htab->sdata[0].sym;
-             }
+             sda = htab->sdata[0].sym;
            else if (strcmp (name, ".sdata2") == 0
                     || strcmp (name, ".sbss2") == 0)
-             {
-               //reg = 2;
-               sda = htab->sdata[1].sym;
-             }
+             sda = htab->sdata[1].sym;
            else
              {
                _bfd_error_handler
@@ -9426,18 +9493,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
                goto copy_reloc;
              }
 
-           if (sda != NULL)
+           if (sda == NULL || !is_static_defined (sda))
              {
-               if (!is_static_defined (sda))
-                 {
-                   unresolved_reloc = TRUE;
-                   break;
-                 }
+               unresolved_reloc = TRUE;
+               break;
              }
-
-           value = (sda->root.u.def.section->output_section->vma
-                    + sda->root.u.def.section->output_offset
-                    + addend);
+           value = relocation + addend - SYM_VAL (sda);
 
            if (r_type == R_PPC_VLE_SDAREL_LO16A)
              ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
@@ -9484,6 +9545,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
          }
          goto copy_reloc;
 
+       case R_PPC_VLE_ADDR20:
+         ppc_elf_vle_split20 (output_bfd, contents + rel->r_offset, relocation);
+         continue;
+
          /* Relocate against the beginning of the section.  */
        case R_PPC_SECTOFF:
        case R_PPC_SECTOFF_LO:
@@ -10263,12 +10328,19 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
 
            if (!htab->elf.dynamic_sections_created
                || h->dynindx == -1)
-             loc = (htab->elf.irelplt->contents
-                    + (htab->elf.irelplt->reloc_count++
-                       * sizeof (Elf32_External_Rela)));
+             {
+               loc = (htab->elf.irelplt->contents
+                      + (htab->elf.irelplt->reloc_count++
+                         * sizeof (Elf32_External_Rela)));
+               htab->local_ifunc_resolver = 1;
+             }
            else
-             loc = (htab->elf.srelplt->contents
-                    + reloc_index * sizeof (Elf32_External_Rela));
+             {
+               loc = (htab->elf.srelplt->contents
+                      + reloc_index * sizeof (Elf32_External_Rela));
+               if (h->type == STT_GNU_IFUNC && is_static_defined (h))
+                 htab->maybe_local_ifunc_resolver = 1;
+             }
            bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
 
            if (!h->def_regular)
@@ -10368,7 +10440,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       if (ppc_elf_hash_entry (h)->has_sda_refs)
        s = htab->relsbss;
-      else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+      else if (h->root.u.def.section == htab->elf.sdynrelro)
        s = htab->elf.sreldynrelro;
       else
        s = htab->elf.srelbss;
@@ -10418,7 +10490,6 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
                                 struct bfd_link_info *info)
 {
   asection *sdyn;
-  asection *splt;
   struct ppc_elf_link_hash_table *htab;
   bfd_vma got;
   bfd *dynobj;
@@ -10431,10 +10502,6 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
   htab = ppc_elf_hash_table (info);
   dynobj = htab->elf.dynobj;
   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
-  if (htab->is_vxworks)
-    splt = htab->elf.splt;
-  else
-    splt = NULL;
 
   got = 0;
   if (htab->elf.hgot != NULL)
@@ -10478,6 +10545,17 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
              dyn.d_un.d_ptr = got;
              break;
 
+           case DT_TEXTREL:
+             if (htab->local_ifunc_resolver)
+               info->callbacks->einfo
+                 (_("%X%P: text relocations and GNU indirect "
+                    "functions will result in a segfault at runtime\n"));
+             else if (htab->maybe_local_ifunc_resolver)
+               info->callbacks->einfo
+                 (_("%P: warning: text relocations and GNU indirect "
+                    "functions may result in a segfault at runtime\n"));
+             continue;
+
            default:
              if (htab->is_vxworks
                  && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
@@ -10489,7 +10567,8 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
        }
     }
 
-  if (htab->elf.sgot != NULL)
+  if (htab->elf.sgot != NULL
+      && htab->elf.sgot->output_section != bfd_abs_section_ptr)
     {
       if (htab->elf.hgot->root.u.def.section == htab->elf.sgot
          || htab->elf.hgot->root.u.def.section == htab->elf.sgotplt)
@@ -10531,8 +10610,12 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
     }
 
   /* Fill in the first entry in the VxWorks procedure linkage table.  */
-  if (splt && splt->size > 0)
+  if (htab->is_vxworks
+      && htab->elf.splt != NULL
+      && htab->elf.splt->size != 0
+      && htab->elf.splt->output_section != bfd_abs_section_ptr)
     {
+      asection *splt = htab->elf.splt;
       /* Use the right PLT. */
       const bfd_vma *plt_entry = (bfd_link_pic (info)
                                  ? ppc_elf_vxworks_pic_plt0_entry
@@ -10938,7 +11021,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #define elf_backend_finish_dynamic_sections    ppc_elf_finish_dynamic_sections
 #define elf_backend_fake_sections              ppc_elf_fake_sections
 #define elf_backend_additional_program_headers ppc_elf_additional_program_headers
-#define elf_backend_modify_segment_map         ppc_elf_modify_segment_map
+#define elf_backend_modify_segment_map         ppc_elf_modify_segment_map
 #define elf_backend_grok_prstatus              ppc_elf_grok_prstatus
 #define elf_backend_grok_psinfo                        ppc_elf_grok_psinfo
 #define elf_backend_write_core_note            ppc_elf_write_core_note
@@ -10986,7 +11069,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 
 /* VxWorks uses the elf default section flags for .plt.  */
 static const struct bfd_elf_special_section *
-ppc_elf_vxworks_get_sec_type_attr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+ppc_elf_vxworks_get_sec_type_attr (bfd *abfd, asection *sec)
 {
   if (sec->name == NULL)
     return NULL;
@@ -11008,7 +11091,7 @@ ppc_elf_vxworks_link_hash_table_create (bfd *abfd)
   if (ret)
     {
       struct ppc_elf_link_hash_table *htab
-        = (struct ppc_elf_link_hash_table *)ret;
+       = (struct ppc_elf_link_hash_table *)ret;
       htab->is_vxworks = 1;
       htab->plt_type = PLT_VXWORKS;
       htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE;
@@ -11023,23 +11106,23 @@ static bfd_boolean
 ppc_elf_vxworks_add_symbol_hook (bfd *abfd,
                                 struct bfd_link_info *info,
                                 Elf_Internal_Sym *sym,
-                                const char **namep ATTRIBUTE_UNUSED,
-                                flagword *flagsp ATTRIBUTE_UNUSED,
+                                const char **namep,
+                                flagword *flagsp,
                                 asection **secp,
                                 bfd_vma *valp)
 {
-  if (!elf_vxworks_add_symbol_hook(abfd, info, sym,namep, flagsp, secp,
-                                  valp))
+  if (!elf_vxworks_add_symbol_hook (abfd, info, sym, namep, flagsp, secp,
+                                   valp))
     return FALSE;
 
-  return ppc_elf_add_symbol_hook(abfd, info, sym,namep, flagsp, secp, valp);
+  return ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp);
 }
 
 static void
 ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
 {
-  ppc_elf_final_write_processing(abfd, linker);
-  elf_vxworks_final_write_processing(abfd, linker);
+  ppc_elf_final_write_processing (abfd, linker);
+  elf_vxworks_final_write_processing (abfd, linker);
 }
 
 /* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so
This page took 0.040902 seconds and 4 git commands to generate.