Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elfxx-sparc.c
index c75d053dbf7721a9e94fc0395b410fdcc8de45b4..81812afc5a41cedfab9ff98d68f26aaf1e082e64 100644 (file)
@@ -311,7 +311,7 @@ static reloc_howto_type sparc_rev32_howto =
   HOWTO(R_SPARC_REV32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_REV32", FALSE,0,0xffffffff,TRUE);
 
 reloc_howto_type *
-_bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+_bfd_sparc_elf_reloc_type_lookup (bfd *abfd,
                                  bfd_reloc_code_real_type code)
 {
   /* We explicitly handle each relocation type in the switch
@@ -585,8 +585,10 @@ _bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     default:
       break;
     }
-    bfd_set_error (bfd_error_bad_value);
-    return NULL;
+  /* xgettext:c-format */
+  _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, (int) code);
+  bfd_set_error (bfd_error_bad_value);
+  return NULL;
 }
 
 reloc_howto_type *
@@ -595,10 +597,7 @@ _bfd_sparc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 {
   unsigned int i;
 
-  for (i = 0;
-       i < (sizeof (_bfd_sparc_elf_howto_table)
-           / sizeof (_bfd_sparc_elf_howto_table[0]));
-       i++)
+  for (i = 0; i < ARRAY_SIZE (_bfd_sparc_elf_howto_table); i++)
     if (_bfd_sparc_elf_howto_table[i].name != NULL
        && strcasecmp (_bfd_sparc_elf_howto_table[i].name, r_name) == 0)
       return &_bfd_sparc_elf_howto_table[i];
@@ -614,7 +613,8 @@ _bfd_sparc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 }
 
 reloc_howto_type *
-_bfd_sparc_elf_info_to_howto_ptr (bfd *abfd, unsigned int r_type)
+_bfd_sparc_elf_info_to_howto_ptr (bfd *abfd ATTRIBUTE_UNUSED,
+                                 unsigned int r_type)
 {
   switch (r_type)
     {
@@ -638,7 +638,8 @@ _bfd_sparc_elf_info_to_howto_ptr (bfd *abfd, unsigned int r_type)
        {
          _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
                              abfd, r_type);
-         r_type = R_SPARC_NONE;
+         bfd_set_error (bfd_error_bad_value);
+         return NULL;
        }
       return &_bfd_sparc_elf_howto_table[r_type];
     }
@@ -649,13 +650,20 @@ _bfd_sparc_elf_info_to_howto_ptr (bfd *abfd, unsigned int r_type)
 #define SPARC_ELF_R_TYPE(r_info)       \
        ((r_info) & 0xff)
 
-void
+bfd_boolean
 _bfd_sparc_elf_info_to_howto (bfd *abfd, arelent *cache_ptr,
                              Elf_Internal_Rela *dst)
 {
   unsigned int r_type = SPARC_ELF_R_TYPE (dst->r_info);
 
-  cache_ptr->howto = _bfd_sparc_elf_info_to_howto_ptr (abfd, r_type);
+  if ((cache_ptr->howto = _bfd_sparc_elf_info_to_howto_ptr (abfd, r_type)) == NULL)
+    {
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+  return TRUE;
 }
 \f
 
@@ -693,9 +701,12 @@ struct _bfd_sparc_elf_link_hash_entry
 #define GOT_TLS_IE      3
   unsigned char tls_type;
 
-    /* Symbol has GOT or PLT relocations.  */
+  /* Symbol has GOT or PLT relocations.  */
   unsigned int has_got_reloc : 1;
 
+  /* Symbol has old-style, non-relaxable GOT relocations.  */
+  unsigned int has_old_style_got_reloc : 1;
+
   /* Symbol has non-GOT/non-PLT relocations in text sections.  */
   unsigned int has_non_got_reloc : 1;
 
@@ -1561,11 +1572,12 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                    && r_type != R_SPARC_GOTDATA_OP_LOX10)
                  local_got_refcounts[r_symndx] += 1;
 
-               old_tls_type = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx];
+               old_tls_type
+                 = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx];
              }
 
-           /* If a TLS symbol is accessed using IE at least once, there is no point
-              in using the dynamic model for it.  */
+           /* If a TLS symbol is accessed using IE at least once, there is no
+              point in using the dynamic model for it.  */
            if (old_tls_type != tls_type)
              {
                if (old_tls_type == GOT_UNKNOWN)
@@ -1595,7 +1607,13 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            return FALSE;
 
          if (eh != NULL)
-           eh->has_got_reloc = 1;
+           {
+             eh->has_got_reloc = 1;
+             if (r_type == R_SPARC_GOT10
+                 || r_type == R_SPARC_GOT13
+                 || r_type == R_SPARC_GOT22)
+               eh->has_old_style_got_reloc = 1;
+           }
          break;
 
        case R_SPARC_TLS_GD_CALL:
@@ -2993,7 +3011,13 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
 
          if ((input_section->flags & SEC_ALLOC) == 0
              || h->plt.offset == (bfd_vma) -1)
-           abort ();
+           {
+             /* 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;
+             abort ();
+           }
 
          plt_sec = htab->elf.splt;
          if (! plt_sec)
@@ -3097,6 +3121,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
            }
        }
 
+    skip_ifunc:
       eh = (struct _bfd_sparc_elf_link_hash_entry *) h;
       resolved_to_zero = eh && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh);
 
@@ -3123,12 +3148,14 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
              bfd_put_32 (output_bfd, relocation, contents + rel->r_offset);
 
              /* If the symbol is global but not dynamic, an .rela.* slot has
-                been allocated for it in the GOT so output R_SPARC_NONE here.
-                See also the handling of other GOT relocations just below.  */
+                been allocated for it in the GOT so output R_SPARC_NONE here,
+                if it isn't also subject to another, old-style GOT relocation.
+                See also the handling of these GOT relocations just below.  */
              if (h != NULL
                  && h->dynindx == -1
                  && !h->forced_local
                  && h->root.type != bfd_link_hash_undefweak
+                 && !eh->has_old_style_got_reloc
                  && (h->got.offset & 1) == 0
                  && bfd_link_pic (info))
                {
This page took 0.026071 seconds and 4 git commands to generate.