Accept mips-sgi-irix output in a few ld tests
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index e74da3af620b16769b3a413775d793abb962cceb..41fc403e07b8e5581bd6f9f128833f629bb129a4 100644 (file)
@@ -1,5 +1,5 @@
 /* Intel 80386/80486-specific support for 32-bit ELF
-   Copyright (C) 1993-2018 Free Software Foundation, Inc.
+   Copyright (C) 1993-2019 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -194,7 +194,7 @@ static reloc_howto_type elf_howto_table[]=
 #endif
 
 static reloc_howto_type *
-elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+elf_i386_reloc_type_lookup (bfd *abfd,
                            bfd_reloc_code_real_type code)
 {
   switch (code)
@@ -346,11 +346,13 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       return &elf_howto_table[R_386_GNU_VTENTRY - R_386_vt_offset];
 
     default:
-      break;
+      TRACE ("Unknown");
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type: %#x"),
+                         abfd, (int) code);
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
     }
-
-  TRACE ("Unknown");
-  return 0;
 }
 
 static reloc_howto_type *
@@ -368,7 +370,7 @@ elf_i386_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 }
 
 static reloc_howto_type *
-elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type)
+elf_i386_rtype_to_howto (unsigned r_type)
 {
   unsigned int indx;
 
@@ -379,25 +381,30 @@ elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type)
          >= R_386_ext2 - R_386_ext)
       && ((indx = r_type - R_386_vt_offset) - R_386_ext2
          >= R_386_vt - R_386_ext2))
-    {
-      /* xgettext:c-format */
-      _bfd_error_handler (_("%B: invalid relocation type %d"),
-                         abfd, (int) r_type);
-      indx = R_386_NONE;
-    }
+      return NULL;
   /* PR 17512: file: 0f67f69d.  */
   if (elf_howto_table [indx].type != r_type)
     return NULL;
   return &elf_howto_table[indx];
 }
 
-static void
-elf_i386_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
+static bfd_boolean
+elf_i386_info_to_howto_rel (bfd *abfd,
                            arelent *cache_ptr,
                            Elf_Internal_Rela *dst)
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
-  cache_ptr->howto = elf_i386_rtype_to_howto (abfd, r_type);
+
+  if ((cache_ptr->howto = elf_i386_rtype_to_howto (r_type)) == NULL)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
 /* Return whether a symbol name implies a local label.  The UnixWare
@@ -759,6 +766,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_plt =
     sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */
     elf_i386_lazy_plt_entry,           /* plt_entry */
     LAZY_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    NULL,                              /* plt_tlsdesc_entry */
+    0,                                 /* plt_tlsdesc_entry_size*/
+    0,                                 /* plt_tlsdesc_got1_offset */
+    0,                                 /* plt_tlsdesc_got2_offset */
+    0,                                 /* plt_tlsdesc_got1_insn_end */
+    0,                                 /* plt_tlsdesc_got2_insn_end */
     2,                                 /* plt0_got1_offset */
     8,                                 /* plt0_got2_offset */
     0,                                 /* plt0_got2_insn_end */
@@ -791,6 +804,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_ibt_plt =
     sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */
     elf_i386_lazy_ibt_plt_entry,       /* plt_entry */
     LAZY_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    NULL,                              /* plt_tlsdesc_entry */
+    0,                                 /* plt_tlsdesc_entry_size*/
+    0,                                 /* plt_tlsdesc_got1_offset */
+    0,                                 /* plt_tlsdesc_got2_offset */
+    0,                                 /* plt_tlsdesc_got1_insn_end */
+    0,                                 /* plt_tlsdesc_got2_insn_end */
     2,                                 /* plt0_got1_offset */
     8,                                 /* plt0_got2_offset */
     0,                                 /* plt0_got2_insn_end */
@@ -1132,8 +1151,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
       reloc_howto_type *from, *to;
       const char *name;
 
-      from = elf_i386_rtype_to_howto (abfd, from_type);
-      to = elf_i386_rtype_to_howto (abfd, to_type);
+      from = elf_i386_rtype_to_howto (from_type);
+      to = elf_i386_rtype_to_howto (to_type);
 
       if (h)
        name = h->root.root.string;
@@ -1156,10 +1175,10 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: TLS transition from %s to %s against `%s' at %#Lx "
-          "in section `%A' failed"),
+       (_("%pB: TLS transition from %s to %s against `%s'"
+          " at %#" PRIx64 " in section `%pA' failed"),
         abfd, from->name, to->name, name,
-        rel->r_offset, sec);
+        (uint64_t) rel->r_offset, sec);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
@@ -1247,7 +1266,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
 
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: direct GOT relocation R_386_GOT32X against `%s' without base"
+       (_("%pB: direct GOT relocation R_386_GOT32X against `%s' without base"
           " register can not be used when making a shared object"),
         abfd, name);
       return FALSE;
@@ -1324,8 +1343,8 @@ convert_branch:
                }
              else
                {
-                 nop = link_info->call_nop_byte;
-                 if (link_info->call_nop_as_suffix)
+                 nop = htab->params->call_nop_byte;
+                 if (htab->params->call_nop_as_suffix)
                    {
                      nop_offset = roff + 3;
                      irel->r_offset -= 1;
@@ -1507,7 +1526,7 @@ elf_i386_check_relocs (bfd *abfd,
       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
        {
          /* xgettext:c-format */
-         _bfd_error_handler (_("%B: bad symbol index: %d"),
+         _bfd_error_handler (_("%pB: bad symbol index: %d"),
                              abfd, r_symndx);
          goto error_return;
        }
@@ -1556,10 +1575,6 @@ elf_i386_check_relocs (bfd *abfd,
 
          /* It is referenced by a non-shared object. */
          h->ref_regular = 1;
-
-         if (h->type == STT_GNU_IFUNC)
-           elf_tdata (info->output_bfd)->has_gnu_symbols
-             |= elf_gnu_symbol_ifunc;
        }
 
       if (r_type == R_386_GOT32X
@@ -1704,7 +1719,7 @@ elf_i386_check_relocs (bfd *abfd,
                                             NULL);
                    _bfd_error_handler
                      /* xgettext:c-format */
-                     (_("%B: `%s' accessed both as normal and "
+                     (_("%pB: `%s' accessed both as normal and "
                         "thread local symbol"),
                       abfd, name);
                    bfd_set_error (bfd_error_bad_value);
@@ -1776,7 +1791,7 @@ do_relocation:
                    {
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: unsupported non-PIC call to IFUNC `%s'"),
+                       (_("%pB: unsupported non-PIC call to IFUNC `%s'"),
                         abfd, h->root.root.string);
                      bfd_set_error (bfd_error_bad_value);
                      goto error_return;
@@ -1812,7 +1827,7 @@ do_relocation:
 
          size_reloc = FALSE;
 do_size:
-         if (NEED_DYNAMIC_RELOCATION_P (info, h, sec, r_type,
+         if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
                                         R_386_32))
            {
              struct elf_dyn_relocs *p;
@@ -1889,9 +1904,7 @@ do_size:
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_386_GNU_VTENTRY:
-         BFD_ASSERT (h != NULL);
-         if (h != NULL
-             && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
            goto error_return;
          break;
 
@@ -1935,7 +1948,7 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
 {
   const char *name;
 
-  name = bfd_get_section_name (abfd, sec);
+  name = bfd_section_name (sec);
 
   /* This is an ugly, but unfortunately necessary hack that is
      needed when producing EFI binaries on x86. It tells
@@ -2009,7 +2022,11 @@ elf_i386_relocate_section (bfd *output_bfd,
   if (htab == NULL)
     return FALSE;
 
-  BFD_ASSERT (is_x86_elf (input_bfd, htab));
+  if (!is_x86_elf (input_bfd, htab))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return FALSE;
+    }
 
   symtab_hdr = &elf_symtab_hdr (input_bfd);
   sym_hashes = elf_sym_hashes (input_bfd);
@@ -2057,15 +2074,10 @@ elf_i386_relocate_section (bfd *output_bfd,
          continue;
        }
 
-      if ((indx = r_type) >= R_386_standard
-         && ((indx = r_type - R_386_ext_offset) - R_386_standard
-             >= R_386_ext - R_386_standard)
-         && ((indx = r_type - R_386_tls_offset) - R_386_ext
-             >= R_386_ext2 - R_386_ext))
+      howto = elf_i386_rtype_to_howto (r_type);
+      if (howto == NULL)
        return _bfd_unrecognized_reloc (input_bfd, input_section, r_type);
 
-      howto = elf_howto_table + indx;
-
       r_symndx = ELF32_R_SYM (rel->r_info);
       h = NULL;
       sym = NULL;
@@ -2178,7 +2190,7 @@ elf_i386_relocate_section (bfd *output_bfd,
       if (sec != NULL && discarded_section (sec))
        {
          _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;
@@ -2214,6 +2226,10 @@ elf_i386_relocate_section (bfd *output_bfd,
 
          if ((input_section->flags & SEC_ALLOC) == 0)
            {
+             /* If this is a SHT_NOTE section without SHF_ALLOC, treat
+                STT_GNU_IFUNC symbol as STT_FUNC.  */
+             if (elf_section_type (input_section) == SHT_NOTE)
+               goto skip_ifunc;
              /* Dynamic relocs are not propagated for SEC_DEBUGGING
                 sections because such sections are not SEC_ALLOC and
                 thus ld.so will not process them.  */
@@ -2354,7 +2370,7 @@ bad_ifunc_reloc:
                                         NULL);
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: relocation %s against STT_GNU_IFUNC "
+               (_("%pB: relocation %s against STT_GNU_IFUNC "
                   "symbol `%s' isn't supported"), input_bfd,
                 howto->name, name);
              bfd_set_error (bfd_error_bad_value);
@@ -2387,7 +2403,7 @@ do_ifunc_pointer:
 
                  if (POINTER_LOCAL_IFUNC_P (info, h))
                    {
-                     info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
+                     info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"),
                                              h->root.root.string,
                                              h->root.u.def.section->owner);
 
@@ -2433,72 +2449,14 @@ do_ifunc_pointer:
            }
        }
 
+skip_ifunc:
       resolved_to_zero = (eh != NULL
                          && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh));
 
       switch (r_type)
        {
        case R_386_GOT32X:
-         /* Avoid optimizing _DYNAMIC since ld.so may use its
-            link-time address.  */
-         if (h == htab->elf.hdynamic)
-           goto r_386_got32;
-
-         if (bfd_link_pic (info))
-           {
-             /* It is OK to convert mov to lea and convert indirect
-                branch to direct branch.  It is OK to convert adc,
-                add, and, cmp, or, sbb, sub, test, xor only when PIC
-                is false.   */
-             unsigned int opcode, addend;
-             addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
-             if (addend != 0)
-               goto r_386_got32;
-             opcode = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
-             if (opcode != 0x8b && opcode != 0xff)
-               goto r_386_got32;
-           }
-
-         /* Resolve "mov GOT[(%reg)], %reg",
-            "call/jmp *GOT[(%reg)]", "test %reg, foo@GOT[(%reg)]"
-            and "binop foo@GOT[(%reg)], %reg".  */
-         if (h == NULL
-             || (h->plt.offset == (bfd_vma) -1
-                 && h->got.offset == (bfd_vma) -1)
-             || htab->elf.sgotplt == NULL)
-           abort ();
-
-         offplt = (htab->elf.sgotplt->output_section->vma
-                   + htab->elf.sgotplt->output_offset);
-
-         /* It is relative to .got.plt section.  */
-         if (h->got.offset != (bfd_vma) -1)
-           /* Use GOT entry.  Mask off the least significant bit in
-              GOT offset which may be set by R_386_GOT32 processing
-              below.  */
-           relocation = (htab->elf.sgot->output_section->vma
-                         + htab->elf.sgot->output_offset
-                         + (h->got.offset & ~1) - offplt);
-         else
-           /* Use GOTPLT entry.  */
-           relocation = (h->plt.offset / plt_entry_size
-                         - htab->plt.has_plt0 + 3) * 4;
-
-         if (!bfd_link_pic (info))
-           {
-             /* If not PIC, add the .got.plt section address for
-                baseless addressing.  */
-             unsigned int modrm;
-             modrm = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
-             if ((modrm & 0xc7) == 0x5)
-               relocation += offplt;
-           }
-
-         unresolved_reloc = FALSE;
-         break;
-
        case R_386_GOT32:
-r_386_got32:
          /* Relocation is to the entry for this symbol in the global
             offset table.  */
          if (htab->elf.sgot == NULL)
@@ -2602,7 +2560,7 @@ disallow_got32:
 
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: direct GOT relocation %s against `%s'"
+                   (_("%pB: direct GOT relocation %s against `%s'"
                       " without base register can not be used"
                       " when making a shared object"),
                     input_bfd, howto->name, name);
@@ -2652,7 +2610,7 @@ disallow_got32:
 
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: relocation R_386_GOTOFF against undefined %s"
+                   (_("%pB: relocation R_386_GOTOFF against undefined %s"
                       " `%s' can not be used when making a shared object"),
                     input_bfd, v, h->root.root.string);
                  bfd_set_error (bfd_error_bad_value);
@@ -2665,7 +2623,7 @@ disallow_got32:
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: relocation R_386_GOTOFF against protected %s"
+                   (_("%pB: relocation R_386_GOTOFF against protected %s"
                       " `%s' can not be used when making a shared object"),
                     input_bfd,
                     h->type == STT_FUNC ? "function" : "data",
@@ -3442,10 +3400,10 @@ disallow_got32:
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
+           (_("%pB(%pA+%#" PRIx64 "): unresolvable %s relocation against symbol `%s'"),
             input_bfd,
             input_section,
-            rel->r_offset,
+            (uint64_t) rel->r_offset,
             howto->name,
             h->root.root.string);
          return FALSE;
@@ -3471,7 +3429,7 @@ check_relocation_error:
              if (name == NULL)
                return FALSE;
              if (*name == '\0')
-               name = bfd_section_name (input_bfd, sec);
+               name = bfd_section_name (sec);
            }
 
          if (r == bfd_reloc_overflow)
@@ -3482,9 +3440,9 @@ check_relocation_error:
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B(%A+%#Lx): reloc against `%s': error %d"),
+               (_("%pB(%pA+%#" PRIx64 "): reloc against `%s': error %d"),
                 input_bfd, input_section,
-                rel->r_offset, name, (int) r);
+                (uint64_t) rel->r_offset, name, (int) r);
              return FALSE;
            }
        }
@@ -3693,7 +3651,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                          + got_offset);
          if (PLT_LOCAL_IFUNC_P (info, h))
            {
-             info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
+             info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"),
                                      h->root.root.string,
                                      h->root.u.def.section->owner);
 
@@ -3793,6 +3751,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
        sym->st_value = 0;
     }
 
+  _bfd_x86_elf_link_fixup_ifunc_symbol (info, htab, h, sym);
+
   /* Don't generate dynamic GOT relocation against undefined weak
      symbol in executable.  */
   if (h->got.offset != (bfd_vma) -1
@@ -3832,7 +3792,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                }
              if (SYMBOL_REFERENCES_LOCAL_P (info, h))
                {
-                 info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
+                 info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"),
                                          h->root.root.string,
                                          h->root.u.def.section->owner);
 
@@ -4423,6 +4383,8 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
 
 #define elf_backend_linux_prpsinfo32_ugid16    TRUE
 
+#define        elf32_bed                             elf32_i386_bed
+
 #include "elf32-target.h"
 
 /* FreeBSD support.  */
@@ -4438,10 +4400,11 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
    "FreeBSD" label in the ELF header.  So we put this label on all
    executables and (for simplicity) also all other object files.  */
 
-static void
-elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
+static bfd_boolean
+elf_i386_fbsd_init_file_header (bfd *abfd, struct bfd_link_info *info)
 {
-  _bfd_elf_post_process_headers (abfd, info);
+  if (!_bfd_elf_init_file_header (abfd, info))
+    return FALSE;
 
 #ifdef OLD_FREEBSD_ABI_LABEL
   {
@@ -4450,10 +4413,11 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
     memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
   }
 #endif
+  return TRUE;
 }
 
-#undef elf_backend_post_process_headers
-#define        elf_backend_post_process_headers        elf_i386_fbsd_post_process_headers
+#undef elf_backend_init_file_header
+#define        elf_backend_init_file_header    elf_i386_fbsd_init_file_header
 #undef elf32_bed
 #define        elf32_bed                               elf32_i386_fbsd_bed
 
@@ -4461,6 +4425,8 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
 
 #include "elf32-target.h"
 
+#undef elf_backend_init_file_header
+
 /* Solaris 2.  */
 
 #undef TARGET_LITTLE_SYM
@@ -4476,8 +4442,6 @@ static const struct elf_x86_backend_data elf_i386_solaris_arch_bed =
 #undef elf_backend_arch_data
 #define        elf_backend_arch_data           &elf_i386_solaris_arch_bed
 
-#undef elf_backend_post_process_headers
-
 /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
    objects won't be recognized.  */
 #undef ELF_OSABI
@@ -4645,7 +4609,6 @@ elf32_iamcu_elf_object_p (bfd *abfd)
 #undef ELF_OSABI
 #undef elf_backend_want_plt_sym
 #define elf_backend_want_plt_sym       0
-#undef elf_backend_post_process_headers
 #undef elf_backend_static_tls_alignment
 
 /* NaCl uses substantially different PLT entries for the same effects.  */
@@ -4771,6 +4734,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt =
     sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */
     elf_i386_nacl_plt_entry,           /* plt_entry */
     NACL_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    NULL,                              /* plt_tlsdesc_entry */
+    0,                                 /* plt_tlsdesc_entry_size*/
+    0,                                 /* plt_tlsdesc_got1_offset */
+    0,                                 /* plt_tlsdesc_got2_offset */
+    0,                                 /* plt_tlsdesc_got1_insn_end */
+    0,                                 /* plt_tlsdesc_got2_insn_end */
     2,                                 /* plt0_got1_offset */
     8,                                 /* plt0_got2_offset */
     0,                                 /* plt0_got2_insn_end */
@@ -4806,8 +4775,8 @@ elf32_i386_nacl_elf_object_p (bfd *abfd)
 #define elf_backend_object_p                   elf32_i386_nacl_elf_object_p
 #undef elf_backend_modify_segment_map
 #define        elf_backend_modify_segment_map          nacl_modify_segment_map
-#undef elf_backend_modify_program_headers
-#define        elf_backend_modify_program_headers      nacl_modify_program_headers
+#undef elf_backend_modify_headers
+#define        elf_backend_modify_headers              nacl_modify_headers
 #undef elf_backend_final_write_processing
 #define elf_backend_final_write_processing     nacl_final_write_processing
 
@@ -4816,7 +4785,7 @@ elf32_i386_nacl_elf_object_p (bfd *abfd)
 /* Restore defaults.  */
 #undef elf_backend_object_p
 #undef elf_backend_modify_segment_map
-#undef elf_backend_modify_program_headers
+#undef elf_backend_modify_headers
 #undef elf_backend_final_write_processing
 
 /* VxWorks support.  */
This page took 0.032722 seconds and 4 git commands to generate.