PowerPC64 GOT_PCREL relocs
[external/binutils.git] / bfd / elf32-ppc.c
index 61f70de..5e5834a 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC-specific support for 32-bit ELF
-   Copyright (C) 1994-2018 Free Software Foundation, Inc.
+   Copyright (C) 1994-2019 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -649,8 +649,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
        ppc_elf_unhandled_reloc),
 
   /* e_li split20 format.  */
-  HOW (R_PPC_VLE_ADDR20, 2, 20, 0x1f07ff, 16, FALSE, dont,
-       bfd_elf_generic_reloc),
+  HOW (R_PPC_VLE_ADDR20, 2, 20, 0x1f7fff, 0, FALSE, dont,
+       ppc_elf_unhandled_reloc),
 
   HOW (R_PPC_IRELATIVE, 2, 32, 0xffffffff, 0, FALSE, dont,
        ppc_elf_unhandled_reloc),
@@ -1077,7 +1077,9 @@ _bfd_elf_ppc_set_arch (bfd *abfd)
   if (mach == 0)
     {
       s = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
-      if (s != NULL && bfd_malloc_and_get_section (abfd, s, &contents))
+      if (s != NULL
+         && s->size >= 24
+         && bfd_malloc_and_get_section (abfd, s, &contents))
        {
          unsigned int apuinfo_size = bfd_get_32 (abfd, contents + 4);
          unsigned int i;
@@ -1703,7 +1705,7 @@ ppc_elf_write_section (bfd *abfd ATTRIBUTE_UNUSED,
 /* Finally we can generate the output section.  */
 
 static void
-ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
+ppc_final_write_processing (bfd *abfd)
 {
   bfd_byte *buffer;
   asection *asec;
@@ -1754,6 +1756,13 @@ ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
 
   apuinfo_list_finish ();
 }
+
+static bfd_boolean
+ppc_elf_final_write_processing (bfd *abfd)
+{
+  ppc_final_write_processing (abfd);
+  return _bfd_elf_final_write_processing (abfd);
+}
 \f
 static bfd_boolean
 is_nonpic_glink_stub (bfd *abfd, asection *glink, bfd_vma off)
@@ -2109,9 +2118,7 @@ struct ppc_elf_link_hash_entry
      of the other TLS bits are set.  tls_optimize clears bits when
      optimizing to indicate the corresponding GOT entry type is not
      needed.  If set, TLS_TLS is never cleared.  tls_optimize may also
-     set TLS_TPRELGD when a GD reloc turns into a TPREL one.  We use a
-     separate flag rather than setting TPREL just for convenience in
-     distinguishing the two cases.
+     set TLS_GDIE when a GD reloc turns into an IE one.
      These flags are also kept for local symbols.  */
 #define TLS_TLS                 1      /* Any TLS reloc.  */
 #define TLS_GD          2      /* GD reloc. */
@@ -2119,7 +2126,7 @@ struct ppc_elf_link_hash_entry
 #define TLS_TPREL       8      /* TPREL reloc, => IE. */
 #define TLS_DTPREL     16      /* DTPREL reloc, => LD. */
 #define TLS_MARK       32      /* __tls_get_addr call marked. */
-#define TLS_TPRELGD    64      /* TPREL reloc resulting from GD->IE. */
+#define TLS_GDIE       64      /* GOT TPREL reloc resulting from GD->IE. */
   unsigned char tls_mask;
 
   /* The above field is also used to mark function symbols.  In which
@@ -3089,11 +3096,6 @@ ppc_elf_check_relocs (bfd *abfd,
 
          /* Indirect .sdata relocation.  */
        case R_PPC_EMB_SDAI16:
-         if (bfd_link_pic (info))
-           {
-             bad_shared_reloc (abfd, r_type);
-             return FALSE;
-           }
          htab->sdata[0].sym->ref_regular = 1;
          if (!elf_allocate_pointer_linker_section (abfd, &htab->sdata[0],
                                                    h, rel))
@@ -3107,7 +3109,7 @@ ppc_elf_check_relocs (bfd *abfd,
 
          /* Indirect .sdata2 relocation.  */
        case R_PPC_EMB_SDA2I16:
-         if (bfd_link_pic (info))
+         if (!bfd_link_executable (info))
            {
              bad_shared_reloc (abfd, r_type);
              return FALSE;
@@ -3153,7 +3155,7 @@ ppc_elf_check_relocs (bfd *abfd,
          break;
 
        case R_PPC_EMB_SDA2REL:
-         if (bfd_link_pic (info))
+         if (!bfd_link_executable (info))
            {
              bad_shared_reloc (abfd, r_type);
              return FALSE;
@@ -3170,11 +3172,6 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_VLE_SDA21:
        case R_PPC_EMB_SDA21:
        case R_PPC_EMB_RELSDA:
-         if (bfd_link_pic (info))
-           {
-             bad_shared_reloc (abfd, r_type);
-             return FALSE;
-           }
          if (h != NULL)
            {
              ppc_elf_hash_entry (h)->has_sda_refs = TRUE;
@@ -3187,11 +3184,6 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_EMB_NADDR16_LO:
        case R_PPC_EMB_NADDR16_HI:
        case R_PPC_EMB_NADDR16_HA:
-         if (bfd_link_pic (info))
-           {
-             bad_shared_reloc (abfd, r_type);
-             return FALSE;
-           }
          if (h != NULL)
            h->non_got_ref = TRUE;
          break;
@@ -3316,9 +3308,7 @@ ppc_elf_check_relocs (bfd *abfd,
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_PPC_GNU_VTENTRY:
-         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;
          break;
 
@@ -3886,10 +3876,10 @@ ppc_elf_vle_split16 (bfd *input_bfd,
                     split16_format_type split16_format,
                     bfd_boolean fixup)
 {
-  unsigned int insn, opcode, top5;
+  unsigned int insn, opcode;
 
   insn = bfd_get_32 (input_bfd, loc);
-  opcode = insn & 0xfc00f800;
+  opcode = insn & E_OPCODE_MASK;
   if (opcode == E_OR2I_INSN
       || opcode == E_AND2I_DOT_INSN
       || opcode == E_OR2IS_INSN
@@ -3926,10 +3916,22 @@ ppc_elf_vle_split16 (bfd *input_bfd,
               input_bfd, input_section, offset, opcode);
        }
     }
-  top5 = value & 0xf800;
-  top5 = top5 << (split16_format == split16a_type ? 5 : 10);
-  insn &= (split16_format == split16a_type ? ~0x1f07ff : ~0x3e007ff);
-  insn |= top5;
+  if (split16_format == split16a_type)
+    {
+      insn &= ~((0xf800 << 5) | 0x7ff);
+      insn |= (value & 0xf800) << 5;
+      if ((insn & E_LI_MASK) == E_LI_INSN)
+       {
+         /* Hack for e_li.  Extend sign.  */
+         insn &= ~(0xf0000 >> 5);
+         insn |= (-(value & 0x8000) & 0xf0000) >> 5;
+       }
+    }
+  else
+    {
+      insn &= ~((0xf800 << 10) | 0x7ff);
+      insn |= (value & 0xf800) << 10;
+    }
   insn |= value & 0x7ff;
   bfd_put_32 (input_bfd, insn, loc);
 }
@@ -4513,7 +4515,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
                        tls_set = 0;
                      else
                        /* GD -> IE */
-                       tls_set = TLS_TLS | TLS_TPRELGD;
+                       tls_set = TLS_TLS | TLS_GDIE;
                      tls_clear = TLS_GD;
                      break;
 
@@ -5039,7 +5041,7 @@ got_entries_needed (int tls_mask)
       need = 0;
       if ((tls_mask & TLS_GD) != 0)
        need += 8;
-      if ((tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
+      if ((tls_mask & (TLS_TPREL | TLS_GDIE)) != 0)
        need += 4;
       if ((tls_mask & TLS_DTPREL) != 0)
        need += 4;
@@ -5060,7 +5062,7 @@ got_relocs_needed (int tls_mask, unsigned int need, bfd_boolean known)
      condition as that for IE, but ld.so needs to differentiate
      LD and GD entries.  */
   if (known && (tls_mask & TLS_TLS) != 0
-      && (tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
+      && (tls_mask & (TLS_TPREL | TLS_GDIE)) != 0)
     need -= 4;
   return need * sizeof (Elf32_External_Rela) / 4;
 }
@@ -7013,6 +7015,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
                      (bfd_link_relocatable (info)) ? " (relocatable)" : "");
 #endif
 
+  if (!is_ppc_elf (input_bfd))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return FALSE;
+    }
+
   got2 = bfd_get_section_by_name (input_bfd, ".got2");
 
   /* Initialize howto table if not already done.  */
@@ -7090,7 +7098,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
            howto = ppc_elf_howto_table[r_type];
 
          _bfd_clear_contents (howto, input_bfd, input_section,
-                              contents + rel->r_offset);
+                              contents, rel->r_offset);
          wrel->r_offset = rel->r_offset;
          wrel->r_info = 0;
          wrel->r_addend = 0;
@@ -7195,7 +7203,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_GOT_TLSGD16_HI:
        case R_PPC_GOT_TLSGD16_HA:
-         tls_gd = TLS_TPRELGD;
+         tls_gd = TLS_GDIE;
          if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
            goto tls_gdld_hi;
          break;
@@ -7220,7 +7228,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_GOT_TLSGD16:
        case R_PPC_GOT_TLSGD16_LO:
-         tls_gd = TLS_TPRELGD;
+         tls_gd = TLS_GDIE;
          if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
            goto tls_ldgd_opt;
          break;
@@ -7322,7 +7330,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  break;
                }
 
-             if ((tls_mask & TLS_TPRELGD) != 0)
+             if ((tls_mask & TLS_GDIE) != 0)
                {
                  /* IE */
                  r_type = R_PPC_NONE;
@@ -7780,7 +7788,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
              {
                unsigned int tls_m = ((tls_mask & TLS_TLS) != 0
                                      ? tls_mask & (TLS_LD | TLS_GD | TLS_DTPREL
-                                                   | TLS_TPREL | TLS_TPRELGD)
+                                                   | TLS_TPREL | TLS_GDIE)
                                      : 0);
 
                if (offp == &htab->tlsld_got.offset)
@@ -7810,7 +7818,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                        tls_ty = TLS_TLS | TLS_DTPREL;
                        tls_m &= ~TLS_DTPREL;
                      }
-                   else if ((tls_m & (TLS_TPREL | TLS_TPRELGD)) != 0)
+                   else if ((tls_m & (TLS_TPREL | TLS_GDIE)) != 0)
                      {
                        tls_ty = TLS_TLS | TLS_TPREL;
                        tls_m = 0;
@@ -8134,6 +8142,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
              outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);
 
+             /* Optimize unaligned reloc use.  */
+             if ((r_type == R_PPC_ADDR32 && (outrel.r_offset & 3) != 0)
+                 || (r_type == R_PPC_UADDR32 && (outrel.r_offset & 3) == 0))
+               r_type ^= R_PPC_ADDR32 ^ R_PPC_UADDR32;
+             if ((r_type == R_PPC_ADDR16 && (outrel.r_offset & 1) != 0)
+                 || (r_type == R_PPC_UADDR16 && (outrel.r_offset & 1) == 0))
+               r_type ^= R_PPC_ADDR16 ^ R_PPC_UADDR16;
+
              if (skip)
                memset (&outrel, 0, sizeof outrel);
              else if (!SYMBOL_REFERENCES_LOCAL (info, h))
@@ -8191,19 +8207,27 @@ ppc_elf_relocate_section (bfd *output_bfd,
                             but ld.so expects buggy relocs.
                             FIXME: Why not always use a zero index?  */
                          osec = sec->output_section;
-                         indx = elf_section_data (osec)->dynindx;
-                         if (indx == 0)
+                         if ((osec->flags & SEC_THREAD_LOCAL) != 0)
+                           {
+                             osec = htab->elf.tls_sec;
+                             indx = 0;
+                           }
+                         else
                            {
-                             osec = htab->elf.text_index_section;
                              indx = elf_section_data (osec)->dynindx;
+                             if (indx == 0)
+                               {
+                                 osec = htab->elf.text_index_section;
+                                 indx = elf_section_data (osec)->dynindx;
+                               }
+                             BFD_ASSERT (indx != 0);
                            }
-                         BFD_ASSERT (indx != 0);
-#ifdef DEBUG
-                         if (indx == 0)
-                           printf ("indx=%ld section=%s flags=%08x name=%s\n",
-                                   indx, osec->name, osec->flags,
-                                   h->root.root.string);
-#endif
+
+                         /* ld.so doesn't expect buggy TLS relocs.
+                            Don't leave the symbol value in the
+                            addend for them.  */
+                         if (IS_PPC_TLS_RELOC (r_type))
+                           outrel.r_addend -= osec->vma;
                        }
 
                      outrel.r_info = ELF32_R_INFO (indx, r_type);
@@ -8638,6 +8662,19 @@ ppc_elf_relocate_section (bfd *output_bfd,
                addend -= SYM_VAL (sda);
              }
 
+           if (r_type == R_PPC_EMB_RELSDA)
+             break;
+
+           /* The PowerPC Embedded Application Binary Interface
+              version 1.0 insanely chose to specify R_PPC_EMB_SDA21
+              operating on a 24-bit field at r_offset.  GNU as and
+              GNU ld have always assumed R_PPC_EMB_SDA21 operates on
+              a 32-bit bit insn at r_offset.  Cope with object file
+              producers that possibly comply with the EABI in
+              generating an odd r_offset for big-endian objects.  */
+           if (r_type == R_PPC_EMB_SDA21)
+             rel->r_offset &= ~1;
+
            insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
            if (reg == 0
                && (r_type == R_PPC_VLE_SDA21
@@ -8665,13 +8702,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  goto overflow;
                goto copy_reloc;
              }
-           else if (r_type == R_PPC_EMB_SDA21
-                    || r_type == R_PPC_VLE_SDA21
-                    || r_type == R_PPC_VLE_SDA21_LO)
-             {
-               /* Fill in register field.  */
-               insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
-             }
+           /* Fill in register field.  */
+           insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
            bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
          }
          break;
@@ -8834,7 +8866,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
            }
          else if (htab->plt_type != PLT_NEW)
            info->callbacks->einfo
-             (_("%P: %H: %s relocation unsupported for bss-plt\n"),
+             (_("%X%P: %H: %s relocation unsupported for bss-plt\n"),
               input_bfd, input_section, rel->r_offset,
               howto->name);
          break;
@@ -8852,7 +8884,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
            }
          else if (htab->plt_type != PLT_NEW)
            info->callbacks->einfo
-             (_("%P: %H: %s relocation unsupported for bss-plt\n"),
+             (_("%X%P: %H: %s relocation unsupported for bss-plt\n"),
               input_bfd, input_section, rel->r_offset,
               howto->name);
          break;
@@ -9686,6 +9718,7 @@ ppc_finish_symbols (struct bfd_link_info *info)
                bfd_byte *loc;
                bfd_vma val;
                Elf_Internal_Rela rela;
+               unsigned char *p;
 
                if (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms,
                                lplt - local_plt, ibfd))
@@ -9730,14 +9763,9 @@ ppc_finish_symbols (struct bfd_link_info *info)
                loc = relplt->contents + (relplt->reloc_count++
                                          * sizeof (Elf32_External_Rela));
                bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
-             }
-           if ((ent->glink_offset & 1) == 0)
-             {
-               unsigned char *p = ((unsigned char *) htab->glink->contents
-                                   + ent->glink_offset);
 
+               p = (unsigned char *) htab->glink->contents + ent->glink_offset;
                write_glink_stub (NULL, ent, htab->elf.iplt, p, info);
-               ent->glink_offset |= 1;
              }
          }
 
@@ -10459,11 +10487,11 @@ ppc_elf_vxworks_add_symbol_hook (bfd *abfd,
   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)
+static bfd_boolean
+ppc_elf_vxworks_final_write_processing (bfd *abfd)
 {
-  ppc_elf_final_write_processing (abfd, linker);
-  elf_vxworks_final_write_processing (abfd, linker);
+  ppc_final_write_processing (abfd);
+  return elf_vxworks_final_write_processing (abfd);
 }
 
 /* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so