Makefile.in: Move ravenscar-thread.c from SFILES to ALLDEPFILES.
[deliverable/binutils-gdb.git] / bfd / elfxx-sparc.c
index bc36920db947e73b5de9fbd42cca7c31fcd9f3d0..9811d17b06cc43705903763018d3d02ac7dd94bd 100644 (file)
@@ -1,5 +1,6 @@
 /* SPARC-specific support for ELF
-   Copyright 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+   Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -52,7 +53,7 @@
 
 static bfd_reloc_status_type
 init_insn_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                PTR data, asection *input_section, bfd *output_bfd,
+                void * data, asection *input_section, bfd *output_bfd,
                 bfd_vma *prelocation, bfd_vma *pinsn)
 {
   bfd_vma relocation;
@@ -96,7 +97,7 @@ static bfd_reloc_status_type
 sparc_elf_notsup_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                        arelent *reloc_entry ATTRIBUTE_UNUSED,
                        asymbol *symbol ATTRIBUTE_UNUSED,
-                       PTR data ATTRIBUTE_UNUSED,
+                       void * data ATTRIBUTE_UNUSED,
                        asection *input_section ATTRIBUTE_UNUSED,
                        bfd *output_bfd ATTRIBUTE_UNUSED,
                        char **error_message ATTRIBUTE_UNUSED)
@@ -108,7 +109,7 @@ sparc_elf_notsup_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 
 static bfd_reloc_status_type
 sparc_elf_wdisp16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                        PTR data, asection *input_section, bfd *output_bfd,
+                        void * data, asection *input_section, bfd *output_bfd,
                         char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_vma relocation;
@@ -131,11 +132,39 @@ sparc_elf_wdisp16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
     return bfd_reloc_ok;
 }
 
+/* Handle the WDISP10 reloc.  */
+
+static bfd_reloc_status_type
+sparc_elf_wdisp10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                        void * data, asection *input_section, bfd *output_bfd,
+                        char **error_message ATTRIBUTE_UNUSED)
+{
+  bfd_vma relocation;
+  bfd_vma insn;
+  bfd_reloc_status_type status;
+
+  status = init_insn_reloc (abfd, reloc_entry, symbol, data,
+                           input_section, output_bfd, &relocation, &insn);
+  if (status != bfd_reloc_other)
+    return status;
+
+  insn &= ~ (bfd_vma) 0x181fe0;
+  insn |= (((relocation >> 2) & 0x300) << 11)
+         | (((relocation >> 2) & 0xff) << 5);
+  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+
+  if ((bfd_signed_vma) relocation < - 0x1000
+      || (bfd_signed_vma) relocation > 0xfff)
+    return bfd_reloc_overflow;
+  else
+    return bfd_reloc_ok;
+}
+
 /* Handle the HIX22 reloc.  */
 
 static bfd_reloc_status_type
 sparc_elf_hix22_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                      PTR data, asection *input_section, bfd *output_bfd,
+                      void * data, asection *input_section, bfd *output_bfd,
                       char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_vma relocation;
@@ -161,7 +190,7 @@ sparc_elf_hix22_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 sparc_elf_lox10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                      PTR data, asection *input_section, bfd *output_bfd,
+                      void * data, asection *input_section, bfd *output_bfd,
                       char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_vma relocation;
@@ -266,6 +295,10 @@ static reloc_howto_type _bfd_sparc_elf_howto_table[] =
   HOWTO(R_SPARC_GOTDATA_OP_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,"R_SPARC_GOTDATA_OP_HIX22",FALSE,0,0x003fffff, FALSE),
   HOWTO(R_SPARC_GOTDATA_OP_LOX10,0,2,0,FALSE,0,complain_overflow_dont,  sparc_elf_lox10_reloc,  "R_SPARC_GOTDATA_OP_LOX10",FALSE,0,0x000003ff, FALSE),
   HOWTO(R_SPARC_GOTDATA_OP,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_GOTDATA_OP",FALSE,0,0x00000000,TRUE),
+  HOWTO(R_SPARC_H34,12,2,22,FALSE,0,complain_overflow_unsigned,bfd_elf_generic_reloc,"R_SPARC_H34",FALSE,0,0x003fffff,FALSE),
+  HOWTO(R_SPARC_SIZE32,0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_SIZE32",FALSE,0,0xffffffff,TRUE),
+  HOWTO(R_SPARC_SIZE64,0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_SIZE64",FALSE,0,MINUS_ONE, TRUE),
+  HOWTO(R_SPARC_WDISP10,2,2,10,TRUE, 0,complain_overflow_signed,sparc_elf_wdisp10_reloc,"R_SPARC_WDISP10",FALSE,0,0x00000000,TRUE),
 };
 static reloc_howto_type sparc_jmp_irel_howto =
   HOWTO(R_SPARC_JMP_IREL,  0,0,00,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_JMP_IREL",FALSE,0,0x00000000,TRUE);
@@ -278,109 +311,263 @@ static reloc_howto_type sparc_vtentry_howto =
 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);
 
-struct elf_reloc_map {
-  bfd_reloc_code_real_type bfd_reloc_val;
-  unsigned char elf_reloc_val;
-};
-
-static const struct elf_reloc_map sparc_reloc_map[] =
-{
-  { BFD_RELOC_NONE, R_SPARC_NONE, },
-  { BFD_RELOC_16, R_SPARC_16, },
-  { BFD_RELOC_16_PCREL, R_SPARC_DISP16 },
-  { BFD_RELOC_8, R_SPARC_8 },
-  { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
-  { BFD_RELOC_CTOR, R_SPARC_64 },
-  { BFD_RELOC_32, R_SPARC_32 },
-  { BFD_RELOC_32_PCREL, R_SPARC_DISP32 },
-  { BFD_RELOC_HI22, R_SPARC_HI22 },
-  { BFD_RELOC_LO10, R_SPARC_LO10, },
-  { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
-  { BFD_RELOC_64_PCREL, R_SPARC_DISP64 },
-  { BFD_RELOC_SPARC22, R_SPARC_22 },
-  { BFD_RELOC_SPARC13, R_SPARC_13 },
-  { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
-  { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 },
-  { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 },
-  { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 },
-  { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 },
-  { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 },
-  { BFD_RELOC_SPARC_COPY, R_SPARC_COPY },
-  { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT },
-  { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
-  { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
-  { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
-  { BFD_RELOC_SPARC_UA16, R_SPARC_UA16 },
-  { BFD_RELOC_SPARC_UA32, R_SPARC_UA32 },
-  { BFD_RELOC_SPARC_UA64, R_SPARC_UA64 },
-  { BFD_RELOC_SPARC_10, R_SPARC_10 },
-  { BFD_RELOC_SPARC_11, R_SPARC_11 },
-  { BFD_RELOC_SPARC_64, R_SPARC_64 },
-  { BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10 },
-  { BFD_RELOC_SPARC_HH22, R_SPARC_HH22 },
-  { BFD_RELOC_SPARC_HM10, R_SPARC_HM10 },
-  { BFD_RELOC_SPARC_LM22, R_SPARC_LM22 },
-  { BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22 },
-  { BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10 },
-  { BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22 },
-  { BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16 },
-  { BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19 },
-  { BFD_RELOC_SPARC_7, R_SPARC_7 },
-  { BFD_RELOC_SPARC_5, R_SPARC_5 },
-  { BFD_RELOC_SPARC_6, R_SPARC_6 },
-  { BFD_RELOC_SPARC_DISP64, R_SPARC_DISP64 },
-  { BFD_RELOC_SPARC_TLS_GD_HI22, R_SPARC_TLS_GD_HI22 },
-  { BFD_RELOC_SPARC_TLS_GD_LO10, R_SPARC_TLS_GD_LO10 },
-  { BFD_RELOC_SPARC_TLS_GD_ADD, R_SPARC_TLS_GD_ADD },
-  { BFD_RELOC_SPARC_TLS_GD_CALL, R_SPARC_TLS_GD_CALL },
-  { BFD_RELOC_SPARC_TLS_LDM_HI22, R_SPARC_TLS_LDM_HI22 },
-  { BFD_RELOC_SPARC_TLS_LDM_LO10, R_SPARC_TLS_LDM_LO10 },
-  { BFD_RELOC_SPARC_TLS_LDM_ADD, R_SPARC_TLS_LDM_ADD },
-  { BFD_RELOC_SPARC_TLS_LDM_CALL, R_SPARC_TLS_LDM_CALL },
-  { BFD_RELOC_SPARC_TLS_LDO_HIX22, R_SPARC_TLS_LDO_HIX22 },
-  { BFD_RELOC_SPARC_TLS_LDO_LOX10, R_SPARC_TLS_LDO_LOX10 },
-  { BFD_RELOC_SPARC_TLS_LDO_ADD, R_SPARC_TLS_LDO_ADD },
-  { BFD_RELOC_SPARC_TLS_IE_HI22, R_SPARC_TLS_IE_HI22 },
-  { BFD_RELOC_SPARC_TLS_IE_LO10, R_SPARC_TLS_IE_LO10 },
-  { BFD_RELOC_SPARC_TLS_IE_LD, R_SPARC_TLS_IE_LD },
-  { BFD_RELOC_SPARC_TLS_IE_LDX, R_SPARC_TLS_IE_LDX },
-  { BFD_RELOC_SPARC_TLS_IE_ADD, R_SPARC_TLS_IE_ADD },
-  { BFD_RELOC_SPARC_TLS_LE_HIX22, R_SPARC_TLS_LE_HIX22 },
-  { BFD_RELOC_SPARC_TLS_LE_LOX10, R_SPARC_TLS_LE_LOX10 },
-  { BFD_RELOC_SPARC_TLS_DTPMOD32, R_SPARC_TLS_DTPMOD32 },
-  { BFD_RELOC_SPARC_TLS_DTPMOD64, R_SPARC_TLS_DTPMOD64 },
-  { BFD_RELOC_SPARC_TLS_DTPOFF32, R_SPARC_TLS_DTPOFF32 },
-  { BFD_RELOC_SPARC_TLS_DTPOFF64, R_SPARC_TLS_DTPOFF64 },
-  { BFD_RELOC_SPARC_TLS_TPOFF32, R_SPARC_TLS_TPOFF32 },
-  { BFD_RELOC_SPARC_TLS_TPOFF64, R_SPARC_TLS_TPOFF64 },
-  { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
-  { BFD_RELOC_SPARC_PLT64, R_SPARC_PLT64 },
-  { BFD_RELOC_SPARC_HIX22, R_SPARC_HIX22 },
-  { BFD_RELOC_SPARC_LOX10, R_SPARC_LOX10 },
-  { BFD_RELOC_SPARC_H44, R_SPARC_H44 },
-  { BFD_RELOC_SPARC_M44, R_SPARC_M44 },
-  { BFD_RELOC_SPARC_L44, R_SPARC_L44 },
-  { BFD_RELOC_SPARC_GOTDATA_HIX22, R_SPARC_GOTDATA_HIX22 },
-  { BFD_RELOC_SPARC_GOTDATA_LOX10, R_SPARC_GOTDATA_LOX10 },
-  { BFD_RELOC_SPARC_GOTDATA_OP_HIX22, R_SPARC_GOTDATA_OP_HIX22 },
-  { BFD_RELOC_SPARC_GOTDATA_OP_LOX10, R_SPARC_GOTDATA_OP_LOX10 },
-  { BFD_RELOC_SPARC_GOTDATA_OP, R_SPARC_GOTDATA_OP },
-  { BFD_RELOC_SPARC_REGISTER, R_SPARC_REGISTER },
-  { BFD_RELOC_SPARC_JMP_IREL, R_SPARC_JMP_IREL },
-  { BFD_RELOC_SPARC_IRELATIVE, R_SPARC_IRELATIVE },
-  { BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT },
-  { BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY },
-  { BFD_RELOC_SPARC_REV32, R_SPARC_REV32 },
-};
-
 reloc_howto_type *
 _bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
                                  bfd_reloc_code_real_type code)
 {
-  unsigned int i;
-
+  /* We explicitly handle each relocation type in the switch
+     instead of using a lookup table for efficiency.  */
   switch (code)
     {
+    case BFD_RELOC_NONE:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_NONE];
+
+    case BFD_RELOC_8:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_8];
+
+    case BFD_RELOC_16:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_16];
+
+    case BFD_RELOC_32:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_32];
+
+    case BFD_RELOC_8_PCREL:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_DISP8];
+
+    case BFD_RELOC_16_PCREL:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_DISP16];
+
+    case BFD_RELOC_32_PCREL:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_DISP32];
+
+    case BFD_RELOC_32_PCREL_S2:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_WDISP30];
+
+    case BFD_RELOC_SPARC_WDISP22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_WDISP22];
+
+    case BFD_RELOC_HI22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_HI22];
+
+    case BFD_RELOC_SPARC22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_22];
+
+    case BFD_RELOC_SPARC13:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_13];
+
+    case BFD_RELOC_LO10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_LO10];
+
+    case BFD_RELOC_SPARC_GOT10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GOT10];
+
+    case BFD_RELOC_SPARC_GOT13:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GOT13];
+
+    case BFD_RELOC_SPARC_GOT22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GOT22];
+
+    case BFD_RELOC_SPARC_PC10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_PC10];
+
+    case BFD_RELOC_SPARC_PC22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_PC22];
+
+    case BFD_RELOC_SPARC_WPLT30:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_WPLT30];
+
+    case BFD_RELOC_SPARC_COPY:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_COPY];
+
+    case BFD_RELOC_SPARC_GLOB_DAT:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GLOB_DAT];
+
+    case BFD_RELOC_SPARC_JMP_SLOT:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_JMP_SLOT];
+
+    case BFD_RELOC_SPARC_RELATIVE:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_RELATIVE];
+
+    case BFD_RELOC_SPARC_UA32:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_UA32];
+
+    case BFD_RELOC_SPARC_PLT32:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_PLT32];
+
+    case BFD_RELOC_SPARC_10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_10];
+
+    case BFD_RELOC_SPARC_11:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_11];
+
+    case BFD_RELOC_SPARC_64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_64];
+
+    case BFD_RELOC_SPARC_OLO10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_OLO10];
+
+    case BFD_RELOC_SPARC_HH22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_HH22];
+
+    case BFD_RELOC_SPARC_HM10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_HM10];
+
+    case BFD_RELOC_SPARC_LM22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_LM22];
+
+    case BFD_RELOC_SPARC_PC_HH22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_PC_HH22];
+
+    case BFD_RELOC_SPARC_PC_HM10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_PC_HM10];
+
+    case BFD_RELOC_SPARC_PC_LM22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_PC_LM22];
+
+    case BFD_RELOC_SPARC_WDISP16:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_WDISP16];
+
+    case BFD_RELOC_SPARC_WDISP19:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_WDISP19];
+
+    case BFD_RELOC_SPARC_7:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_7];
+
+    case BFD_RELOC_SPARC_5:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_5];
+
+    case BFD_RELOC_SPARC_6:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_6];
+
+    case BFD_RELOC_SPARC_DISP64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_DISP64];
+
+    case BFD_RELOC_SPARC_PLT64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_PLT64];
+
+    case BFD_RELOC_SPARC_HIX22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_HIX22];
+
+    case BFD_RELOC_SPARC_LOX10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_LOX10];
+
+    case BFD_RELOC_SPARC_H44:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_H44];
+
+    case BFD_RELOC_SPARC_M44:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_M44];
+
+    case BFD_RELOC_SPARC_L44:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_L44];
+
+    case BFD_RELOC_SPARC_REGISTER:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_REGISTER];
+
+    case BFD_RELOC_SPARC_UA64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_UA64];
+
+    case BFD_RELOC_SPARC_UA16:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_UA16];
+
+    case BFD_RELOC_SPARC_TLS_GD_HI22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_GD_HI22];
+
+    case BFD_RELOC_SPARC_TLS_GD_LO10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_GD_LO10];
+
+    case BFD_RELOC_SPARC_TLS_GD_ADD:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_GD_ADD];
+
+    case BFD_RELOC_SPARC_TLS_GD_CALL:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_GD_CALL];
+
+    case BFD_RELOC_SPARC_TLS_LDM_HI22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LDM_HI22];
+
+    case BFD_RELOC_SPARC_TLS_LDM_LO10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LDM_LO10];
+
+    case BFD_RELOC_SPARC_TLS_LDM_ADD:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LDM_ADD];
+
+    case BFD_RELOC_SPARC_TLS_LDM_CALL:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LDM_CALL];
+
+    case BFD_RELOC_SPARC_TLS_LDO_HIX22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LDO_HIX22];
+
+    case BFD_RELOC_SPARC_TLS_LDO_LOX10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LDO_LOX10];
+
+    case BFD_RELOC_SPARC_TLS_LDO_ADD:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LDO_ADD];
+
+    case BFD_RELOC_SPARC_TLS_IE_HI22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_IE_HI22];
+
+    case BFD_RELOC_SPARC_TLS_IE_LO10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_IE_LO10];
+
+    case BFD_RELOC_SPARC_TLS_IE_LD:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_IE_LD];
+
+    case BFD_RELOC_SPARC_TLS_IE_LDX:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_IE_LDX];
+
+    case BFD_RELOC_SPARC_TLS_IE_ADD:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_IE_ADD];
+
+    case BFD_RELOC_SPARC_TLS_LE_HIX22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LE_HIX22];
+
+    case BFD_RELOC_SPARC_TLS_LE_LOX10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_LE_LOX10];
+
+    case BFD_RELOC_SPARC_TLS_DTPMOD32:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_DTPMOD32];
+
+    case BFD_RELOC_SPARC_TLS_DTPMOD64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_DTPMOD64];
+
+    case BFD_RELOC_SPARC_TLS_DTPOFF32:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_DTPOFF32];
+
+    case BFD_RELOC_SPARC_TLS_DTPOFF64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_DTPOFF64];
+
+    case BFD_RELOC_SPARC_TLS_TPOFF32:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_TPOFF32];
+
+    case BFD_RELOC_SPARC_TLS_TPOFF64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_TLS_TPOFF64];
+
+    case BFD_RELOC_SPARC_GOTDATA_HIX22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GOTDATA_HIX22];
+
+    case BFD_RELOC_SPARC_GOTDATA_LOX10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GOTDATA_LOX10];
+
+    case BFD_RELOC_SPARC_GOTDATA_OP_HIX22:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GOTDATA_OP_HIX22];
+
+    case BFD_RELOC_SPARC_GOTDATA_OP_LOX10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GOTDATA_OP_LOX10];
+
+    case BFD_RELOC_SPARC_GOTDATA_OP:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_GOTDATA_OP];
+
+    case BFD_RELOC_SPARC_H34:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_H34];
+
+    case BFD_RELOC_SPARC_SIZE32:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_SIZE32];
+
+    case BFD_RELOC_SPARC_SIZE64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_SIZE64];
+
+    case BFD_RELOC_SPARC_WDISP10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_WDISP10];
+
     case BFD_RELOC_SPARC_JMP_IREL:
       return &sparc_jmp_irel_howto;
 
@@ -397,14 +584,7 @@ _bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       return &sparc_rev32_howto;
 
     default:
-      for (i = 0;
-          i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map);
-          i++)
-       {
-         if (sparc_reloc_map[i].bfd_reloc_val == code)
-           return (_bfd_sparc_elf_howto_table
-                   + (int) sparc_reloc_map[i].elf_reloc_val);
-       }
+      break;
     }
     bfd_set_error (bfd_error_bad_value);
     return NULL;
@@ -1027,9 +1207,9 @@ _bfd_sparc_elf_create_dynamic_sections (bfd *dynobj,
   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
     return FALSE;
 
-  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
+  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
   if (!info->shared)
-    htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
 
   if (htab->is_vxworks)
     {
@@ -1191,7 +1371,6 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   struct _bfd_sparc_elf_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
-  bfd_vma *local_got_offsets;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
@@ -1205,12 +1384,11 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   BFD_ASSERT (htab != NULL);
   symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
-  local_got_offsets = elf_local_got_offsets (abfd);
 
   sreloc = NULL;
 
   if (ABI_64_P (abfd))
-    num_relocs = NUM_SHDR_ENTRIES (& elf_section_data (sec)->rel_hdr);
+    num_relocs = NUM_SHDR_ENTRIES (_bfd_elf_single_rel_hdr (sec));
   else
     num_relocs = sec->reloc_count;
 
@@ -1277,7 +1455,10 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       if (h && h->type == STT_GNU_IFUNC)
        {
          if (h->def_regular)
-           h->plt.refcount += 1;
+           {
+             h->ref_regular = 1;
+             h->plt.refcount += 1;
+           }
        }
 
       /* Compatibility with old R_SPARC_REV32 reloc conflicting
@@ -1345,8 +1526,6 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              case R_SPARC_GOT10:
              case R_SPARC_GOT13:
              case R_SPARC_GOT22:
-             case R_SPARC_GOTDATA_HIX22:
-             case R_SPARC_GOTDATA_LOX10:
              case R_SPARC_GOTDATA_OP_HIX22:
              case R_SPARC_GOTDATA_OP_LOX10:
                tls_type = GOT_NORMAL;
@@ -1386,7 +1565,16 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                    _bfd_sparc_elf_local_got_tls_type (abfd)
                      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
                  }
-               local_got_refcounts[r_symndx] += 1;
+               switch (r_type)
+                 {
+                 case R_SPARC_GOTDATA_OP_HIX22:
+                 case R_SPARC_GOTDATA_OP_LOX10:
+                   break;
+
+                 default:
+                   local_got_refcounts[r_symndx] += 1;
+                   break;
+                 }
                old_tls_type = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx];
              }
 
@@ -1512,6 +1700,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_SPARC_WDISP22:
        case R_SPARC_WDISP19:
        case R_SPARC_WDISP16:
+       case R_SPARC_WDISP10:
        case R_SPARC_8:
        case R_SPARC_16:
        case R_SPARC_32:
@@ -1536,6 +1725,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_SPARC_H44:
        case R_SPARC_M44:
        case R_SPARC_L44:
+       case R_SPARC_H34:
        case R_SPARC_UA64:
          if (h != NULL)
            h->non_got_ref = 1;
@@ -1686,6 +1876,20 @@ _bfd_sparc_elf_gc_mark_hook (asection *sec,
   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
+static Elf_Internal_Rela *
+sparc_elf_find_reloc_at_ofs (Elf_Internal_Rela *rel,
+                            Elf_Internal_Rela *relend,
+                            bfd_vma offset)
+{
+  while (rel < relend)
+    {
+      if (rel->r_offset == offset)
+       return rel;
+      rel++;
+    }
+  return NULL;
+}
+
 /* Update the got entry reference counts for the section being removed.  */
 bfd_boolean
 _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
@@ -1766,8 +1970,17 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
            }
          else
            {
-             if (local_got_refcounts[r_symndx] > 0)
-               local_got_refcounts[r_symndx]--;
+             switch (r_type)
+               {
+               case R_SPARC_GOTDATA_OP_HIX22:
+               case R_SPARC_GOTDATA_OP_LOX10:
+                 break;
+
+               default:
+                 if (local_got_refcounts[r_symndx] > 0)
+                   local_got_refcounts[r_symndx]--;
+                 break;
+               }
            }
          break;
 
@@ -1789,6 +2002,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
        case R_SPARC_WDISP22:
        case R_SPARC_WDISP19:
        case R_SPARC_WDISP16:
+       case R_SPARC_WDISP10:
        case R_SPARC_8:
        case R_SPARC_16:
        case R_SPARC_32:
@@ -1814,6 +2028,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
        case R_SPARC_H44:
        case R_SPARC_M44:
        case R_SPARC_L44:
+       case R_SPARC_H34:
        case R_SPARC_UA64:
          if (info->shared)
            break;
@@ -1947,13 +2162,6 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       return TRUE;
     }
 
-  if (h->size == 0)
-    {
-      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
-                            h->root.root.string);
-      return TRUE;
-    }
-
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
      an entry for this symbol in the .dynsym section.  The dynamic
@@ -1968,7 +2176,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      to copy the initial value out of the dynamic object and into the
      runtime process image.  We need to remember the offset into the
      .rel.bss section we are going to use.  */
-  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
       htab->srelbss->size += SPARC_ELF_RELA_BYTES (htab);
       h->needs_copy = 1;
@@ -1983,7 +2191,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
    dynamic relocs.  */
 
 static bfd_boolean
-allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
+allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 {
   struct bfd_link_info *info;
   struct _bfd_sparc_elf_link_hash_table *htab;
@@ -1993,12 +2201,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    /* When warning symbols are created, they **replace** the "real"
-       entry in the hash table, thus we never get to see the real
-       symbol in a hash traversal.  So look at it now.  */
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   info = (struct bfd_link_info *) inf;
   htab = _bfd_sparc_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
@@ -2006,7 +2208,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
   if ((htab->elf.dynamic_sections_created
        && h->plt.refcount > 0)
       || (h->type == STT_GNU_IFUNC
-         && h->def_regular))
+         && h->def_regular
+         && h->ref_regular))
     {
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
@@ -2018,7 +2221,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
        }
 
       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h)
-         || h->type == STT_GNU_IFUNC)
+         || (h->type == STT_GNU_IFUNC
+             && h->def_regular))
        {
          asection *s = htab->elf.splt;
 
@@ -2267,14 +2471,11 @@ allocate_local_dynrelocs (void **slot, void *inf)
 /* Find any dynamic relocs that apply to read-only sections.  */
 
 static bfd_boolean
-readonly_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
+readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 {
   struct _bfd_sparc_elf_link_hash_entry *eh;
   struct _bfd_sparc_elf_dyn_relocs *p;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   eh = (struct _bfd_sparc_elf_link_hash_entry *) h;
   for (p = eh->dyn_relocs; p != NULL; p = p->next)
     {
@@ -2331,7 +2532,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
       /* Set the contents of the .interp section to the interpreter.  */
       if (info->executable)
        {
-         s = bfd_get_section_by_name (dynobj, ".interp");
+         s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
          s->size = htab->dynamic_interpreter_size;
          s->contents = (unsigned char *) htab->dynamic_interpreter;
@@ -2426,7 +2627,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
 
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
-  elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
+  elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
 
   /* Allocate .plt and .got entries, and space for local symbols.  */
   htab_traverse (htab->loc_hash_table, allocate_local_dynrelocs, info);
@@ -2541,8 +2742,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
       /* If any dynamic relocs apply to a read-only section,
         then we need a DT_TEXTREL entry.  */
       if ((info->flags & DF_TEXTREL) == 0)
-       elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
-                               (PTR) info);
+       elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info);
 
       if (info->flags & DF_TEXTREL)
        {
@@ -2589,6 +2789,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
                entry->isym.st_info = ELF_ST_INFO (app_regs [reg].bind,
                                                   STT_REGISTER);
                entry->isym.st_shndx = app_regs [reg].shndx;
+               entry->isym.st_target_internal = 0;
                entry->next = NULL;
                entry->input_bfd = output_bfd;
                entry->input_indx = -1;
@@ -2665,11 +2866,31 @@ static bfd_vma
 tpoff (struct bfd_link_info *info, bfd_vma address)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
+  const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd);
+  bfd_vma static_tls_size;
 
   /* If tls_sec is NULL, we should have signalled an error already.  */
   if (htab->tls_sec == NULL)
     return 0;
-  return address - htab->tls_size - htab->tls_sec->vma;
+
+  /* Consider special static TLS alignment requirements.  */
+  static_tls_size = BFD_ALIGN (htab->tls_size, bed->static_tls_alignment);
+  return address - static_tls_size - htab->tls_sec->vma;
+}
+
+/* Return the relocation value for a %gdop relocation.  */
+
+static bfd_vma
+gdopoff (struct bfd_link_info *info, bfd_vma address)
+{
+  struct elf_link_hash_table *htab = elf_hash_table (info);
+  bfd_vma got_base;
+
+  got_base = (htab->hgot->root.u.def.value
+             + htab->hgot->root.u.def.section->output_offset
+             + htab->hgot->root.u.def.section->output_section->vma);
+
+  return address - got_base;
 }
 
 /* Relocate a SPARC ELF section.  */
@@ -2715,7 +2936,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
 
   rel = relocs;
   if (ABI_64_P (output_bfd))
-    num_relocs = NUM_SHDR_ENTRIES (& elf_section_data (input_section)->rel_hdr);
+    num_relocs = NUM_SHDR_ENTRIES (_bfd_elf_single_rel_hdr (input_section));
   else
     num_relocs = input_section->reloc_count;
   relend = relocs + num_relocs;
@@ -2789,17 +3010,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
            }
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce
-            sections, or sections discarded by a linker script, we
-            just want the section contents zeroed.  Avoid any
-            special processing.  */
-         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
        continue;
@@ -2821,10 +3034,17 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
 
          switch (r_type)
            {
-           case R_SPARC_GOTDATA_HIX22:
-           case R_SPARC_GOTDATA_LOX10:
+           case R_SPARC_GOTDATA_OP:
+             continue;
+
            case R_SPARC_GOTDATA_OP_HIX22:
            case R_SPARC_GOTDATA_OP_LOX10:
+             r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22
+                       ? R_SPARC_GOT22
+                       : R_SPARC_GOT10);
+             howto = _bfd_sparc_elf_howto_table + r_type;
+             /* Fall through.  */
+
            case R_SPARC_GOT10:
            case R_SPARC_GOT13:
            case R_SPARC_GOT22:
@@ -2911,19 +3131,37 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
 
       switch (r_type)
        {
-       case R_SPARC_GOTDATA_HIX22:
-       case R_SPARC_GOTDATA_LOX10:
        case R_SPARC_GOTDATA_OP_HIX22:
        case R_SPARC_GOTDATA_OP_LOX10:
-         /* We don't support these code transformation optimizations
-            yet, so just leave the sequence alone and treat as
-            GOT22/GOT10.  */
-         if (r_type == R_SPARC_GOTDATA_HIX22
-             || r_type == R_SPARC_GOTDATA_OP_HIX22)
-           r_type = R_SPARC_GOT22;
+         if (SYMBOL_REFERENCES_LOCAL (info, h))
+           r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22
+                     ? R_SPARC_GOTDATA_HIX22
+                     : R_SPARC_GOTDATA_LOX10);
          else
-           r_type = R_SPARC_GOT10;
-         /* Fall through. */
+           r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22
+                     ? R_SPARC_GOT22
+                     : R_SPARC_GOT10);
+         howto = _bfd_sparc_elf_howto_table + r_type;
+         break;
+
+       case R_SPARC_GOTDATA_OP:
+         if (SYMBOL_REFERENCES_LOCAL (info, h))
+           {
+             bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+             /* {ld,ldx} [%rs1 + %rs2], %rd --> add %rs1, %rs2, %rd */
+             relocation = 0x80000000 | (insn & 0x3e07c01f);
+             bfd_put_32 (output_bfd, relocation, contents + rel->r_offset);
+           }
+         continue;
+       }
+
+      switch (r_type)
+       {
+       case R_SPARC_GOTDATA_HIX22:
+       case R_SPARC_GOTDATA_LOX10:
+         relocation = gdopoff (info, relocation);
+         break;
 
        case R_SPARC_GOT10:
        case R_SPARC_GOT13:
@@ -3085,6 +3323,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
        case R_SPARC_WDISP22:
        case R_SPARC_WDISP19:
        case R_SPARC_WDISP16:
+       case R_SPARC_WDISP10:
        case R_SPARC_8:
        case R_SPARC_16:
        case R_SPARC_32:
@@ -3109,6 +3348,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
        case R_SPARC_H44:
        case R_SPARC_M44:
        case R_SPARC_L44:
+       case R_SPARC_H34:
        case R_SPARC_UA64:
        r_sparc_plt32:
          if ((input_section->flags & SEC_ALLOC) == 0
@@ -3446,7 +3686,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
          if (info->shared)
            {
              Elf_Internal_Rela outrel;
-             bfd_boolean skip, relocate = FALSE;
+             bfd_boolean skip;
 
              BFD_ASSERT (sreloc != NULL);
              skip = FALSE;
@@ -3456,7 +3696,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
              if (outrel.r_offset == (bfd_vma) -1)
                skip = TRUE;
              else if (outrel.r_offset == (bfd_vma) -2)
-               skip = TRUE, relocate = TRUE;
+               skip = TRUE;
              outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);
              if (skip)
@@ -3492,6 +3732,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
          if (! info->shared
              || (r_type == R_SPARC_TLS_GD_CALL && tls_type == GOT_TLS_IE))
            {
+             Elf_Internal_Rela *rel2;
              bfd_vma insn;
 
              if (!info->shared && (h == NULL || h->dynindx == -1))
@@ -3527,7 +3768,26 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
                  continue;
                }
 
-             bfd_put_32 (output_bfd, 0x9001c008, contents + rel->r_offset);
+             /* We cannot just overwrite the delay slot instruction,
+                as it might be what puts the %o0 argument to
+                __tls_get_addr into place.  So we have to transpose
+                the delay slot with the add we patch in.  */
+             insn = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+             bfd_put_32 (output_bfd, insn,
+                         contents + rel->r_offset);
+             bfd_put_32 (output_bfd, 0x9001c008,
+                         contents + rel->r_offset + 4);
+
+             rel2 = rel;
+             while ((rel2 = sparc_elf_find_reloc_at_ofs (rel2 + 1, relend,
+                                                         rel->r_offset + 4))
+                    != NULL)
+               {
+                 /* If the instruction we moved has a relocation attached to
+                    it, adjust the offset so that it will apply to the correct
+                    instruction.  */
+                 rel2->r_offset -= 4;
+               }
              continue;
            }
 
@@ -3576,11 +3836,6 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
            }
          continue;
 
-       case R_SPARC_GOTDATA_OP:
-         /* We don't support gotdata code transformation optimizations
-            yet, so simply leave the sequence as-is.  */
-         continue;
-
        case R_SPARC_TLS_IE_LD:
        case R_SPARC_TLS_IE_LDX:
          if (! info->shared && (h == NULL || h->dynindx == -1))
@@ -3615,7 +3870,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
         not process them.  */
       if (unresolved_reloc
          && !((input_section->flags & SEC_DEBUGGING) != 0
-              && h->def_dynamic))
+              && h->def_dynamic)
+         && _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'"),
           input_bfd,
@@ -3658,6 +3915,25 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
                | ((relocation >> 2) & 0x3fff));
          bfd_put_32 (input_bfd, x, contents + rel->r_offset);
 
+         r = bfd_check_overflow (howto->complain_on_overflow,
+                                 howto->bitsize, howto->rightshift,
+                                 bfd_arch_bits_per_address (input_bfd),
+                                 relocation);
+       }
+      else if (r_type == R_SPARC_WDISP10)
+       {
+         bfd_vma x;
+
+         relocation += rel->r_addend;
+         relocation -= (input_section->output_section->vma
+                        + input_section->output_offset);
+         relocation -= rel->r_offset;
+
+         x = bfd_get_32 (input_bfd, contents + rel->r_offset);
+         x |= ((((relocation >> 2) & 0x300) << 11)
+               | (((relocation >> 2) & 0xff) << 5));
+         bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+
          r = bfd_check_overflow (howto->complain_on_overflow,
                                  howto->bitsize, howto->rightshift,
                                  bfd_arch_bits_per_address (input_bfd),
@@ -3704,12 +3980,15 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
 
          r = bfd_reloc_ok;
        }
-      else if (r_type == R_SPARC_HIX22)
+      else if (r_type == R_SPARC_HIX22
+              || r_type == R_SPARC_GOTDATA_HIX22)
        {
          bfd_vma x;
 
          relocation += rel->r_addend;
-         relocation = relocation ^ MINUS_ONE;
+         if (r_type == R_SPARC_HIX22
+             || (bfd_signed_vma) relocation < 0)
+           relocation = relocation ^ MINUS_ONE;
 
          x = bfd_get_32 (input_bfd, contents + rel->r_offset);
          x = (x & ~(bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff);
@@ -3720,12 +3999,17 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
                                  bfd_arch_bits_per_address (input_bfd),
                                  relocation);
        }
-      else if (r_type == R_SPARC_LOX10)
+      else if (r_type == R_SPARC_LOX10
+              || r_type == R_SPARC_GOTDATA_LOX10)
        {
          bfd_vma x;
 
          relocation += rel->r_addend;
-         relocation = (relocation & 0x3ff) | 0x1c00;
+         if (r_type == R_SPARC_LOX10
+             || (bfd_signed_vma) relocation < 0)
+           relocation = (relocation & 0x3ff) | 0x1c00;
+         else
+           relocation = (relocation & 0x3ff);
 
          x = bfd_get_32 (input_bfd, contents + rel->r_offset);
          x = (x & ~(bfd_vma) 0x1fff) | relocation;
@@ -3846,7 +4130,9 @@ do_relocation:
                   We don't, but this breaks stabs debugging info, whose
                   relocations are only 32-bits wide.  Ignore overflows in
                   this case and also for discarded entries.  */
-               if ((r_type == R_SPARC_32 || r_type == R_SPARC_DISP32)
+               if ((r_type == R_SPARC_32
+                    || r_type == R_SPARC_UA32
+                    || r_type == R_SPARC_DISP32)
                    && (((input_section->flags & SEC_DEBUGGING) != 0
                         && strcmp (bfd_section_name (input_bfd,
                                                      input_section),
@@ -4209,8 +4495,8 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
       /* This symbols needs a copy reloc.  Set it up.  */
       BFD_ASSERT (h->dynindx != -1);
 
-      s = bfd_get_section_by_name (h->root.u.def.section->owner,
-                                  ".rela.bss");
+      s = bfd_get_linker_section (h->root.u.def.section->owner,
+                                 ".rela.bss");
       BFD_ASSERT (s != NULL);
 
       rela.r_offset = (h->root.u.def.value
@@ -4225,7 +4511,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
      _GLOBAL_OFFSET_TABLE_ is not absolute: it is relative to the
      ".got" section.  Likewise _PROCEDURE_LINKAGE_TABLE_ and ".plt".  */
   if (sym != NULL
-      && (strcmp (h->root.root.string, "_DYNAMIC") == 0
+      && (h == htab->elf.hdynamic
          || (!htab->is_vxworks
              && (h == htab->elf.hgot || h == htab->elf.hplt))))
     sym->st_shndx = SHN_ABS;
@@ -4449,13 +4735,13 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i
   BFD_ASSERT (htab != NULL);
   dynobj = htab->elf.dynobj;
 
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       asection *splt;
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
+      splt = htab->elf.splt;
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       if (!sparc_finish_dyn (output_bfd, info, dynobj, sdyn, splt))
@@ -4567,3 +4853,38 @@ _bfd_sparc_elf_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel)
   else
     return rel->address;
 }
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+bfd_boolean
+_bfd_sparc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+  obj_attribute *in_attr, *in_attrs;
+  obj_attribute *out_attr, *out_attrs;
+
+  if (!elf_known_obj_attributes_proc (obfd)[0].i)
+    {
+      /* This is the first object.  Copy the attributes.  */
+      _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
+      /* Use the Tag_null value to indicate the attributes have been
+        initialized.  */
+      elf_known_obj_attributes_proc (obfd)[0].i = 1;
+
+      return TRUE;
+    }
+
+  in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+  out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
+
+  in_attr = &in_attrs[Tag_GNU_Sparc_HWCAPS];
+  out_attr = &out_attrs[Tag_GNU_Sparc_HWCAPS];
+
+  out_attr->i |= in_attr->i;
+
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  _bfd_elf_merge_object_attributes (ibfd, obfd);
+
+  return TRUE;
+}
This page took 0.057794 seconds and 4 git commands to generate.