* elf64-sparc.c (sparc64_elf_object_p): bfd_mach_sparc64 renamed to
authorDavid Edelsohn <dje.gcc@gmail.com>
Mon, 22 Jan 1996 17:18:05 +0000 (17:18 +0000)
committerDavid Edelsohn <dje.gcc@gmail.com>
Mon, 22 Jan 1996 17:18:05 +0000 (17:18 +0000)
bfd_mach_sparc_v9.

bfd/ChangeLog
bfd/elf64-sparc.c

index 67c8c29a1eca059ffcc17983d26e52e2ad1edff1..22267ae350435861c589eaee395854dd7e44f8a0 100644 (file)
@@ -8,6 +8,7 @@ end-sanitize-v8plus
        * bfd-in2.h: Regenerated.
        * aoutx.h (aout,machine_type): bfd_mach_sparc64 renamed to
        bfd_mach_sparc_v9.
+       * elf64-sparc.c (sparc64_elf_object_p): Likewise.
        * config.bfd (sparc64-*-sysv4*,sparc64-*-solaris2*): Set targ_defvec
        to bfd_elf32_sparc_vec.
        * cpu-sparc.c (arch_info_struct): Renamed from sparc_arch_info.
index 39785905723abb9ab2782e78c0bfced31e6c4294..8508fdabaee33159ffcce22fc3d7c84818f66e40 100644 (file)
@@ -1,5 +1,5 @@
-/* SPARC-specific support for 32-bit ELF
-   Copyright 1993 Free Software Foundation, Inc.
+/* SPARC-specific support for 64-bit ELF
+   Copyright 1993, 1995 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -15,26 +15,36 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* We need a published ABI spec for this.  Until one comes out, don't
+   assume this'll remain unchanged forever.  */
 
 #include "bfd.h"
 #include "sysdep.h"
 #include "libbfd.h"
-#include "libelf.h"
+#include "elf-bfd.h"
+
+static bfd_reloc_status_type sparc64_elf_wdisp16_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static boolean sparc64_elf_relocate_section
+  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean sparc64_elf_object_p PARAMS ((bfd *));
 
 enum reloc_type
   {
     R_SPARC_NONE = 0,
-    R_SPARC_8,         R_SPARC_16,             R_SPARC_32, 
-    R_SPARC_DISP8,     R_SPARC_DISP16,         R_SPARC_DISP32, 
-    R_SPARC_WDISP30,   R_SPARC_WDISP22,
-    R_SPARC_HI22,      R_SPARC_22,
-    R_SPARC_13,                R_SPARC_LO10,
-    R_SPARC_GOT10,     R_SPARC_GOT13,          R_SPARC_GOT22,
-    R_SPARC_PC10,      R_SPARC_PC22,
+    R_SPARC_8, R_SPARC_16, R_SPARC_32,
+    R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
+    R_SPARC_WDISP30, R_SPARC_WDISP22,
+    R_SPARC_HI22, R_SPARC_22,
+    R_SPARC_13, R_SPARC_LO10,
+    R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
+    R_SPARC_PC10, R_SPARC_PC22,
     R_SPARC_WPLT30,
     R_SPARC_COPY,
-    R_SPARC_GLOB_DAT,  R_SPARC_JMP_SLOT,
+    R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
     R_SPARC_RELATIVE,
     R_SPARC_UA32,
 
@@ -52,16 +62,16 @@ enum reloc_type
 static CONST char *CONST reloc_type_names[] =
 {
   "R_SPARC_NONE",
-  "R_SPARC_8",         "R_SPARC_16",           "R_SPARC_32",
-  "R_SPARC_DISP8",     "R_SPARC_DISP16",       "R_SPARC_DISP32",
-  "R_SPARC_WDISP30",   "R_SPARC_WDISP22",
-  "R_SPARC_HI22",      "R_SPARC_22",
-  "R_SPARC_13",                "R_SPARC_LO10",
-  "R_SPARC_GOT10",     "R_SPARC_GOT13",        "R_SPARC_GOT22",
-  "R_SPARC_PC10",      "R_SPARC_PC22",
+  "R_SPARC_8", "R_SPARC_16", "R_SPARC_32",
+  "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32",
+  "R_SPARC_WDISP30", "R_SPARC_WDISP22",
+  "R_SPARC_HI22", "R_SPARC_22",
+  "R_SPARC_13", "R_SPARC_LO10",
+  "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22",
+  "R_SPARC_PC10", "R_SPARC_PC22",
   "R_SPARC_WPLT30",
   "R_SPARC_COPY",
-  "R_SPARC_GLOB_DAT",  "R_SPARC_JMP_SLOT",
+  "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT",
   "R_SPARC_RELATIVE",
   "R_SPARC_UA32",
 
@@ -76,99 +86,156 @@ static CONST char *CONST reloc_type_names[] =
 extern void abort ();
 #define DIE    ((bfd_reloc_status_type(*)())abort)
 
-static reloc_howto_type elf_sparc_howto_table[] = 
+static reloc_howto_type elf_sparc_howto_table[] =
 {
-  HOWTO(R_SPARC_NONE,   0,0, 0,false,0,false,false, bfd_elf_generic_reloc,"R_SPARC_NONE",   false,0,0x00000000,false),
-  HOWTO(R_SPARC_8,      0,0, 8,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_8",      false,0,0x000000ff,false),
-  HOWTO(R_SPARC_16,     0,1,16,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_16",     false,0,0x0000ffff,false),
-  HOWTO(R_SPARC_32,     0,2,32,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_32",     false,0,0xffffffff,false),
-  HOWTO(R_SPARC_DISP8,  0,0, 8,true, 0,false, true, bfd_elf_generic_reloc,"R_SPARC_DISP8",  false,0,0x000000ff,false),
-  HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,false, true, bfd_elf_generic_reloc,"R_SPARC_DISP16", false,0,0x0000ffff,false),
-  HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,false, true, bfd_elf_generic_reloc,"R_SPARC_DISP32", false,0,0x00ffffff,false),
-  HOWTO(R_SPARC_WDISP30,2,2,30,true, 0,false, true, bfd_elf_generic_reloc,"R_SPARC_WDISP30",false,0,0x3fffffff,true),
-  HOWTO(R_SPARC_WDISP22,2,2,22,true, 0,false, true, bfd_elf_generic_reloc,"R_SPARC_WDISP22",false,0,0x003fffff,false),
-  HOWTO(R_SPARC_HI22,  10,2,22,false,0,true, false, bfd_elf_generic_reloc,"R_SPARC_HI22",   false,0,0x003fffff,false),
-  HOWTO(R_SPARC_22,     0,2,22,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_22",     false,0,0x003fffff,false),
-  HOWTO(R_SPARC_13,     0,1,13,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_13",     false,0,0x00001fff,false),
-  HOWTO(R_SPARC_LO10,   0,1,10,false,0,true, false, bfd_elf_generic_reloc,"R_SPARC_LO10",   false,0,0x000003ff,false),
-  HOWTO(R_SPARC_GOT10,  0,1,10,false,0,false, true, bfd_elf_generic_reloc,"R_SPARC_GOT10",  false,0,0x000003ff,false),
-  HOWTO(R_SPARC_GOT13,  0,1,13,false,0,false, true, bfd_elf_generic_reloc,"R_SPARC_GOT13",  false,0,0x00001fff,false),
-  HOWTO(R_SPARC_GOT22, 10,2,22,false,0,false, true, bfd_elf_generic_reloc,"R_SPARC_GOT22",  false,0,0x003fffff,false),
-  HOWTO(R_SPARC_PC10,   0,1,10,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_PC10",   false,0,0x000003ff,false),
-  HOWTO(R_SPARC_PC22,   0,2,22,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_PC22",   false,0,0x003fffff,false),
-  HOWTO(R_SPARC_WPLT30, 0,0,00,false,0,false,false, bfd_elf_generic_reloc,"R_SPARC_WPLT30", false,0,0x00000000,false),
-  HOWTO(R_SPARC_COPY,   0,0,00,false,0,false,false, bfd_elf_generic_reloc,"R_SPARC_COPY",   false,0,0x00000000,false),
-  HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,false,false,bfd_elf_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,false),
-  HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,false,false,bfd_elf_generic_reloc,"R_SPARC_JMP_SLOT",false,0,0x00000000,false),
-  HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,false,false,bfd_elf_generic_reloc,"R_SPARC_RELATIVE",false,0,0x00000000,false),
-  HOWTO(R_SPARC_UA32,    0,0,00,false,0,false,false,bfd_elf_generic_reloc,"R_SPARC_UA32",    false,0,0x00000000,false),
-  HOWTO(R_SPARC_10,      0,1,10,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_10",        false,0,0x000003ff,false),
-  HOWTO(R_SPARC_11,     0,1,11,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_11",     false,0,0x000007ff,false),
-  HOWTO(R_SPARC_64,     0,4,00,false,0,true,  true, bfd_elf_generic_reloc,"R_SPARC_64",     false,0,(((bfd_vma)0xffffffff)<<32)+0xffffffff,false),
-  HOWTO(R_SPARC_OLO10,   0,1,10,false,0,true,false, bfd_elf_generic_reloc,"R_SPARC_OLO10",false,0,0x000003ff,false),
-  HOWTO(R_SPARC_HH22,   42,2,22,false,0,true, false, bfd_elf_generic_reloc,"R_SPARC_HH22",   false,0,0x003fffff,false),
-  HOWTO(R_SPARC_HM10,   32,1,10,false,0,true,false, bfd_elf_generic_reloc,"R_SPARC_HM10",    false,0,0x000003ff,false),
-  HOWTO(R_SPARC_LM22,   10,2,22,false,0,true,false, bfd_elf_generic_reloc,"R_SPARC_LM22",    false,0,0x003fffff,false),
-  HOWTO(R_SPARC_PC_HH22,42,2,22, true,0,true, false, bfd_elf_generic_reloc,"R_SPARC_HH22",   false,0,0x003fffff,false),
-  HOWTO(R_SPARC_PC_HM10,32,1,10, true,0,true,false, bfd_elf_generic_reloc,"R_SPARC_HM10",    false,0,0x000003ff,false),
-  HOWTO(R_SPARC_PC_LM22,10,2,22,true, 0,true,false, bfd_elf_generic_reloc,"R_SPARC_LM22",    false,0,0x003fffff,false),
-  HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,false, true,bfd_elf_generic_reloc,"R_SPARC_WDISP16",false,0,0,false),
-  HOWTO(R_SPARC_WDISP19, 2,2,22,true, 0,false, true, bfd_elf_generic_reloc,"R_SPARC_WDISP19",false,0,0x0007ffff,false),
-  HOWTO(R_SPARC_GLOB_JMP,0,0,00,false,0,false,false,bfd_elf_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,false),
-  HOWTO(R_SPARC_LO7,     0,1, 7,false,0,false,false,bfd_elf_generic_reloc,"R_SPARC_LO7",     false,0,0x0000007f,false),
+  HOWTO (R_SPARC_NONE, 0, 0, 0, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false, 0, 0x00000000, true),
+  HOWTO (R_SPARC_8, 0, 0, 8, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_8", false, 0, 0x000000ff, true),
+  HOWTO (R_SPARC_16, 0, 1, 16, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_16", false, 0, 0x0000ffff, true),
+  HOWTO (R_SPARC_32, 0, 2, 32, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_32", false, 0, 0xffffffff, true),
+  HOWTO (R_SPARC_DISP8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false, 0, 0x000000ff, true),
+  HOWTO (R_SPARC_DISP16, 0, 1, 16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false, 0, 0x0000ffff, true),
+  HOWTO (R_SPARC_DISP32, 0, 2, 32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false, 0, 0x00ffffff, true),
+  HOWTO (R_SPARC_WDISP30, 2, 2, 30, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false, 0, 0x3fffffff, true),
+  HOWTO (R_SPARC_WDISP22, 2, 2, 22, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_HI22, 10, 2, 22, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_22, 0, 2, 22, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_13, 0, 2, 13, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_13", false, 0, 0x00001fff, true),
+  HOWTO (R_SPARC_LO10, 0, 2, 10, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", false, 0, 0x000003ff, true),
+  HOWTO (R_SPARC_GOT10, 0, 2, 10, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT10", false, 0, 0x000003ff, true),
+  HOWTO (R_SPARC_GOT13, 0, 2, 13, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT13", false, 0, 0x00001fff, true),
+  HOWTO (R_SPARC_GOT22, 10, 2, 22, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_PC10, 0, 2, 10, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_PC10", false, 0, 0x000003ff, true),
+  HOWTO (R_SPARC_PC22, 0, 2, 22, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_PC22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_WPLT30, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false, 0, 0x00000000, true),
+  HOWTO (R_SPARC_COPY, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", false, 0, 0x00000000, true),
+  HOWTO (R_SPARC_GLOB_DAT, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT", false, 0, 0x00000000, true),
+  HOWTO (R_SPARC_JMP_SLOT, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_SLOT", false, 0, 0x00000000, true),
+  HOWTO (R_SPARC_RELATIVE, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE", false, 0, 0x00000000, true),
+  HOWTO (R_SPARC_UA32, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UA32", false, 0, 0x00000000, true),
+  HOWTO (R_SPARC_10, 0, 2, 10, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_10", false, 0, 0x000003ff, true),
+  HOWTO (R_SPARC_11, 0, 2, 11, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_11", false, 0, 0x000007ff, true),
+  HOWTO (R_SPARC_64, 0, 4, 00, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_64", false, 0, (((bfd_vma) 0xffffffff) << 32) + 0xffffffff, true),
+  HOWTO (R_SPARC_OLO10, 0, 2, 10, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_OLO10", false, 0, 0x000003ff, true),
+  HOWTO (R_SPARC_HH22, 42, 2, 22, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_HM10, 32, 2, 10, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false, 0, 0x000003ff, true),
+  HOWTO (R_SPARC_LM22, 10, 2, 22, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_PC_HH22, 42, 2, 22, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_PC_HM10, 32, 2, 10, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false, 0, 0x000003ff, true),
+  HOWTO (R_SPARC_PC_LM22, 10, 2, 22, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false, 0, 0x003fffff, true),
+  HOWTO (R_SPARC_WDISP16, 2, 2, 16, true, 0, complain_overflow_signed, sparc64_elf_wdisp16_reloc, "R_SPARC_WDISP16", false, 0, 0, true),
+  HOWTO (R_SPARC_WDISP19, 2, 2, 22, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false, 0, 0x0007ffff, true),
+  HOWTO (R_SPARC_GLOB_JMP, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT", false, 0, 0x00000000, true),
+  HOWTO (R_SPARC_LO7, 0, 2, 7, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO7", false, 0, 0x0000007f, true),
 };
 
-struct elf_reloc_map {
-  unsigned char bfd_reloc_val;
-  unsigned char elf_reloc_val;
-};
+/* Handle the WDISP16 reloc.  */
+
+static bfd_reloc_status_type
+sparc64_elf_wdisp16_reloc (abfd,
+                          reloc_entry,
+                          symbol,
+                          data,
+                          input_section,
+                          output_bfd,
+                          error_message)
+     bfd *abfd;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     PTR data;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message;
+{
+  bfd_vma relocation;
+  bfd_vma x;
+
+  if (output_bfd != (bfd *) NULL
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && (! reloc_entry->howto->partial_inplace
+         || reloc_entry->addend == 0))
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  if (output_bfd != NULL)
+    return bfd_reloc_continue;
+
+  if (reloc_entry->address > input_section->_cooked_size)
+    return bfd_reloc_outofrange;
+
+  relocation = (symbol->value
+               + symbol->section->output_section->vma
+               + symbol->section->output_offset);
+  relocation += reloc_entry->addend;
+  relocation -=        (input_section->output_section->vma
+                + input_section->output_offset);
+  relocation -= reloc_entry->address;
+
+  x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
+  x |= ((((relocation >> 2) & 0xc000) << 6)
+       | ((relocation >> 2) & 0x3fff));
+  bfd_put_32 (abfd, x, (char *) data + reloc_entry->address);
+
+  if ((bfd_signed_vma) relocation < - 0x40000
+      || (bfd_signed_vma) relocation > 0x3ffff)
+    return bfd_reloc_overflow;
+  else
+    return bfd_reloc_ok;
+}
+
+struct elf_reloc_map
+  {
+    unsigned char 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_8, R_SPARC_8 },
-  { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
-  { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits.  */
-  { 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_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_NONE, R_SPARC_NONE,},
+  {BFD_RELOC_16, R_SPARC_16,},
+  {BFD_RELOC_8, R_SPARC_8},
+  {BFD_RELOC_8_PCREL, R_SPARC_DISP8},
+  {BFD_RELOC_CTOR, R_SPARC_32},        /* @@ Assumes 32 bits.  */
+  {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_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_UA32, R_SPARC_UA32 }, not used?? */
-  { 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_GLOB_JMP, R_SPARC_GLOB_JMP },
-  { BFD_RELOC_SPARC_LO7, R_SPARC_LO7 },
+  {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_GLOB_JMP, R_SPARC_GLOB_JMP},
+  {BFD_RELOC_SPARC_LO7, R_SPARC_LO7},
 };
 
-static CONST struct reloc_howto_struct *
-DEFUN (bfd_elf64_bfd_reloc_type_lookup, (abfd, code),
-       bfd *abfd AND
-       bfd_reloc_code_real_type code)
+static reloc_howto_type *
+bfd_elf64_bfd_reloc_type_lookup (abfd, code)
+     bfd *abfd;
+     bfd_reloc_code_real_type code;
 {
   int i;
   for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++)
@@ -180,17 +247,192 @@ DEFUN (bfd_elf64_bfd_reloc_type_lookup, (abfd, code),
 }
 
 static void
-DEFUN (elf_info_to_howto, (abfd, cache_ptr, dst),
-       bfd *abfd AND
-       arelent *cache_ptr AND
-       Elf64_Internal_Rela *dst)
+elf_info_to_howto (abfd, cache_ptr, dst)
+     bfd *abfd;
+     arelent *cache_ptr;
+     Elf64_Internal_Rela *dst;
+{
+  BFD_ASSERT (ELF64_R_TYPE (dst->r_info) < (unsigned int) R_SPARC_max);
+  cache_ptr->howto = &elf_sparc_howto_table[ELF64_R_TYPE (dst->r_info)];
+}
+
+/* Relocate a SPARC64 ELF section.  */
+
+static boolean
+sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
+                             contents, relocs, local_syms, local_sections)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     asection *input_section;
+     bfd_byte *contents;
+     Elf_Internal_Rela *relocs;
+     Elf_Internal_Sym *local_syms;
+     asection **local_sections;
 {
-  BFD_ASSERT (ELF64_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max);
-  cache_ptr->howto = &elf_sparc_howto_table[ELF64_R_TYPE(dst->r_info)];
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  Elf_Internal_Rela *rel;
+  Elf_Internal_Rela *relend;
+
+  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (input_bfd);
+
+  rel = relocs;
+  relend = relocs + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      int r_type;
+      reloc_howto_type *howto;
+      long r_symndx;
+      struct elf_link_hash_entry *h;
+      Elf_Internal_Sym *sym;
+      asection *sec;
+      bfd_vma relocation;
+      bfd_reloc_status_type r;
+
+      r_type = ELF64_R_TYPE (rel->r_info);
+      if (r_type < 0 || r_type >= (int) R_SPARC_max)
+       {
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+       }
+      howto = elf_sparc_howto_table + r_type;
+
+      r_symndx = ELF64_R_SYM (rel->r_info);
+
+      if (info->relocateable)
+       {
+         /* This is a relocateable link.  We don't have to change
+            anything, unless the reloc is against a section symbol,
+            in which case we have to adjust according to where the
+            section symbol winds up in the output section.  */
+         if (r_symndx < symtab_hdr->sh_info)
+           {
+             sym = local_syms + r_symndx;
+             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+               {
+                 sec = local_sections[r_symndx];
+                 rel->r_addend += sec->output_offset + sym->st_value;
+               }
+           }
+
+         continue;
+       }
+
+      /* This is a final link.  */
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+      if (r_symndx < symtab_hdr->sh_info)
+       {
+         sym = local_syms + r_symndx;
+         sec = local_sections[r_symndx];
+         relocation = (sec->output_section->vma
+                       + sec->output_offset
+                       + sym->st_value);
+       }
+      else
+       {
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         if (h->root.type == bfd_link_hash_defined
+             || h->root.type == bfd_link_hash_defweak)
+           {
+             sec = h->root.u.def.section;
+             relocation = (h->root.u.def.value
+                           + sec->output_section->vma
+                           + sec->output_offset);
+           }
+         else if (h->root.type == bfd_link_hash_undefweak)
+           relocation = 0;
+         else
+           {
+             if (! ((*info->callbacks->undefined_symbol)
+                    (info, h->root.root.string, input_bfd,
+                     input_section, rel->r_offset)))
+               return false;
+             relocation = 0;
+           }
+       }
+
+      if (r_type != R_SPARC_WDISP16)
+       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+                                     contents, rel->r_offset,
+                                     relocation, rel->r_addend);
+      else
+       {
+         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) & 0xc000) << 6)
+               | ((relocation >> 2) & 0x3fff));
+         bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+
+         if ((bfd_signed_vma) relocation < - 0x40000
+             || (bfd_signed_vma) relocation > 0x3ffff)
+           r = bfd_reloc_overflow;
+         else
+           r = bfd_reloc_ok;
+       }
+
+      if (r != bfd_reloc_ok)
+       {
+         switch (r)
+           {
+           default:
+           case bfd_reloc_outofrange:
+             abort ();
+           case bfd_reloc_overflow:
+             {
+               const char *name;
+
+               if (h != NULL)
+                 name = h->root.root.string;
+               else
+                 {
+                   name = (bfd_elf_string_from_elf_section
+                           (input_bfd,
+                            symtab_hdr->sh_link,
+                            sym->st_name));
+                   if (name == NULL)
+                     return false;
+                   if (*name == '\0')
+                     name = bfd_section_name (input_bfd, sec);
+                 }
+               if (! ((*info->callbacks->reloc_overflow)
+                      (info, name, howto->name, (bfd_vma) 0,
+                       input_bfd, input_section, rel->r_offset)))
+                 return false;
+             }
+             break;
+           }
+       }
+    }
+
+  return true;
+}
+
+/* Set the right machine number for a SPARC64 ELF file.  */
+
+static boolean
+sparc64_elf_object_p (abfd)
+     bfd *abfd;
+{
+  return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9);
 }
 
 #define TARGET_BIG_SYM bfd_elf64_sparc_vec
 #define TARGET_BIG_NAME        "elf64-sparc"
 #define ELF_ARCH       bfd_arch_sparc
+#define ELF_MACHINE_CODE EM_SPARC64
+#define ELF_MAXPAGESIZE 0x100000
+
+#define elf_backend_relocate_section   sparc64_elf_relocate_section
+#define elf_backend_object_p           sparc64_elf_object_p
 
 #include "elf64-target.h"