]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gold/sparc.cc
opcodes: bfin: simplify field width processing and fix build warnings
[thirdparty/binutils-gdb.git] / gold / sparc.cc
index 234c5f5aa0aac0ba576ad4d703e22e67d7158778..39c7e7ccf6fe73bdfff5519aaca5f01dc8521345 100644 (file)
@@ -1,6 +1,6 @@
 // sparc.cc -- sparc target support for gold.
 
-// Copyright 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by David S. Miller <davem@davemloft.net>.
 
 // This file is part of gold.
@@ -69,7 +69,7 @@ class Target_sparc : public Sized_target<size, big_endian>
   void
   gc_process_relocs(Symbol_table* symtab,
                    Layout* layout,
-                   Sized_relobj<size, big_endian>* object,
+                   Sized_relobj_file<size, big_endian>* object,
                    unsigned int data_shndx,
                    unsigned int sh_type,
                    const unsigned char* prelocs,
@@ -83,7 +83,7 @@ class Target_sparc : public Sized_target<size, big_endian>
   void
   scan_relocs(Symbol_table* symtab,
              Layout* layout,
-             Sized_relobj<size, big_endian>* object,
+             Sized_relobj_file<size, big_endian>* object,
              unsigned int data_shndx,
              unsigned int sh_type,
              const unsigned char* prelocs,
@@ -118,7 +118,7 @@ class Target_sparc : public Sized_target<size, big_endian>
   void
   scan_relocatable_relocs(Symbol_table* symtab,
                          Layout* layout,
-                         Sized_relobj<size, big_endian>* object,
+                         Sized_relobj_file<size, big_endian>* object,
                          unsigned int data_shndx,
                          unsigned int sh_type,
                          const unsigned char* prelocs,
@@ -161,12 +161,33 @@ class Target_sparc : public Sized_target<size, big_endian>
 
   // Return the size of the GOT section.
   section_size_type
-  got_size()
+  got_size() const
   {
     gold_assert(this->got_ != NULL);
     return this->got_->data_size();
   }
 
+  // Return the number of entries in the GOT.
+  unsigned int
+  got_entry_count() const
+  {
+    if (this->got_ == NULL)
+      return 0;
+    return this->got_size() / (size / 8);
+  }
+
+  // Return the number of entries in the PLT.
+  unsigned int
+  plt_entry_count() const;
+
+  // Return the offset of the first non-reserved PLT entry.
+  unsigned int
+  first_plt_entry_offset() const;
+
+  // Return the size of each PLT entry.
+  unsigned int
+  plt_entry_size() const;
+
  private:
 
   // The class which scans relocations.
@@ -177,9 +198,12 @@ class Target_sparc : public Sized_target<size, big_endian>
       : issued_non_pic_error_(false)
     { }
 
+    static inline int
+    get_reference_flags(unsigned int r_type);
+
     inline void
     local(Symbol_table* symtab, Layout* layout, Target_sparc* target,
-         Sized_relobj<size, big_endian>* object,
+         Sized_relobj_file<size, big_endian>* object,
          unsigned int data_shndx,
          Output_section* output_section,
          const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
@@ -187,19 +211,42 @@ class Target_sparc : public Sized_target<size, big_endian>
 
     inline void
     global(Symbol_table* symtab, Layout* layout, Target_sparc* target,
-          Sized_relobj<size, big_endian>* object,
+          Sized_relobj_file<size, big_endian>* object,
           unsigned int data_shndx,
           Output_section* output_section,
           const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
           Symbol* gsym);
 
+    inline bool
+    local_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
+                                       Target_sparc* ,
+                                       Sized_relobj_file<size, big_endian>* ,
+                                               unsigned int ,
+                                       Output_section* ,
+                                       const elfcpp::Rela<size, big_endian>& ,
+                                       unsigned int ,
+                                       const elfcpp::Sym<size, big_endian>&)
+    { return false; }
+
+    inline bool
+    global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
+                                        Target_sparc* ,
+                                        Sized_relobj_file<size, big_endian>* ,
+                                        unsigned int ,
+                                        Output_section* ,
+                                        const elfcpp::Rela<size,
+                                                           big_endian>& ,
+                                        unsigned int , Symbol*)
+    { return false; }
+
+
   private:
     static void
-    unsupported_reloc_local(Sized_relobj<size, big_endian>*,
+    unsupported_reloc_local(Sized_relobj_file<size, big_endian>*,
                            unsigned int r_type);
 
     static void
-    unsupported_reloc_global(Sized_relobj<size, big_endian>*,
+    unsupported_reloc_global(Sized_relobj_file<size, big_endian>*,
                             unsigned int r_type, Symbol*);
 
     static void
@@ -218,7 +265,7 @@ class Target_sparc : public Sized_target<size, big_endian>
   {
    public:
     Relocate()
-      : ignore_gd_add_(false)
+      : ignore_gd_add_(false), reloc_adjust_addr_(NULL)
     { }
 
     ~Relocate()
@@ -255,6 +302,9 @@ class Target_sparc : public Sized_target<size, big_endian>
 
     // Ignore the next relocation which should be R_SPARC_TLS_GD_ADD
     bool ignore_gd_add_;
+
+    // If we hit a reloc at this view address, adjust it back by 4 bytes.
+    unsigned char *reloc_adjust_addr_;
   };
 
   // A class which returns the size required for a relocation type,
@@ -277,7 +327,7 @@ class Target_sparc : public Sized_target<size, big_endian>
   // Create a GOT entry for the TLS module index.
   unsigned int
   got_mod_index_entry(Symbol_table* symtab, Layout* layout,
-                     Sized_relobj<size, big_endian>* object);
+                     Sized_relobj_file<size, big_endian>* object);
 
   // Return the gsym for "__tls_get_addr".  Cache if not already
   // cached.
@@ -305,7 +355,7 @@ class Target_sparc : public Sized_target<size, big_endian>
   // Copy a relocation against a global symbol.
   void
   copy_reloc(Symbol_table* symtab, Layout* layout,
-             Sized_relobj<size, big_endian>* object,
+             Sized_relobj_file<size, big_endian>* object,
             unsigned int shndx, Output_section* output_section,
             Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
   {
@@ -320,6 +370,9 @@ class Target_sparc : public Sized_target<size, big_endian>
   static Target::Target_info sparc_info;
 
   // The types of GOT entries needed for this platform.
+  // These values are exposed to the ABI in an incremental link.
+  // Do not renumber existing values without changing the version
+  // number of the .gnu_incremental_inputs section.
   enum Got_type
   {
     GOT_TYPE_STANDARD = 0,      // GOT entry for a regular symbol
@@ -353,6 +406,7 @@ Target::Target_info Target_sparc<32, true>::sparc_info =
   false,               // has_resolve
   false,               // has_code_fill
   true,                        // is_default_stack_executable
+  false,               // can_icf_inline_merge_sections
   '\0',                        // wrap_char
   "/usr/lib/ld.so.1",  // dynamic_linker
   0x00010000,          // default_text_segment_address
@@ -376,6 +430,7 @@ Target::Target_info Target_sparc<64, true>::sparc_info =
   false,               // has_resolve
   false,               // has_code_fill
   true,                        // is_default_stack_executable
+  false,               // can_icf_inline_merge_sections
   '\0',                        // wrap_char
   "/usr/lib/sparcv9/ld.so.1",  // dynamic_linker
   0x100000,            // default_text_segment_address
@@ -422,7 +477,7 @@ private:
   rela(unsigned char* view,
        unsigned int right_shift,
        typename elfcpp::Elf_types<valsize>::Elf_Addr dst_mask,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Swap<valsize, big_endian>::Valtype addend)
   {
@@ -443,7 +498,7 @@ private:
   static inline void
   rela_ua(unsigned char* view,
          unsigned int right_shift, elfcpp::Elf_Xword dst_mask,
-         const Sized_relobj<size, big_endian>* object,
+         const Sized_relobj_file<size, big_endian>* object,
          const Symbol_value<size>* psymval,
          typename elfcpp::Swap<size, big_endian>::Valtype addend)
   {
@@ -466,7 +521,7 @@ private:
   pcrela(unsigned char* view,
         unsigned int right_shift,
         typename elfcpp::Elf_types<valsize>::Elf_Addr dst_mask,
-        const Sized_relobj<size, big_endian>* object,
+        const Sized_relobj_file<size, big_endian>* object,
         const Symbol_value<size>* psymval,
         typename elfcpp::Swap<size, big_endian>::Valtype addend,
         typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -486,7 +541,7 @@ private:
   template<int valsize>
   static inline void
   pcrela_unaligned(unsigned char* view,
-                  const Sized_relobj<size, big_endian>* object,
+                  const Sized_relobj_file<size, big_endian>* object,
                   const Symbol_value<size>* psymval,
                   typename elfcpp::Swap<size, big_endian>::Valtype addend,
                   typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -506,7 +561,7 @@ public:
   // R_SPARC_WDISP30: (Symbol + Addend - Address) >> 2
   static inline void
   wdisp30(unsigned char* view,
-          const Sized_relobj<size, big_endian>* object,
+          const Sized_relobj_file<size, big_endian>* object,
           const Symbol_value<size>* psymval,
           typename elfcpp::Elf_types<size>::Elf_Addr addend,
           typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -518,7 +573,7 @@ public:
   // R_SPARC_WDISP22: (Symbol + Addend - Address) >> 2
   static inline void
   wdisp22(unsigned char* view,
-          const Sized_relobj<size, big_endian>* object,
+          const Sized_relobj_file<size, big_endian>* object,
           const Symbol_value<size>* psymval,
           typename elfcpp::Elf_types<size>::Elf_Addr addend,
           typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -530,7 +585,7 @@ public:
   // R_SPARC_WDISP19: (Symbol + Addend - Address) >> 2
   static inline void
   wdisp19(unsigned char* view,
-         const Sized_relobj<size, big_endian>* object,
+         const Sized_relobj_file<size, big_endian>* object,
          const Symbol_value<size>* psymval,
          typename elfcpp::Elf_types<size>::Elf_Addr addend,
          typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -542,7 +597,7 @@ public:
   // R_SPARC_WDISP16: (Symbol + Addend - Address) >> 2
   static inline void
   wdisp16(unsigned char* view,
-         const Sized_relobj<size, big_endian>* object,
+         const Sized_relobj_file<size, big_endian>* object,
          const Symbol_value<size>* psymval,
          typename elfcpp::Elf_types<size>::Elf_Addr addend,
          typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -565,7 +620,7 @@ public:
   // R_SPARC_PC22: (Symbol + Addend - Address) >> 10
   static inline void
   pc22(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend,
        typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -577,7 +632,7 @@ public:
   // R_SPARC_PC10: (Symbol + Addend - Address) & 0x3ff
   static inline void
   pc10(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend,
        typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -598,7 +653,7 @@ public:
   // R_SPARC_HI22: (Symbol + Addend) >> 10
   static inline void
   hi22(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -608,7 +663,7 @@ public:
   // R_SPARC_PCPLT22: (Symbol + Addend - Address) >> 10
   static inline void
   pcplt22(unsigned char* view,
-         const Sized_relobj<size, big_endian>* object,
+         const Sized_relobj_file<size, big_endian>* object,
          const Symbol_value<size>* psymval,
          typename elfcpp::Elf_types<size>::Elf_Addr addend,
          typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -629,7 +684,7 @@ public:
   // R_SPARC_LO10: (Symbol + Addend) & 0x3ff
   static inline void
   lo10(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -639,7 +694,7 @@ public:
   // R_SPARC_LO10: (Symbol + Addend) & 0x3ff
   static inline void
   lo10(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend,
        typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -651,7 +706,7 @@ public:
   // R_SPARC_OLO10: ((Symbol + Addend) & 0x3ff) + Addend2
   static inline void
   olo10(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend,
        typename elfcpp::Elf_types<size>::Elf_Addr addend2)
@@ -672,7 +727,7 @@ public:
   // R_SPARC_22: (Symbol + Addend)
   static inline void
   rela32_22(unsigned char* view,
-           const Sized_relobj<size, big_endian>* object,
+           const Sized_relobj_file<size, big_endian>* object,
            const Symbol_value<size>* psymval,
            typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -691,7 +746,7 @@ public:
   // R_SPARC_13: (Symbol + Addend)
   static inline void
   rela32_13(unsigned char* view,
-           const Sized_relobj<size, big_endian>* object,
+           const Sized_relobj_file<size, big_endian>* object,
            const Symbol_value<size>* psymval,
            typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -701,7 +756,7 @@ public:
   // R_SPARC_UA16: (Symbol + Addend)
   static inline void
   ua16(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -711,7 +766,7 @@ public:
   // R_SPARC_UA32: (Symbol + Addend)
   static inline void
   ua32(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -721,7 +776,7 @@ public:
   // R_SPARC_UA64: (Symbol + Addend)
   static inline void
   ua64(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -732,7 +787,7 @@ public:
   // R_SPARC_DISP8: (Symbol + Addend - Address)
   static inline void
   disp8(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend,
        typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -744,7 +799,7 @@ public:
   // R_SPARC_DISP16: (Symbol + Addend - Address)
   static inline void
   disp16(unsigned char* view,
-        const Sized_relobj<size, big_endian>* object,
+        const Sized_relobj_file<size, big_endian>* object,
         const Symbol_value<size>* psymval,
         typename elfcpp::Elf_types<size>::Elf_Addr addend,
         typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -756,7 +811,7 @@ public:
   // R_SPARC_DISP32: (Symbol + Addend - Address)
   static inline void
   disp32(unsigned char* view,
-        const Sized_relobj<size, big_endian>* object,
+        const Sized_relobj_file<size, big_endian>* object,
         const Symbol_value<size>* psymval,
         typename elfcpp::Elf_types<size>::Elf_Addr addend,
         typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -768,7 +823,7 @@ public:
   // R_SPARC_DISP64: (Symbol + Addend - Address)
   static inline void
   disp64(unsigned char* view,
-        const Sized_relobj<size, big_endian>* object,
+        const Sized_relobj_file<size, big_endian>* object,
         const Symbol_value<size>* psymval,
         elfcpp::Elf_Xword addend,
         typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -780,7 +835,7 @@ public:
   // R_SPARC_H44: (Symbol + Addend) >> 22
   static inline void
   h44(unsigned char* view,
-      const Sized_relobj<size, big_endian>* object,
+      const Sized_relobj_file<size, big_endian>* object,
       const Symbol_value<size>* psymval,
       typename elfcpp::Elf_types<size>::Elf_Addr  addend)
   {
@@ -790,7 +845,7 @@ public:
   // R_SPARC_M44: ((Symbol + Addend) >> 12) & 0x3ff
   static inline void
   m44(unsigned char* view,
-      const Sized_relobj<size, big_endian>* object,
+      const Sized_relobj_file<size, big_endian>* object,
       const Symbol_value<size>* psymval,
       typename elfcpp::Elf_types<size>::Elf_Addr  addend)
   {
@@ -800,7 +855,7 @@ public:
   // R_SPARC_L44: (Symbol + Addend) & 0xfff
   static inline void
   l44(unsigned char* view,
-      const Sized_relobj<size, big_endian>* object,
+      const Sized_relobj_file<size, big_endian>* object,
       const Symbol_value<size>* psymval,
       typename elfcpp::Elf_types<size>::Elf_Addr  addend)
   {
@@ -810,7 +865,7 @@ public:
   // R_SPARC_HH22: (Symbol + Addend) >> 42
   static inline void
   hh22(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -820,7 +875,7 @@ public:
   // R_SPARC_PC_HH22: (Symbol + Addend - Address) >> 42
   static inline void
   pc_hh22(unsigned char* view,
-         const Sized_relobj<size, big_endian>* object,
+         const Sized_relobj_file<size, big_endian>* object,
          const Symbol_value<size>* psymval,
          typename elfcpp::Elf_types<size>::Elf_Addr addend,
          typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -832,7 +887,7 @@ public:
   // R_SPARC_HM10: ((Symbol + Addend) >> 32) & 0x3ff
   static inline void
   hm10(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -842,7 +897,7 @@ public:
   // R_SPARC_PC_HM10: ((Symbol + Addend - Address) >> 32) & 0x3ff
   static inline void
   pc_hm10(unsigned char* view,
-         const Sized_relobj<size, big_endian>* object,
+         const Sized_relobj_file<size, big_endian>* object,
          const Symbol_value<size>* psymval,
          typename elfcpp::Elf_types<size>::Elf_Addr addend,
          typename elfcpp::Elf_types<size>::Elf_Addr address)
@@ -854,7 +909,7 @@ public:
   // R_SPARC_11: (Symbol + Addend)
   static inline void
   rela32_11(unsigned char* view,
-           const Sized_relobj<size, big_endian>* object,
+           const Sized_relobj_file<size, big_endian>* object,
            const Symbol_value<size>* psymval,
            typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -864,7 +919,7 @@ public:
   // R_SPARC_10: (Symbol + Addend)
   static inline void
   rela32_10(unsigned char* view,
-           const Sized_relobj<size, big_endian>* object,
+           const Sized_relobj_file<size, big_endian>* object,
            const Symbol_value<size>* psymval,
            typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -874,7 +929,7 @@ public:
   // R_SPARC_7: (Symbol + Addend)
   static inline void
   rela32_7(unsigned char* view,
-          const Sized_relobj<size, big_endian>* object,
+          const Sized_relobj_file<size, big_endian>* object,
           const Symbol_value<size>* psymval,
           typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -884,7 +939,7 @@ public:
   // R_SPARC_6: (Symbol + Addend)
   static inline void
   rela32_6(unsigned char* view,
-          const Sized_relobj<size, big_endian>* object,
+          const Sized_relobj_file<size, big_endian>* object,
           const Symbol_value<size>* psymval,
           typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -894,7 +949,7 @@ public:
   // R_SPARC_5: (Symbol + Addend)
   static inline void
   rela32_5(unsigned char* view,
-          const Sized_relobj<size, big_endian>* object,
+          const Sized_relobj_file<size, big_endian>* object,
           const Symbol_value<size>* psymval,
           typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -951,7 +1006,7 @@ public:
   // R_SPARC_HIX22: ((Symbol + Addend) ^ 0xffffffffffffffff) >> 10
   static inline void
   hix22(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -992,7 +1047,7 @@ public:
   // R_SPARC_LOX10: ((Symbol + Addend) & 0x3ff) | 0x1c00
   static inline void
   lox10(unsigned char* view,
-       const Sized_relobj<size, big_endian>* object,
+       const Sized_relobj_file<size, big_endian>* object,
        const Symbol_value<size>* psymval,
        typename elfcpp::Elf_types<size>::Elf_Addr addend)
   {
@@ -1022,12 +1077,10 @@ Target_sparc<size, big_endian>::got_section(Symbol_table* symtab,
 
       this->got_ = new Output_data_got<size, big_endian>();
 
-      Output_section* os;
-      os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
-                                          (elfcpp::SHF_ALLOC
-                                           | elfcpp::SHF_WRITE),
-                                          this->got_, false, true, false,
-                                          false);
+      layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
+                                     (elfcpp::SHF_ALLOC
+                                      | elfcpp::SHF_WRITE),
+                                     this->got_, ORDER_RELRO, true);
 
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
       symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
@@ -1053,8 +1106,8 @@ Target_sparc<size, big_endian>::rela_dyn_section(Layout* layout)
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-                                     elfcpp::SHF_ALLOC, this->rela_dyn_, true,
-                                     false, false, false);
+                                     elfcpp::SHF_ALLOC, this->rela_dyn_,
+                                     ORDER_DYNAMIC_RELOCS, false);
     }
   return this->rela_dyn_;
 }
@@ -1079,6 +1132,21 @@ class Output_data_plt_sparc : public Output_section_data
     return this->rel_;
   }
 
+  // Return the number of PLT entries.
+  unsigned int
+  entry_count() const
+  { return this->count_; }
+
+  // Return the offset of the first non-reserved PLT entry.
+  static unsigned int
+  first_plt_entry_offset()
+  { return 4 * base_plt_entry_size; }
+
+  // Return the size of a PLT entry.
+  static unsigned int
+  get_plt_entry_size()
+  { return base_plt_entry_size; }
+
  protected:
   void do_adjust_output_section(Output_section* os);
 
@@ -1156,8 +1224,8 @@ Output_data_plt_sparc<size, big_endian>::Output_data_plt_sparc(Layout* layout)
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-                                 elfcpp::SHF_ALLOC, this->rel_, true,
-                                 false, false, false);
+                                 elfcpp::SHF_ALLOC, this->rel_,
+                                 ORDER_DYNAMIC_PLT_RELOCS, false);
 }
 
 template<int size, bool big_endian>
@@ -1379,7 +1447,7 @@ Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR
                                       | elfcpp::SHF_WRITE),
-                                     this->plt_, false, false, false, false);
+                                     this->plt_, ORDER_PLT, false);
 
       // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
       symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
@@ -1394,13 +1462,43 @@ Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
   this->plt_->add_entry(gsym);
 }
 
+// Return the number of entries in the PLT.
+
+template<int size, bool big_endian>
+unsigned int
+Target_sparc<size, big_endian>::plt_entry_count() const
+{
+  if (this->plt_ == NULL)
+    return 0;
+  return this->plt_->entry_count();
+}
+
+// Return the offset of the first non-reserved PLT entry.
+
+template<int size, bool big_endian>
+unsigned int
+Target_sparc<size, big_endian>::first_plt_entry_offset() const
+{
+  return Output_data_plt_sparc<size, big_endian>::first_plt_entry_offset();
+}
+
+// Return the size of each PLT entry.
+
+template<int size, bool big_endian>
+unsigned int
+Target_sparc<size, big_endian>::plt_entry_size() const
+{
+  return Output_data_plt_sparc<size, big_endian>::get_plt_entry_size();
+}
+
 // Create a GOT entry for the TLS module index.
 
 template<int size, bool big_endian>
 unsigned int
-Target_sparc<size, big_endian>::got_mod_index_entry(Symbol_table* symtab,
-                                                   Layout* layout,
-                                                   Sized_relobj<size, big_endian>* object)
+Target_sparc<size, big_endian>::got_mod_index_entry(
+     Symbol_table* symtab,
+     Layout* layout,
+     Sized_relobj_file<size, big_endian>* object)
 {
   if (this->got_mod_index_offset_ == -1U)
     {
@@ -1487,6 +1585,119 @@ optimize_tls_reloc(bool is_final, int r_type)
     }
 }
 
+// Get the Reference_flags for a particular relocation.
+
+template<int size, bool big_endian>
+int
+Target_sparc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
+{
+  r_type &= 0xff;
+  switch (r_type)
+    {
+    case elfcpp::R_SPARC_NONE:
+    case elfcpp::R_SPARC_REGISTER:
+    case elfcpp::R_SPARC_GNU_VTINHERIT:
+    case elfcpp::R_SPARC_GNU_VTENTRY:
+      // No symbol reference.
+      return 0;
+
+    case elfcpp::R_SPARC_UA64:
+    case elfcpp::R_SPARC_64:
+    case elfcpp::R_SPARC_HIX22:
+    case elfcpp::R_SPARC_LOX10:
+    case elfcpp::R_SPARC_H44:
+    case elfcpp::R_SPARC_M44:
+    case elfcpp::R_SPARC_L44:
+    case elfcpp::R_SPARC_HH22:
+    case elfcpp::R_SPARC_HM10:
+    case elfcpp::R_SPARC_LM22:
+    case elfcpp::R_SPARC_HI22:
+    case elfcpp::R_SPARC_LO10:
+    case elfcpp::R_SPARC_OLO10:
+    case elfcpp::R_SPARC_UA32:
+    case elfcpp::R_SPARC_32:
+    case elfcpp::R_SPARC_UA16:
+    case elfcpp::R_SPARC_16:
+    case elfcpp::R_SPARC_11:
+    case elfcpp::R_SPARC_10:
+    case elfcpp::R_SPARC_8:
+    case elfcpp::R_SPARC_7:
+    case elfcpp::R_SPARC_6:
+    case elfcpp::R_SPARC_5:
+      return Symbol::ABSOLUTE_REF;
+
+    case elfcpp::R_SPARC_DISP8:
+    case elfcpp::R_SPARC_DISP16:
+    case elfcpp::R_SPARC_DISP32:
+    case elfcpp::R_SPARC_DISP64:
+    case elfcpp::R_SPARC_PC_HH22:
+    case elfcpp::R_SPARC_PC_HM10:
+    case elfcpp::R_SPARC_PC_LM22:
+    case elfcpp::R_SPARC_PC10:
+    case elfcpp::R_SPARC_PC22:
+    case elfcpp::R_SPARC_WDISP30:
+    case elfcpp::R_SPARC_WDISP22:
+    case elfcpp::R_SPARC_WDISP19:
+    case elfcpp::R_SPARC_WDISP16:
+      return Symbol::RELATIVE_REF;
+
+    case elfcpp::R_SPARC_PLT64:
+    case elfcpp::R_SPARC_PLT32:
+    case elfcpp::R_SPARC_HIPLT22:
+    case elfcpp::R_SPARC_LOPLT10:
+    case elfcpp::R_SPARC_PCPLT10:
+      return Symbol::FUNCTION_CALL | Symbol::ABSOLUTE_REF;
+
+    case elfcpp::R_SPARC_PCPLT32:
+    case elfcpp::R_SPARC_PCPLT22:
+    case elfcpp::R_SPARC_WPLT30:
+      return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
+
+    case elfcpp::R_SPARC_GOTDATA_OP:
+    case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
+    case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+    case elfcpp::R_SPARC_GOT10:
+    case elfcpp::R_SPARC_GOT13:
+    case elfcpp::R_SPARC_GOT22:
+      // Absolute in GOT.
+      return Symbol::ABSOLUTE_REF;
+
+    case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic
+    case elfcpp::R_SPARC_TLS_GD_LO10:
+    case elfcpp::R_SPARC_TLS_GD_ADD:
+    case elfcpp::R_SPARC_TLS_GD_CALL:
+    case elfcpp::R_SPARC_TLS_LDM_HI22: // Local-dynamic
+    case elfcpp::R_SPARC_TLS_LDM_LO10:
+    case elfcpp::R_SPARC_TLS_LDM_ADD:
+    case elfcpp::R_SPARC_TLS_LDM_CALL:
+    case elfcpp::R_SPARC_TLS_LDO_HIX22:        // Alternate local-dynamic
+    case elfcpp::R_SPARC_TLS_LDO_LOX10:
+    case elfcpp::R_SPARC_TLS_LDO_ADD:
+    case elfcpp::R_SPARC_TLS_LE_HIX22:
+    case elfcpp::R_SPARC_TLS_LE_LOX10:
+    case elfcpp::R_SPARC_TLS_IE_HI22:  // Initial-exec
+    case elfcpp::R_SPARC_TLS_IE_LO10:
+    case elfcpp::R_SPARC_TLS_IE_LD:
+    case elfcpp::R_SPARC_TLS_IE_LDX:
+    case elfcpp::R_SPARC_TLS_IE_ADD:
+      return Symbol::TLS_REF;
+
+    case elfcpp::R_SPARC_COPY:
+    case elfcpp::R_SPARC_GLOB_DAT:
+    case elfcpp::R_SPARC_JMP_SLOT:
+    case elfcpp::R_SPARC_RELATIVE:
+    case elfcpp::R_SPARC_TLS_DTPMOD64:
+    case elfcpp::R_SPARC_TLS_DTPMOD32:
+    case elfcpp::R_SPARC_TLS_DTPOFF64:
+    case elfcpp::R_SPARC_TLS_DTPOFF32:
+    case elfcpp::R_SPARC_TLS_TPOFF64:
+    case elfcpp::R_SPARC_TLS_TPOFF32:
+    default:
+      // Not expected.  We will give an error later.
+      return 0;
+    }
+}
+
 // Generate a PLT entry slot for a call to __tls_get_addr
 template<int size, bool big_endian>
 void
@@ -1504,7 +1715,7 @@ Target_sparc<size, big_endian>::Scan::generate_tls_call(Symbol_table* symtab,
 template<int size, bool big_endian>
 void
 Target_sparc<size, big_endian>::Scan::unsupported_reloc_local(
-                       Sized_relobj<size, big_endian>* object,
+                       Sized_relobj_file<size, big_endian>* object,
                        unsigned int r_type)
 {
   gold_error(_("%s: unsupported reloc %u against local symbol"),
@@ -1611,7 +1822,7 @@ Target_sparc<size, big_endian>::Scan::local(
                        Symbol_table* symtab,
                        Layout* layout,
                        Target_sparc<size, big_endian>* target,
-                       Sized_relobj<size, big_endian>* object,
+                       Sized_relobj_file<size, big_endian>* object,
                        unsigned int data_shndx,
                        Output_section* output_section,
                        const elfcpp::Rela<size, big_endian>& reloc,
@@ -1644,7 +1855,7 @@ Target_sparc<size, big_endian>::Scan::local(
           rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE,
                                       output_section, data_shndx,
                                       reloc.get_r_offset(),
-                                      reloc.get_r_addend());
+                                      reloc.get_r_addend(), false);
         }
       break;
 
@@ -1686,25 +1897,17 @@ Target_sparc<size, big_endian>::Scan::local(
             }
           else
             {
-             unsigned int shndx = lsym.get_st_shndx();
-             bool is_ordinary;
-
               gold_assert(lsym.get_st_value() == 0);
-             shndx = object->adjust_sym_shndx(r_sym, shndx,
-                                              &is_ordinary);
-             if (!is_ordinary)
-               object->error(_("section symbol %u has bad shndx %u"),
-                             r_sym, shndx);
-             else
-               rela_dyn->add_local_section(object, shndx,
-                                           r_type, output_section,
-                                           data_shndx, reloc.get_r_offset(),
-                                           reloc.get_r_addend());
+             rela_dyn->add_symbolless_local_addend(object, r_sym, orig_r_type,
+                                                   output_section, data_shndx,
+                                                   reloc.get_r_offset(),
+                                                   reloc.get_r_addend());
             }
         }
       break;
 
     case elfcpp::R_SPARC_WDISP30:
+    case elfcpp::R_SPARC_WPLT30:
     case elfcpp::R_SPARC_WDISP22:
     case elfcpp::R_SPARC_WDISP19:
     case elfcpp::R_SPARC_WDISP16:
@@ -1743,7 +1946,7 @@ Target_sparc<size, big_endian>::Scan::local(
                object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
                rela_dyn->add_local_relative(object, r_sym,
                                             elfcpp::R_SPARC_RELATIVE,
-                                            got, off, 0);
+                                            got, off, 0, false);
              }
          }
        else
@@ -1795,14 +1998,14 @@ Target_sparc<size, big_endian>::Scan::local(
                  object->error(_("local symbol %u has bad shndx %u"),
                                r_sym, shndx);
                else
-                 got->add_local_pair_with_rela(object, r_sym, 
-                                               lsym.get_st_shndx(),
-                                               GOT_TYPE_TLS_PAIR,
-                                               target->rela_dyn_section(layout),
-                                               (size == 64
-                                                ? elfcpp::R_SPARC_TLS_DTPMOD64
-                                                : elfcpp::R_SPARC_TLS_DTPMOD32),
-                                                0);
+                 got->add_local_pair_with_rel(object, r_sym, 
+                                              lsym.get_st_shndx(),
+                                              GOT_TYPE_TLS_PAIR,
+                                              target->rela_dyn_section(layout),
+                                              (size == 64
+                                               ? elfcpp::R_SPARC_TLS_DTPMOD64
+                                               : elfcpp::R_SPARC_TLS_DTPMOD32),
+                                              0);
                if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
                  generate_tls_call(symtab, layout, target);
              }
@@ -1847,13 +2050,15 @@ Target_sparc<size, big_endian>::Scan::local(
                if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_OFFSET))
                  {
                    Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+                   unsigned int off = got->add_constant(0);
+
+                   object->set_local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET, off);
 
-                   got->add_local_with_rela(object, r_sym,
-                                            GOT_TYPE_TLS_OFFSET,
-                                            rela_dyn,
-                                            (size == 64 ?
-                                             elfcpp::R_SPARC_TLS_TPOFF64 :
-                                             elfcpp::R_SPARC_TLS_TPOFF32));
+                   rela_dyn->add_symbolless_local_addend(object, r_sym,
+                                                         (size == 64 ?
+                                                          elfcpp::R_SPARC_TLS_TPOFF64 :
+                                                          elfcpp::R_SPARC_TLS_TPOFF32),
+                                                         got, off, 0);
                  }
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
@@ -1869,9 +2074,9 @@ Target_sparc<size, big_endian>::Scan::local(
                 gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
                 unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
                 Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-                rela_dyn->add_local(object, r_sym, r_type,
-                                   output_section, data_shndx,
-                                   reloc.get_r_offset(), 0);
+                rela_dyn->add_symbolless_local_addend(object, r_sym, r_type,
+                                                     output_section, data_shndx,
+                                                     reloc.get_r_offset(), 0);
              }
            break;
          }
@@ -1905,7 +2110,7 @@ Target_sparc<size, big_endian>::Scan::local(
 template<int size, bool big_endian>
 void
 Target_sparc<size, big_endian>::Scan::unsupported_reloc_global(
-                       Sized_relobj<size, big_endian>* object,
+                       Sized_relobj_file<size, big_endian>* object,
                        unsigned int r_type,
                        Symbol* gsym)
 {
@@ -1921,7 +2126,7 @@ Target_sparc<size, big_endian>::Scan::global(
                                Symbol_table* symtab,
                                Layout* layout,
                                Target_sparc<size, big_endian>* target,
-                               Sized_relobj<size, big_endian>* object,
+                               Sized_relobj_file<size, big_endian>* object,
                                unsigned int data_shndx,
                                Output_section* output_section,
                                const elfcpp::Rela<size, big_endian>& reloc,
@@ -1985,10 +2190,7 @@ Target_sparc<size, big_endian>::Scan::global(
        if (gsym->needs_plt_entry())
          target->make_plt_entry(symtab, layout, gsym);
        // Make a dynamic relocation if necessary.
-       int flags = Symbol::NON_PIC_REF;
-       if (gsym->type() == elfcpp::STT_FUNC)
-         flags |= Symbol::FUNCTION_CALL;
-       if (gsym->needs_dynamic_reloc(flags))
+       if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
          {
            if (gsym->may_need_copy_reloc())
              {
@@ -2044,8 +2246,40 @@ Target_sparc<size, big_endian>::Scan::global(
               gsym->set_needs_dynsym_value();
           }
         // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
+        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
           {
+           unsigned int r_off = reloc.get_r_offset();
+
+           // The assembler can sometimes emit unaligned relocations
+           // for dwarf2 cfi directives. 
+           switch (r_type)
+             {
+             case elfcpp::R_SPARC_16:
+               if (r_off & 0x1)
+                 orig_r_type = r_type = elfcpp::R_SPARC_UA16;
+               break;
+             case elfcpp::R_SPARC_32:
+               if (r_off & 0x3)
+                 orig_r_type = r_type = elfcpp::R_SPARC_UA32;
+               break;
+             case elfcpp::R_SPARC_64:
+               if (r_off & 0x7)
+                 orig_r_type = r_type = elfcpp::R_SPARC_UA64;
+               break;
+             case elfcpp::R_SPARC_UA16:
+               if (!(r_off & 0x1))
+                 orig_r_type = r_type = elfcpp::R_SPARC_16;
+               break;
+             case elfcpp::R_SPARC_UA32:
+               if (!(r_off & 0x3))
+                 orig_r_type = r_type = elfcpp::R_SPARC_32;
+               break;
+             case elfcpp::R_SPARC_UA64:
+               if (!(r_off & 0x7))
+                 orig_r_type = r_type = elfcpp::R_SPARC_64;
+               break;
+             }
+
             if (gsym->may_need_copy_reloc())
               {
                target->copy_reloc(symtab, layout, object,
@@ -2066,10 +2300,19 @@ Target_sparc<size, big_endian>::Scan::global(
                 Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 
                check_non_pic(object, r_type);
-               rela_dyn->add_global(gsym, orig_r_type, output_section,
-                                    object, data_shndx,
-                                    reloc.get_r_offset(),
-                                    reloc.get_r_addend());
+               if (gsym->is_from_dynobj()
+                   || gsym->is_undefined()
+                   || gsym->is_preemptible())
+                 rela_dyn->add_global(gsym, orig_r_type, output_section,
+                                      object, data_shndx,
+                                      reloc.get_r_offset(),
+                                      reloc.get_r_addend());
+               else
+                 rela_dyn->add_symbolless_global_addend(gsym, orig_r_type,
+                                                        output_section,
+                                                        object, data_shndx,
+                                                        reloc.get_r_offset(),
+                                                        reloc.get_r_addend());
               }
           }
       }
@@ -2096,8 +2339,8 @@ Target_sparc<size, big_endian>::Scan::global(
             if (gsym->is_from_dynobj()
                 || gsym->is_undefined()
                 || gsym->is_preemptible())
-              got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
-                                        elfcpp::R_SPARC_GLOB_DAT);
+              got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
+                                      elfcpp::R_SPARC_GLOB_DAT);
             else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
               {
                unsigned int off = got->add_constant(0);
@@ -2146,14 +2389,14 @@ Target_sparc<size, big_endian>::Scan::global(
                 // dtv-relative offset.
                 Output_data_got<size, big_endian>* got
                     = target->got_section(symtab, layout);
-                got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR,
-                                               target->rela_dyn_section(layout),
-                                              (size == 64 ?
-                                               elfcpp::R_SPARC_TLS_DTPMOD64 :
-                                               elfcpp::R_SPARC_TLS_DTPMOD32),
-                                              (size == 64 ?
-                                               elfcpp::R_SPARC_TLS_DTPOFF64 :
-                                               elfcpp::R_SPARC_TLS_DTPOFF32));
+                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
+                                             target->rela_dyn_section(layout),
+                                             (size == 64
+                                              ? elfcpp::R_SPARC_TLS_DTPMOD64
+                                              : elfcpp::R_SPARC_TLS_DTPMOD32),
+                                             (size == 64
+                                              ? elfcpp::R_SPARC_TLS_DTPOFF64
+                                              : elfcpp::R_SPARC_TLS_DTPOFF32));
 
                // Emit R_SPARC_WPLT30 against "__tls_get_addr"
                if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
@@ -2164,11 +2407,11 @@ Target_sparc<size, big_endian>::Scan::global(
                 // Create a GOT entry for the tp-relative offset.
                 Output_data_got<size, big_endian>* got
                     = target->got_section(symtab, layout);
-                got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
-                                          target->rela_dyn_section(layout),
-                                         (size == 64 ?
-                                          elfcpp::R_SPARC_TLS_TPOFF64 :
-                                          elfcpp::R_SPARC_TLS_TPOFF32));
+                got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+                                        target->rela_dyn_section(layout),
+                                        (size == 64 ?
+                                         elfcpp::R_SPARC_TLS_TPOFF64 :
+                                         elfcpp::R_SPARC_TLS_TPOFF32));
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_global(object, r_type, gsym);
@@ -2201,10 +2444,10 @@ Target_sparc<size, big_endian>::Scan::global(
            if (parameters->options().shared())
              {
                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-               rela_dyn->add_global(gsym, orig_r_type,
-                                    output_section, object,
-                                    data_shndx, reloc.get_r_offset(),
-                                    0);
+               rela_dyn->add_symbolless_global_addend(gsym, orig_r_type,
+                                                      output_section, object,
+                                                      data_shndx, reloc.get_r_offset(),
+                                                      0);
              }
            break;
 
@@ -2219,11 +2462,11 @@ Target_sparc<size, big_endian>::Scan::global(
                // Create a GOT entry for the tp-relative offset.
                Output_data_got<size, big_endian>* got
                  = target->got_section(symtab, layout);
-               got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
-                                         target->rela_dyn_section(layout),
-                                         (size == 64 ?
-                                          elfcpp::R_SPARC_TLS_TPOFF64 :
-                                          elfcpp::R_SPARC_TLS_TPOFF32));
+               got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+                                        target->rela_dyn_section(layout),
+                                        (size == 64
+                                         ? elfcpp::R_SPARC_TLS_TPOFF64
+                                         : elfcpp::R_SPARC_TLS_TPOFF32));
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_global(object, r_type, gsym);
@@ -2261,7 +2504,7 @@ void
 Target_sparc<size, big_endian>::gc_process_relocs(
                        Symbol_table* symtab,
                        Layout* layout,
-                       Sized_relobj<size, big_endian>* object,
+                       Sized_relobj_file<size, big_endian>* object,
                        unsigned int data_shndx,
                        unsigned int,
                        const unsigned char* prelocs,
@@ -2274,7 +2517,8 @@ Target_sparc<size, big_endian>::gc_process_relocs(
   typedef Target_sparc<size, big_endian> Sparc;
   typedef typename Target_sparc<size, big_endian>::Scan Scan;
 
-  gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>(
+  gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan,
+                         typename Target_sparc::Relocatable_size_for_reloc>(
     symtab,
     layout,
     this,
@@ -2295,7 +2539,7 @@ void
 Target_sparc<size, big_endian>::scan_relocs(
                        Symbol_table* symtab,
                        Layout* layout,
-                       Sized_relobj<size, big_endian>* object,
+                       Sized_relobj_file<size, big_endian>* object,
                        unsigned int data_shndx,
                        unsigned int sh_type,
                        const unsigned char* prelocs,
@@ -2381,25 +2625,15 @@ Target_sparc<size, big_endian>::Relocate::relocate(
          return false;
        }
     }
+  if (this->reloc_adjust_addr_ == view)
+    view -= 4;
 
   typedef Sparc_relocate_functions<size, big_endian> Reloc;
 
   // Pick the value to use for symbols defined in shared objects.
   Symbol_value<size> symval;
   if (gsym != NULL
-      && gsym->use_plt_offset(r_type == elfcpp::R_SPARC_DISP8
-                             || r_type == elfcpp::R_SPARC_DISP16
-                             || r_type == elfcpp::R_SPARC_DISP32
-                             || r_type == elfcpp::R_SPARC_DISP64
-                             || r_type == elfcpp::R_SPARC_PC_HH22
-                             || r_type == elfcpp::R_SPARC_PC_HM10
-                             || r_type == elfcpp::R_SPARC_PC_LM22
-                             || r_type == elfcpp::R_SPARC_PC10
-                             || r_type == elfcpp::R_SPARC_PC22
-                             || r_type == elfcpp::R_SPARC_WDISP30
-                             || r_type == elfcpp::R_SPARC_WDISP22
-                             || r_type == elfcpp::R_SPARC_WDISP19
-                             || r_type == elfcpp::R_SPARC_WDISP16))
+      && gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
     {
       elfcpp::Elf_Xword value;
 
@@ -2410,13 +2644,12 @@ Target_sparc<size, big_endian>::Relocate::relocate(
       psymval = &symval;
     }
 
-  const Sized_relobj<size, big_endian>* object = relinfo->object;
+  const Sized_relobj_file<size, big_endian>* object = relinfo->object;
   const elfcpp::Elf_Xword addend = rela.get_r_addend();
 
   // Get the GOT offset if needed.  Unlike i386 and x86_64, our GOT
   // pointer points to the beginning, not the end, of the table.
   // So we just use the plain offset.
-  bool have_got_offset = false;
   unsigned int got_offset = 0;
   switch (r_type)
     {
@@ -2437,7 +2670,6 @@ Target_sparc<size, big_endian>::Relocate::relocate(
           gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
           got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
         }
-      have_got_offset = true;
       break;
 
     default:
@@ -2755,7 +2987,7 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
 {
   Output_segment* tls_segment = relinfo->layout->tls_segment();
   typedef Sparc_relocate_functions<size, big_endian> Reloc;
-  const Sized_relobj<size, big_endian>* object = relinfo->object;
+  const Sized_relobj_file<size, big_endian>* object = relinfo->object;
   typedef typename elfcpp::Swap<32, true>::Valtype Insntype;
 
   const elfcpp::Elf_Xword addend = rela.get_r_addend();
@@ -2855,7 +3087,7 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
                  // The compiler can put the TLS_GD_ADD instruction
                  // into the delay slot of the call.  If so, we need
                  // to transpose the two instructions so that the
-                 // the new sequence works properly.
+                 // new sequence works properly.
                  //
                  // The test we use is if the instruction in the
                  // delay slot is an add with destination register
@@ -2874,7 +3106,15 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
                      wv += 1;
                      this->ignore_gd_add_ = true;
                    }
-
+                 else
+                   {
+                     // Even if the delay slot isn't the TLS_GD_ADD
+                     // instruction, we still have to handle the case
+                     // where it sets up %o0 in some other way.
+                     elfcpp::Swap<32, true>::writeval(wv, val);
+                     wv += 1;
+                     this->reloc_adjust_addr_ = view + 4;
+                   }
                  // call __tls_get_addr --> add %g7, %o0, %o0
                  elfcpp::Swap<32, true>::writeval(wv, 0x9001c008);
                  break;
@@ -3168,7 +3408,7 @@ void
 Target_sparc<size, big_endian>::scan_relocatable_relocs(
                        Symbol_table* symtab,
                        Layout* layout,
-                       Sized_relobj<size, big_endian>* object,
+                       Sized_relobj_file<size, big_endian>* object,
                        unsigned int data_shndx,
                        unsigned int sh_type,
                        const unsigned char* prelocs,
@@ -3254,7 +3494,8 @@ class Target_selector_sparc : public Target_selector
 public:
   Target_selector_sparc()
     : Target_selector(elfcpp::EM_NONE, size, big_endian,
-                     (size == 64 ? "elf64-sparc" : "elf32-sparc"))
+                     (size == 64 ? "elf64-sparc" : "elf32-sparc"),
+                     (size == 64 ? "elf64_sparc" : "elf32_sparc"))
   { }
 
   Target* do_recognize(int machine, int, int)