OSDN Git Service

Initialize subspace_sections.
[pf3gnuchains/pf3gnuchains4x.git] / bfd / elf64-sparc.c
index 29effd1..cb03eeb 100644 (file)
@@ -35,31 +35,37 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define MINUS_ONE (~ (bfd_vma) 0)
 
 static struct bfd_link_hash_table * sparc64_elf_bfd_link_hash_table_create
-  PARAMS((bfd *));
+  PARAMS ((bfd *));
+static bfd_reloc_status_type init_insn_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *,
+          bfd *, bfd_vma *, bfd_vma *));
 static reloc_howto_type *sparc64_elf_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static void sparc64_elf_info_to_howto
   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
 
 static void sparc64_elf_build_plt
-  PARAMS((bfd *, unsigned char *, int));
+  PARAMS ((bfd *, unsigned char *, int));
 static bfd_vma sparc64_elf_plt_entry_offset
-  PARAMS((int));
+  PARAMS ((bfd_vma));
 static bfd_vma sparc64_elf_plt_ptr_offset
-  PARAMS((int, int));
+  PARAMS ((bfd_vma, bfd_vma));
 
 static boolean sparc64_elf_check_relocs
-  PARAMS((bfd *, struct bfd_link_info *, asection *sec,
-         const Elf_Internal_Rela *));
+  PARAMS ((bfd *, struct bfd_link_info *, asection *sec,
+          const Elf_Internal_Rela *));
 static boolean sparc64_elf_adjust_dynamic_symbol
-  PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 static boolean sparc64_elf_size_dynamic_sections
-  PARAMS((bfd *, struct bfd_link_info *));
+  PARAMS ((bfd *, struct bfd_link_info *));
 static int sparc64_elf_get_symbol_type
   PARAMS (( Elf_Internal_Sym *, int));
 static boolean sparc64_elf_add_symbol_hook
   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
-        const char **, flagword *, asection **, bfd_vma *));
+          const char **, flagword *, asection **, bfd_vma *));
+static boolean sparc64_elf_output_arch_syms
+  PARAMS ((bfd *, struct bfd_link_info *, PTR,
+          boolean (*) (PTR, const char *, Elf_Internal_Sym *, asection *)));
 static void sparc64_elf_symbol_processing
   PARAMS ((bfd *, asymbol *));
 
@@ -68,11 +74,18 @@ static boolean sparc64_elf_copy_private_bfd_data
 static boolean sparc64_elf_merge_private_bfd_data
   PARAMS ((bfd *, bfd *));
 
+static const char *sparc64_elf_print_symbol_all
+  PARAMS ((bfd *, PTR, asymbol *));
 static boolean sparc64_elf_relax_section
   PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
 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_finish_dynamic_symbol
+  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+          Elf_Internal_Sym *));
+static boolean sparc64_elf_finish_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
 static boolean sparc64_elf_object_p PARAMS ((bfd *));
 static long sparc64_elf_get_reloc_upper_bound PARAMS ((bfd *, asection *));
 static long sparc64_elf_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
@@ -83,6 +96,8 @@ static boolean sparc64_elf_slurp_reloc_table
 static long sparc64_elf_canonicalize_dynamic_reloc
   PARAMS ((bfd *, arelent **, asymbol **));
 static void sparc64_elf_write_relocs PARAMS ((bfd *, asection *, PTR));
+static enum elf_reloc_type_class sparc64_elf_reloc_type_class
+  PARAMS ((const Elf_Internal_Rela *));
 \f
 /* The relocation "howto" table.  */
 
@@ -163,7 +178,7 @@ struct elf_reloc_map {
   unsigned char elf_reloc_val;
 };
 
-static CONST struct elf_reloc_map sparc_reloc_map[] =
+static const struct elf_reloc_map sparc_reloc_map[] =
 {
   { BFD_RELOC_NONE, R_SPARC_NONE, },
   { BFD_RELOC_16, R_SPARC_16, },
@@ -280,13 +295,12 @@ sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, dynamic)
   bfd_size_type count;
   arelent *relents;
 
-  allocated = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size);
+  allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
   if (allocated == NULL)
     goto error_return;
 
   if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
-      || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd)
-         != rel_hdr->sh_size))
+      || bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size)
     goto error_return;
 
   native_relocs = (bfd_byte *) allocated;
@@ -371,6 +385,7 @@ sparc64_elf_slurp_reloc_table (abfd, asect, symbols, dynamic)
   struct bfd_elf_section_data * const d = elf_section_data (asect);
   Elf_Internal_Shdr *rel_hdr;
   Elf_Internal_Shdr *rel_hdr2;
+  bfd_size_type amt;
 
   if (asect->relocation != NULL)
     return true;
@@ -401,9 +416,9 @@ sparc64_elf_slurp_reloc_table (abfd, asect, symbols, dynamic)
       rel_hdr2 = NULL;
     }
 
-  asect->relocation = ((arelent *)
-                      bfd_alloc (abfd,
-                                 asect->reloc_count * 2 * sizeof (arelent)));
+  amt = asect->reloc_count;
+  amt *= 2 * sizeof (arelent);
+  asect->relocation = (arelent *) bfd_alloc (abfd, amt);
   if (asect->relocation == NULL)
     return false;
 
@@ -639,9 +654,9 @@ sparc64_elf_bfd_link_hash_table_create (abfd)
      bfd *abfd;
 {
   struct sparc64_elf_link_hash_table *ret;
+  bfd_size_type amt = sizeof (struct sparc64_elf_link_hash_table);
 
-  ret = ((struct sparc64_elf_link_hash_table *)
-        bfd_zalloc (abfd, sizeof (struct sparc64_elf_link_hash_table)));
+  ret = (struct sparc64_elf_link_hash_table *) bfd_zalloc (abfd, amt);
   if (ret == (struct sparc64_elf_link_hash_table *) NULL)
     return NULL;
 
@@ -759,8 +774,8 @@ sparc_elf_wdisp16_reloc (abfd, reloc_entry, symbol, data, input_section,
   if (status != bfd_reloc_other)
     return status;
 
-  insn = (insn & ~0x303fff) | ((((relocation >> 2) & 0xc000) << 6)
-                              | ((relocation >> 2) & 0x3fff));
+  insn &= ~ (bfd_vma) 0x303fff;
+  insn |= (((relocation >> 2) & 0xc000) << 6) | ((relocation >> 2) & 0x3fff);
   bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
 
   if ((bfd_signed_vma) relocation < - 0x40000
@@ -798,7 +813,7 @@ sparc_elf_hix22_reloc (abfd,
     return status;
 
   relocation ^= MINUS_ONE;
-  insn = (insn & ~0x3fffff) | ((relocation >> 10) & 0x3fffff);
+  insn = (insn &~ (bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff);
   bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
 
   if ((relocation & ~ (bfd_vma) 0xffffffff) != 0)
@@ -834,7 +849,7 @@ sparc_elf_lox10_reloc (abfd,
   if (status != bfd_reloc_other)
     return status;
 
-  insn = (insn & ~0x1fff) | 0x1c00 | (relocation & 0x3ff);
+  insn = (insn &~ (bfd_vma) 0x1fff) | 0x1c00 | (relocation & 0x3ff);
   bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
 
   return bfd_reloc_ok;
@@ -865,7 +880,7 @@ sparc64_elf_build_plt (output_bfd, contents, nentries)
      We fill them with `illtrap 0' to force ld.so to do something.  */
 
   for (i = 0; i < PLT_HEADER_SIZE/4; ++i)
-    bfd_put_32 (output_bfd, 0, contents+i*4);
+    bfd_put_32 (output_bfd, (bfd_vma) 0, contents+i*4);
 
   /* The first 32768 entries are close enough to plt1 to get there via
      a straight branch.  */
@@ -881,14 +896,14 @@ sparc64_elf_build_plt (output_bfd, contents, nentries)
       /* ba,a,pt %xcc, plt1 */
       ba = 0x30680000 | (((contents+PLT_ENTRY_SIZE) - (entry+4)) / 4 & 0x7ffff);
 
-      bfd_put_32 (output_bfd, sethi, entry);
-      bfd_put_32 (output_bfd, ba, entry+4);
-      bfd_put_32 (output_bfd, nop, entry+8);
-      bfd_put_32 (output_bfd, nop, entry+12);
-      bfd_put_32 (output_bfd, nop, entry+16);
-      bfd_put_32 (output_bfd, nop, entry+20);
-      bfd_put_32 (output_bfd, nop, entry+24);
-      bfd_put_32 (output_bfd, nop, entry+28);
+      bfd_put_32 (output_bfd, (bfd_vma) sethi, entry);
+      bfd_put_32 (output_bfd, (bfd_vma) ba,    entry + 4);
+      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 8);
+      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 12);
+      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 16);
+      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 20);
+      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 24);
+      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 28);
     }
 
   /* Now the tricky bit.  Entries 32768 and higher are grouped in blocks of
@@ -906,17 +921,23 @@ sparc64_elf_build_plt (output_bfd, contents, nentries)
          entry = contents + i*PLT_ENTRY_SIZE + j*4*6;
          ptr = contents + i*PLT_ENTRY_SIZE + block*4*6 + j*8;
 
-         /* ldx [%o7 + ptr - entry+4], %g1 */
-         ldx = 0xc25be000 | ((ptr - entry+4) & 0x1fff);
-
-         bfd_put_32 (output_bfd, 0x8a10000f, entry);    /* mov %o7,%g5 */
-         bfd_put_32 (output_bfd, 0x40000002, entry+4);  /* call .+8 */
-         bfd_put_32 (output_bfd, nop, entry+8);         /* nop */
-         bfd_put_32 (output_bfd, ldx, entry+12);        /* ldx [%o7+P],%g1 */
-         bfd_put_32 (output_bfd, 0x83c3c001, entry+16); /* jmpl %o7+%g1,%g1 */
-         bfd_put_32 (output_bfd, 0x9e100005, entry+20); /* mov %g5,%o7 */
-
-         bfd_put_64 (output_bfd, contents - (entry+4), ptr);
+         /* ldx [%o7 + ptr - (entry+4)], %g1 */
+         ldx = 0xc25be000 | ((ptr - (entry+4)) & 0x1fff);
+
+         /* mov %o7,%g5
+            call .+8
+            nop
+            ldx [%o7+P],%g1
+            jmpl %o7+%g1,%g1
+            mov %g5,%o7  */
+         bfd_put_32 (output_bfd, (bfd_vma) 0x8a10000f, entry);
+         bfd_put_32 (output_bfd, (bfd_vma) 0x40000002, entry + 4);
+         bfd_put_32 (output_bfd, (bfd_vma) nop,        entry + 8);
+         bfd_put_32 (output_bfd, (bfd_vma) ldx,        entry + 12);
+         bfd_put_32 (output_bfd, (bfd_vma) 0x83c3c001, entry + 16);
+         bfd_put_32 (output_bfd, (bfd_vma) 0x9e100005, entry + 20);
+
+         bfd_put_64 (output_bfd, (bfd_vma) (contents - (entry + 4)), ptr);
        }
     }
 }
@@ -925,9 +946,9 @@ sparc64_elf_build_plt (output_bfd, contents, nentries)
 
 static bfd_vma
 sparc64_elf_plt_entry_offset (index)
-     int index;
+     bfd_vma index;
 {
-  int block, ofs;
+  bfd_vma block, ofs;
 
   if (index < LARGE_PLT_THRESHOLD)
     return index * PLT_ENTRY_SIZE;
@@ -937,22 +958,21 @@ sparc64_elf_plt_entry_offset (index)
   block = (index - LARGE_PLT_THRESHOLD) / 160;
   ofs = (index - LARGE_PLT_THRESHOLD) % 160;
 
-  return ((bfd_vma) (LARGE_PLT_THRESHOLD + block*160) * PLT_ENTRY_SIZE
-         + ofs * 6*4);
+  return (LARGE_PLT_THRESHOLD + block * 160) * PLT_ENTRY_SIZE + ofs * 6 * 4;
 }
 
 static bfd_vma
 sparc64_elf_plt_ptr_offset (index, max)
-     int index, max;
+     bfd_vma index;
+     bfd_vma max;
 {
-  int block, ofs, last;
+  bfd_vma block, ofs, last;
 
   BFD_ASSERT(index >= LARGE_PLT_THRESHOLD);
 
   /* See above for details.  */
 
-  block = (((index - LARGE_PLT_THRESHOLD) / 160) * 160)
-         + LARGE_PLT_THRESHOLD;
+  block = (((index - LARGE_PLT_THRESHOLD) / 160) * 160) + LARGE_PLT_THRESHOLD;
   ofs = index - block;
   if (block + 160 > max)
     last = (max - LARGE_PLT_THRESHOLD) % 160;
@@ -1073,10 +1093,11 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
                  symbol.  */
              if (local_got_offsets == NULL)
                {
-                 size_t size;
+                 bfd_size_type size;
                  register unsigned int i;
 
-                 size = symtab_hdr->sh_info * sizeof (bfd_vma);
+                 size = symtab_hdr->sh_info;
+                 size *= sizeof (bfd_vma);
                  local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
                  if (local_got_offsets == NULL)
                    return false;
@@ -1235,6 +1256,8 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
                          || ! bfd_set_section_alignment (dynobj, sreloc, 3))
                        return false;
                    }
+                 if (sec->flags & SEC_READONLY)
+                   info->flags |= DF_TEXTREL;
                }
 
              sreloc->_raw_size += sizeof (Elf64_External_Rela);
@@ -1247,7 +1270,7 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
 
        default:
          (*_bfd_error_handler) (_("%s: check_relocs: unhandled reloc type %d"),
-                               bfd_get_filename(abfd),
+                               bfd_archive_filename (abfd),
                                ELF64_R_TYPE_ID (rel->r_info));
          return false;
        }
@@ -1269,7 +1292,7 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      asection **secp ATTRIBUTE_UNUSED;
      bfd_vma *valp ATTRIBUTE_UNUSED;
 {
-  static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
+  static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
 
   if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
     {
@@ -1284,7 +1307,7 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
        default:
           (*_bfd_error_handler)
             (_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"),
-             bfd_get_filename (abfd));
+             bfd_archive_filename (abfd));
          return false;
        }
 
@@ -1303,11 +1326,12 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
       if (p->name != NULL && strcmp (p->name, *namep))
        {
           (*_bfd_error_handler)
-            (_("Register %%g%d used incompatibly: "
-               "previously declared in %s to %s, in %s redefined to %s"),
-             (int)sym->st_value,
-             bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch",
-             bfd_get_filename (abfd), **namep ? *namep : "#scratch");
+            (_("Register %%g%d used incompatibly: %s in %s"),
+             (int) sym->st_value,
+             **namep ? *namep : "#scratch", bfd_archive_filename (abfd));
+          (*_bfd_error_handler)
+            (_("  previously %s in %s"),
+             *p->name ? p->name : "#scratch", bfd_archive_filename (p->abfd));
          return false;
        }
 
@@ -1324,11 +1348,14 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
                {
                  unsigned char type = h->type;
 
-                 if (type > STT_FUNC) type = 0;
+                 if (type > STT_FUNC)
+                   type = 0;
+                 (*_bfd_error_handler)
+                   (_("Symbol `%s' has differing types: %s in %s"),
+                    *namep, "REGISTER", bfd_archive_filename (abfd));
                  (*_bfd_error_handler)
-                   (_("Symbol `%s' has differing types: "
-                      "previously %s, REGISTER in %s"),
-                    *namep, stt_types [type], bfd_get_filename (abfd));
+                   (_("  previously %s in %s"),
+                    stt_types[type], bfd_archive_filename (p->abfd));
                  return false;
                }
 
@@ -1370,12 +1397,14 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
          {
            unsigned char type = ELF_ST_TYPE (sym->st_info);
 
-           if (type > STT_FUNC) type = 0;
+           if (type > STT_FUNC)
+             type = 0;
            (*_bfd_error_handler)
-             (_("Symbol `%s' has differing types: "
-                "REGISTER in %s, %s in %s"),
-              *namep, bfd_get_filename (p->abfd), stt_types [type],
-              bfd_get_filename (abfd));
+             (_("Symbol `%s' has differing types: %s in %s"),
+              *namep, stt_types[type], bfd_archive_filename (abfd));
+           (*_bfd_error_handler)
+             (_("  previously %s in %s"),
+              "REGISTER", bfd_archive_filename (p->abfd));
            return false;
          }
     }
@@ -1653,7 +1682,6 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
 {
   bfd *dynobj;
   asection *s;
-  boolean reltext;
   boolean relplt;
 
   dynobj = elf_hash_table (info)->dynobj;
@@ -1685,7 +1713,6 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */
-  reltext = false;
   relplt = false;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
@@ -1718,18 +1745,6 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
            }
          else
            {
-             const char *outname;
-             asection *target;
-
-             /* If this relocation section applies to a read only
-                section, then we probably need a DT_TEXTREL entry.  */
-             outname = bfd_get_section_name (output_bfd,
-                                             s->output_section);
-             target = bfd_get_section_by_name (output_bfd, outname + 5);
-             if (target != NULL
-                 && (target->flags & SEC_READONLY) != 0)
-               reltext = true;
-
              if (strcmp (name, ".rela.plt") == 0)
                relplt = true;
 
@@ -1766,37 +1781,38 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
         must add the entries now so that we get the correct size for
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
+#define add_dynamic_entry(TAG, VAL) \
+  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
       int reg;
       struct sparc64_elf_app_reg * app_regs;
       struct bfd_strtab_hash *dynstr;
       struct elf_link_hash_table *eht = elf_hash_table (info);
 
-      if (! info->shared)
+      if (!info->shared)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
+         if (!add_dynamic_entry (DT_DEBUG, 0))
            return false;
        }
 
       if (relplt)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_PLTRELSZ, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0))
+         if (!add_dynamic_entry (DT_PLTGOT, 0)
+             || !add_dynamic_entry (DT_PLTRELSZ, 0)
+             || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+             || !add_dynamic_entry (DT_JMPREL, 0))
            return false;
        }
 
-      if (! bfd_elf64_add_dynamic_entry (info, DT_RELA, 0)
-         || ! bfd_elf64_add_dynamic_entry (info, DT_RELASZ, 0)
-         || ! bfd_elf64_add_dynamic_entry (info, DT_RELAENT,
-                                           sizeof (Elf64_External_Rela)))
+      if (!add_dynamic_entry (DT_RELA, 0)
+         || !add_dynamic_entry (DT_RELASZ, 0)
+         || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
        return false;
 
-      if (reltext)
+      if (info->flags & DF_TEXTREL)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
+         if (!add_dynamic_entry (DT_TEXTREL, 0))
            return false;
-         info->flags |= DF_TEXTREL;
        }
 
       /* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER
@@ -1809,7 +1825,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
          {
            struct elf_link_local_dynamic_entry *entry, *e;
 
-           if (! bfd_elf64_add_dynamic_entry (info, DT_SPARC_REGISTER, 0))
+           if (!add_dynamic_entry (DT_SPARC_REGISTER, 0))
              return false;
 
            entry = (struct elf_link_local_dynamic_entry *)
@@ -1846,6 +1862,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
            eht->dynsymcount++;
          }
     }
+#undef add_dynamic_entry
 
   return true;
 }
@@ -2059,7 +2076,8 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          else if (h->root.type == bfd_link_hash_undefweak)
            relocation = 0;
-         else if (info->shared && !info->symbolic
+         else if (info->shared
+                  && (!info->symbolic || info->allow_shlib_undefined)
                   && !info->no_undefined
                   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
            relocation = 0;
@@ -2261,7 +2279,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                BFD_FAIL ();
                                (*_bfd_error_handler)
                                  (_("%s: probably compiled without -fPIC?"),
-                                  bfd_get_filename (input_bfd));
+                                  bfd_archive_filename (input_bfd));
                                bfd_set_error (bfd_error_bad_value);
                                return false;
                              }
@@ -2364,7 +2382,8 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                         Note this is different behaviour to the
                         32-bit linker, which both adds the contents
                         and ignores the addend.  So clear the location.  */
-                     bfd_put_64 (output_bfd, 0, sgot->contents + off);
+                     bfd_put_64 (output_bfd, (bfd_vma) 0,
+                                 sgot->contents + off);
 
                      /* We need to generate a R_SPARC_RELATIVE reloc
                         for the dynamic linker.  */
@@ -2430,7 +2449,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            relocation = (relocation & 0x3ff) + ELF64_R_TYPE_DATA (rel->r_info);
 
            x = bfd_get_32 (input_bfd, contents + rel->r_offset);
-           x = (x & ~0x1fff) | (relocation & 0x1fff);
+           x = (x & ~(bfd_vma) 0x1fff) | (relocation & 0x1fff);
            bfd_put_32 (input_bfd, x, contents + rel->r_offset);
 
            r = bfd_check_overflow (howto->complain_on_overflow,
@@ -2451,8 +2470,9 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            relocation -= rel->r_offset;
 
            x = bfd_get_32 (input_bfd, contents + rel->r_offset);
-           x = (x & ~0x303fff) | ((((relocation >> 2) & 0xc000) << 6)
-                                  | ((relocation >> 2) & 0x3fff));
+           x &= ~(bfd_vma) 0x303fff;
+           x |= ((((relocation >> 2) & 0xc000) << 6)
+                 | ((relocation >> 2) & 0x3fff));
            bfd_put_32 (input_bfd, x, contents + rel->r_offset);
 
            r = bfd_check_overflow (howto->complain_on_overflow,
@@ -2470,7 +2490,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            relocation = relocation ^ MINUS_ONE;
 
            x = bfd_get_32 (input_bfd, contents + rel->r_offset);
-           x = (x & ~0x3fffff) | ((relocation >> 10) & 0x3fffff);
+           x = (x & ~(bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff);
            bfd_put_32 (input_bfd, x, contents + rel->r_offset);
 
            r = bfd_check_overflow (howto->complain_on_overflow,
@@ -2488,7 +2508,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            relocation = (relocation & 0x3ff) | 0x1c00;
 
            x = bfd_get_32 (input_bfd, contents + rel->r_offset);
-           x = (x & ~0x1fff) | relocation;
+           x = (x & ~(bfd_vma) 0x1fff) | relocation;
            bfd_put_32 (input_bfd, x, contents + rel->r_offset);
 
            r = bfd_reloc_ok;
@@ -2577,7 +2597,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                              || reg == G0 || reg == O7)
                            break;
 
-                         bfd_put_32 (input_bfd, INSN_NOP,
+                         bfd_put_32 (input_bfd, (bfd_vma) INSN_NOP,
                                      contents + rel->r_offset + 4);
                        }
                      break;
@@ -2682,7 +2702,7 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
        }
       else
        {
-         int max = splt->_raw_size / PLT_ENTRY_SIZE;
+         bfd_vma max = splt->_raw_size / PLT_ENTRY_SIZE;
          rela.r_offset = sparc64_elf_plt_ptr_offset (h->plt.offset, max);
          rela.r_addend = -(sparc64_elf_plt_entry_offset (h->plt.offset) + 4)
                          -(splt->output_section->vma + splt->output_offset);
@@ -2728,7 +2748,7 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       rela.r_offset = (sgot->output_section->vma
                       + sgot->output_offset
-                      + (h->got.offset &~ 1));
+                      + (h->got.offset &~ (bfd_vma) 1));
 
       /* If this is a -Bsymbolic link, and the symbol is defined
         locally, we just want to emit a RELATIVE reloc.  Likewise if
@@ -2870,8 +2890,8 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
       /* Initialize the contents of the .plt section.  */
       if (splt->_raw_size > 0)
        {
-         sparc64_elf_build_plt(output_bfd, splt->contents,
-                               splt->_raw_size / PLT_ENTRY_SIZE);
+         sparc64_elf_build_plt (output_bfd, splt->contents,
+                                (int) (splt->_raw_size / PLT_ENTRY_SIZE));
        }
 
       elf_section_data (splt->output_section)->this_hdr.sh_entsize =
@@ -2896,6 +2916,23 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
 
   return true;
 }
+
+static enum elf_reloc_type_class
+sparc64_elf_reloc_type_class (rela)
+     const Elf_Internal_Rela *rela;
+{
+  switch ((int) ELF64_R_TYPE (rela->r_info))
+    {
+    case R_SPARC_RELATIVE:
+      return reloc_class_relative;
+    case R_SPARC_JMP_SLOT:
+      return reloc_class_plt;
+    case R_SPARC_COPY:
+      return reloc_class_copy;
+    default:
+      return reloc_class_normal;
+    }
+}
 \f
 /* Functions for dealing with the e_flags field.  */
 
@@ -2972,7 +3009,7 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd)
              error = true;
              (*_bfd_error_handler)
                (_("%s: linking UltraSPARC specific with HAL specific code"),
-                bfd_get_filename (ibfd));
+                bfd_archive_filename (ibfd));
            }
          /* Choose the most restrictive memory ordering.  */
          old_mm = (old_flags & EF_SPARCV9_MM);
@@ -2991,7 +3028,7 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd)
           error = true;
           (*_bfd_error_handler)
             (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
-             bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
+             bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags);
         }
 
       elf_elfheader (obfd)->e_flags = old_flags;
@@ -3025,8 +3062,8 @@ sparc64_elf_print_symbol_all (abfd, filep, symbol)
   fprintf (file, "REG_%c%c%11s%c%c    R", "GOLI" [reg / 8], '0' + (reg & 7), "",
                 ((type & BSF_LOCAL)
                  ? (type & BSF_GLOBAL) ? '!' : 'l'
-                 : (type & BSF_GLOBAL) ? 'g' : ' '),
-                (type & BSF_WEAK) ? 'w' : ' ');
+                 : (type & BSF_GLOBAL) ? 'g' : ' '),
+                (type & BSF_WEAK) ? 'w' : ' ');
   if (symbol->name == NULL || symbol->name [0] == '\0')
     return "#scratch";
   else
@@ -3147,6 +3184,8 @@ const struct elf_size_info sparc64_elf_size_info =
   sparc64_elf_size_info
 #define elf_backend_object_p \
   sparc64_elf_object_p
+#define elf_backend_reloc_type_class \
+  sparc64_elf_reloc_type_class
 
 #define elf_backend_want_got_plt 0
 #define elf_backend_plt_readonly 0