gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gold / sparc.cc
index a85bb8118bf41c0d32b884152fccaed1e5114ef6..e73970afd779c3af6336947a739d7de71ac068b7 100644 (file)
@@ -1,6 +1,6 @@
 // sparc.cc -- sparc target support for gold.
 
-// Copyright 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+// Copyright (C) 2008-2020 Free Software Foundation, Inc.
 // Written by David S. Miller <davem@davemloft.net>.
 
 // This file is part of gold.
@@ -59,27 +59,31 @@ class Target_sparc : public Sized_target<size, big_endian>
   Target_sparc()
     : Sized_target<size, big_endian>(&sparc_info),
       got_(NULL), plt_(NULL), rela_dyn_(NULL), rela_ifunc_(NULL),
-      copy_relocs_(elfcpp::R_SPARC_COPY), dynbss_(NULL),
+      copy_relocs_(elfcpp::R_SPARC_COPY),
       got_mod_index_offset_(-1U), tls_get_addr_sym_(NULL),
       elf_machine_(sparc_info.machine_code), elf_flags_(0),
-      elf_flags_set_(false)
+      elf_flags_set_(false), register_syms_()
   {
   }
 
-  // Process the relocations to determine unreferenced sections for 
+  // Make a new symbol table entry.
+  Sized_symbol<size>*
+  make_symbol(const char*, elfcpp::STT, Object*, unsigned int, uint64_t);
+
+  // Process the relocations to determine unreferenced sections for
   // garbage collection.
   void
   gc_process_relocs(Symbol_table* symtab,
-                   Layout* layout,
-                   Sized_relobj_file<size, big_endian>* object,
-                   unsigned int data_shndx,
-                   unsigned int sh_type,
-                   const unsigned char* prelocs,
-                   size_t reloc_count,
-                   Output_section* output_section,
-                   bool needs_special_offset_handling,
-                   size_t local_symbol_count,
-                   const unsigned char* plocal_symbols);
+                   Layout* layout,
+                   Sized_relobj_file<size, big_endian>* object,
+                   unsigned int data_shndx,
+                   unsigned int sh_type,
+                   const unsigned char* prelocs,
+                   size_t reloc_count,
+                   Output_section* output_section,
+                   bool needs_special_offset_handling,
+                   size_t local_symbol_count,
+                   const unsigned char* plocal_symbols);
 
   // Scan the relocations to look for symbol adjustments.
   void
@@ -131,30 +135,40 @@ class Target_sparc : public Sized_target<size, big_endian>
                          const unsigned char* plocal_symbols,
                          Relocatable_relocs*);
 
-  // Relocate a section during a relocatable link.
+  // Scan the relocs for --emit-relocs.
   void
-  relocate_for_relocatable(const Relocate_info<size, big_endian>*,
-                          unsigned int sh_type,
-                          const unsigned char* prelocs,
-                          size_t reloc_count,
-                          Output_section* output_section,
-                          off_t offset_in_output_section,
-                          const Relocatable_relocs*,
-                          unsigned char* view,
-                          typename elfcpp::Elf_types<size>::Elf_Addr view_address,
-                          section_size_type view_size,
-                          unsigned char* reloc_view,
-                          section_size_type reloc_view_size);
+  emit_relocs_scan(Symbol_table* symtab,
+                  Layout* layout,
+                  Sized_relobj_file<size, big_endian>* object,
+                  unsigned int data_shndx,
+                  unsigned int sh_type,
+                  const unsigned char* prelocs,
+                  size_t reloc_count,
+                  Output_section* output_section,
+                  bool needs_special_offset_handling,
+                  size_t local_symbol_count,
+                  const unsigned char* plocal_syms,
+                  Relocatable_relocs* rr);
+
+  // Emit relocations for a section.
+  void
+  relocate_relocs(const Relocate_info<size, big_endian>*,
+                 unsigned int sh_type,
+                 const unsigned char* prelocs,
+                 size_t reloc_count,
+                 Output_section* output_section,
+                 typename elfcpp::Elf_types<size>::Elf_Off
+                    offset_in_output_section,
+                 unsigned char* view,
+                 typename elfcpp::Elf_types<size>::Elf_Addr view_address,
+                 section_size_type view_size,
+                 unsigned char* reloc_view,
+                 section_size_type reloc_view_size);
+
   // Return whether SYM is defined by the ABI.
   bool
   do_is_defined_by_abi(const Symbol* sym) const
-  {
-    // XXX Really need to support this better...
-    if (sym->type() == elfcpp::STT_SPARC_REGISTER)
-      return 1;
-
-    return strcmp(sym->name(), "___tls_get_addr") == 0;
-  }
+  { return strcmp(sym->name(), "___tls_get_addr") == 0; }
 
   // Return the PLT address to use for a global symbol.
   uint64_t
@@ -215,7 +229,7 @@ class Target_sparc : public Sized_target<size, big_endian>
                     const elfcpp::Ehdr<size, big_endian>& ehdr);
 
   void
-  do_adjust_elf_header(unsigned char* view, int len) const;
+  do_adjust_elf_header(unsigned char* view, int len);
 
  private:
 
@@ -236,7 +250,8 @@ class Target_sparc : public Sized_target<size, big_endian>
          unsigned int data_shndx,
          Output_section* output_section,
          const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
-         const elfcpp::Sym<size, big_endian>& lsym);
+         const elfcpp::Sym<size, big_endian>& lsym,
+         bool is_discarded);
 
     inline void
     global(Symbol_table* symtab, Layout* layout, Target_sparc* target,
@@ -248,24 +263,24 @@ class Target_sparc : public Sized_target<size, big_endian>
 
     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>& ,
+                                       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>&)
+                                       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*)
+                                        Target_sparc* ,
+                                        Sized_relobj_file<size, big_endian>* ,
+                                        unsigned int ,
+                                        Output_section* ,
+                                        const elfcpp::Rela<size,
+                                                           big_endian>& ,
+                                        unsigned int , Symbol*)
     { return false; }
 
 
@@ -313,20 +328,17 @@ class Target_sparc : public Sized_target<size, big_endian>
     // Do a relocation.  Return false if the caller should not issue
     // any warnings about this relocation.
     inline bool
-    relocate(const Relocate_info<size, big_endian>*, Target_sparc*,
-            Output_section*, size_t relnum,
-            const elfcpp::Rela<size, big_endian>&,
-            unsigned int r_type, const Sized_symbol<size>*,
-            const Symbol_value<size>*,
-            unsigned char*,
-            typename elfcpp::Elf_types<size>::Elf_Addr,
+    relocate(const Relocate_info<size, big_endian>*, unsigned int,
+            Target_sparc*, Output_section*, size_t, const unsigned char*,
+            const Sized_symbol<size>*, const Symbol_value<size>*,
+            unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
             section_size_type);
 
    private:
     // Do a TLS relocation.
     inline void
     relocate_tls(const Relocate_info<size, big_endian>*, Target_sparc* target,
-                 size_t relnum, const elfcpp::Rela<size, big_endian>&,
+                size_t relnum, const elfcpp::Rela<size, big_endian>&,
                 unsigned int r_type, const Sized_symbol<size>*,
                 const Symbol_value<size>*,
                 unsigned char*,
@@ -346,15 +358,6 @@ class Target_sparc : public Sized_target<size, big_endian>
     unsigned char *reloc_adjust_addr_;
   };
 
-  // A class which returns the size required for a relocation type,
-  // used while scanning relocs during a relocatable link.
-  class Relocatable_size_for_reloc
-  {
-   public:
-    unsigned int
-    get_size_for_reloc(unsigned int, Relobj*);
-  };
-
   // Get the GOT section, creating it if necessary.
   Output_data_got<size, big_endian>*
   got_section(Symbol_table*, Layout*);
@@ -408,14 +411,17 @@ 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_file<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)
   {
+    unsigned int r_type = elfcpp::elf_r_type<size>(reloc.get_r_info());
     this->copy_relocs_.copy_reloc(symtab, layout,
                                  symtab->get_sized_symbol<size>(sym),
                                  object, shndx, output_section,
-                                 reloc, this->rela_dyn_section(layout));
+                                 r_type, reloc.get_r_offset(),
+                                 reloc.get_r_addend(),
+                                 this->rela_dyn_section(layout));
   }
 
   // Information about this specific target which we pass to the
@@ -433,6 +439,16 @@ class Target_sparc : public Sized_target<size, big_endian>
     GOT_TYPE_TLS_PAIR = 2,      // GOT entry for TLS module/offset pair
   };
 
+  struct Register_symbol
+  {
+    Register_symbol()
+      : name(NULL), shndx(0), obj(NULL)
+    { }
+    const char* name;
+    unsigned int shndx;
+    Object* obj;
+  };
+
   // The GOT section.
   Output_data_got<size, big_endian>* got_;
   // The PLT section.
@@ -443,8 +459,6 @@ class Target_sparc : public Sized_target<size, big_endian>
   Reloc_section* rela_ifunc_;
   // Relocs saved to avoid a COPY reloc.
   Copy_relocs<elfcpp::SHT_RELA, size, big_endian> copy_relocs_;
-  // Space for variables copied with a COPY reloc.
-  Output_data_space* dynbss_;
   // Offset of the GOT entry for the TLS module index;
   unsigned int got_mod_index_offset_;
   // Cached pointer to __tls_get_addr symbol
@@ -455,6 +469,8 @@ class Target_sparc : public Sized_target<size, big_endian>
   elfcpp::Elf_Word elf_flags_;
   // Whether elf_flags_ has been set for the first time yet
   bool elf_flags_set_;
+  // STT_SPARC_REGISTER symbols (%g2, %g3, %g6, %g7).
+  Register_symbol register_syms_[4];
 };
 
 template<>
@@ -473,12 +489,17 @@ Target::Target_info Target_sparc<32, true>::sparc_info =
   0x00010000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
   8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
   0,                   // large_common_section_flags
   NULL,                        // attributes_section
-  NULL                 // attributes_vendor
+  NULL,                        // attributes_vendor
+  "_start",            // entry_symbol_name
+  32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -487,7 +508,7 @@ Target::Target_info Target_sparc<64, true>::sparc_info =
   64,                  // size
   true,                        // is_big_endian
   elfcpp::EM_SPARCV9,  // machine_code
-  false,               // has_make_symbol
+  true,                        // has_make_symbol
   false,               // has_resolve
   false,               // has_code_fill
   true,                        // is_default_stack_executable
@@ -497,12 +518,17 @@ Target::Target_info Target_sparc<64, true>::sparc_info =
   0x100000,            // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
   8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
   0,                   // large_common_section_flags
   NULL,                        // attributes_section
-  NULL                 // attributes_vendor
+  NULL,                        // attributes_vendor
+  "_start",            // entry_symbol_name
+  32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 // We have to take care here, even when operating in little-endian
@@ -1100,13 +1126,12 @@ public:
   // R_SPARC_GOTDATA_OP_HIX22: @gdopoff(Symbol + Addend) >> 10
   static inline void
   gdop_hix22(unsigned char* view,
-            typename elfcpp::Elf_types<size>::Elf_Addr value,
-            typename elfcpp::Elf_types<size>::Elf_Addr addend)
+            typename elfcpp::Elf_types<size>::Elf_Addr value)
   {
     typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
     Valtype* wv = reinterpret_cast<Valtype*>(view);
     Valtype val = elfcpp::Swap<32, true>::readval(wv);
-    int32_t reloc = static_cast<int32_t>(value + addend);
+    int32_t reloc = static_cast<int32_t>(value);
 
     val &= ~0x3fffff;
 
@@ -1163,13 +1188,12 @@ public:
   // R_SPARC_GOTDATA_OP_LOX10: (@gdopoff(Symbol + Addend) & 0x3ff) | 0x1c00
   static inline void
   gdop_lox10(unsigned char* view,
-            typename elfcpp::Elf_types<size>::Elf_Addr value,
-            typename elfcpp::Elf_types<size>::Elf_Addr addend)
+            typename elfcpp::Elf_types<size>::Elf_Addr value)
   {
     typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
     Valtype* wv = reinterpret_cast<Valtype*>(view);
     Valtype val = elfcpp::Swap<32, true>::readval(wv);
-    int32_t reloc = static_cast<int32_t>(value + addend);
+    int32_t reloc = static_cast<int32_t>(value);
 
     if (reloc < 0)
       reloc = (reloc & 0x3ff) | 0x1c00;
@@ -1613,7 +1637,7 @@ Output_data_plt_sparc<size, big_endian>::address_for_global(const Symbol* gsym)
   if (gsym->type() == elfcpp::STT_GNU_IFUNC
       && gsym->can_use_relative_reloc(false))
     offset = plt_index_to_offset(this->count_ + 4);
-  return this->address() + offset;
+  return this->address() + offset + gsym->plt_offset();
 }
 
 // Return the PLT address to use for a local symbol.  These are always
@@ -1622,10 +1646,12 @@ Output_data_plt_sparc<size, big_endian>::address_for_global(const Symbol* gsym)
 template<int size, bool big_endian>
 uint64_t
 Output_data_plt_sparc<size, big_endian>::address_for_local(
-       const Relobj*,
-       unsigned int)
+       const Relobj* object,
+       unsigned int r_sym)
 {
-  return this->address() + plt_index_to_offset(this->count_ + 4);
+  return (this->address()
+         + plt_index_to_offset(this->count_ + 4)
+         + object->local_plt_offset(r_sym));
 }
 
 static const unsigned int sparc_nop = 0x01000000;
@@ -2126,6 +2152,7 @@ Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int
        case elfcpp::R_SPARC_RELATIVE:
        case elfcpp::R_SPARC_IRELATIVE:
        case elfcpp::R_SPARC_COPY:
+       case elfcpp::R_SPARC_32:
        case elfcpp::R_SPARC_64:
        case elfcpp::R_SPARC_GLOB_DAT:
        case elfcpp::R_SPARC_JMP_SLOT:
@@ -2218,7 +2245,7 @@ Target_sparc<size, big_endian>::Scan::reloc_needs_plt_for_ifunc(
   int flags = Scan::get_reference_flags(r_type);
   if (flags & Symbol::TLS_REF)
     gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
-               object->name().c_str(), r_type);
+              object->name().c_str(), r_type);
   return flags != 0;
 }
 
@@ -2235,8 +2262,12 @@ Target_sparc<size, big_endian>::Scan::local(
                        Output_section* output_section,
                        const elfcpp::Rela<size, big_endian>& reloc,
                        unsigned int r_type,
-                       const elfcpp::Sym<size, big_endian>& lsym)
+                       const elfcpp::Sym<size, big_endian>& lsym,
+                       bool is_discarded)
 {
+  if (is_discarded)
+    return;
+
   bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
   unsigned int orig_r_type = r_type;
   r_type &= 0xff;
@@ -2264,16 +2295,19 @@ Target_sparc<size, big_endian>::Scan::local(
       // apply the link-time value, so we flag the location with
       // an R_SPARC_RELATIVE relocation so the dynamic loader can
       // relocate it easily.
-      if (parameters->options().output_is_position_independent())
-        {
-          Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-          rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE,
+      if (parameters->options().output_is_position_independent()
+         && ((size == 64 && r_type == elfcpp::R_SPARC_64)
+             || (size == 32 && r_type == elfcpp::R_SPARC_32)))
+       {
+         Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+         rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE,
                                       output_section, data_shndx,
                                       reloc.get_r_offset(),
                                       reloc.get_r_addend(), is_ifunc);
-        }
-      break;
+         break;
+       }
+      // Fall through.
 
     case elfcpp::R_SPARC_HIX22:
     case elfcpp::R_SPARC_LOX10:
@@ -2301,26 +2335,26 @@ Target_sparc<size, big_endian>::Scan::local(
       // executable), we need to create a dynamic relocation for
       // this location.
       if (parameters->options().output_is_position_independent())
-        {
-          Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+       {
+         Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
 
          check_non_pic(object, r_type);
-          if (lsym.get_st_type() != elfcpp::STT_SECTION)
-            {
-              rela_dyn->add_local(object, r_sym, orig_r_type, output_section,
+         if (lsym.get_st_type() != elfcpp::STT_SECTION)
+           {
+             rela_dyn->add_local(object, r_sym, orig_r_type, output_section,
                                  data_shndx, reloc.get_r_offset(),
                                  reloc.get_r_addend());
-            }
-          else
-            {
-              gold_assert(lsym.get_st_value() == 0);
+           }
+         else
+           {
+             gold_assert(lsym.get_st_value() == 0);
              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:
@@ -2348,9 +2382,9 @@ Target_sparc<size, big_endian>::Scan::local(
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<size, big_endian>* got;
-        unsigned int r_sym;
+       // The symbol requires a GOT entry.
+       Output_data_got<size, big_endian>* got;
+       unsigned int r_sym;
 
        got = target->got_section(symtab, layout);
        r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
@@ -2397,7 +2431,7 @@ Target_sparc<size, big_endian>::Scan::local(
       {
        bool output_is_shared = parameters->options().shared();
        const tls::Tls_optimization optimized_type
-            = optimize_tls_reloc(!output_is_shared, r_type);
+           = optimize_tls_reloc(!output_is_shared, r_type);
        switch (r_type)
          {
          case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic
@@ -2406,11 +2440,11 @@ Target_sparc<size, big_endian>::Scan::local(
          case elfcpp::R_SPARC_TLS_GD_CALL:
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a pair of GOT entries for the module index and
-               // dtv-relative offset.
-                Output_data_got<size, big_endian>* got
-                    = target->got_section(symtab, layout);
-                unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Output_data_got<size, big_endian>* got
+                   = target->got_section(symtab, layout);
+               unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
                unsigned int shndx = lsym.get_st_shndx();
                bool is_ordinary;
                shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
@@ -2418,14 +2452,13 @@ 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_rel(object, r_sym, 
+                 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);
+                                               : elfcpp::R_SPARC_TLS_DTPMOD32));
                if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
                  generate_tls_call(symtab, layout, target);
              }
@@ -2490,11 +2523,11 @@ Target_sparc<size, big_endian>::Scan::local(
            layout->set_has_static_tls();
            if (output_is_shared)
              {
-               // We need to create a dynamic relocation.
-                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_symbolless_local_addend(object, r_sym, r_type,
+               // We need to create a dynamic relocation.
+               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_symbolless_local_addend(object, r_sym, r_type,
                                                      output_section, data_shndx,
                                                      reloc.get_r_offset(), 0);
              }
@@ -2596,8 +2629,8 @@ Target_sparc<size, big_endian>::Scan::global(
       // if the symbol is defined in the output file and is protected
       // or hidden.
       if (gsym->is_defined()
-          && !gsym->is_from_dynobj()
-          && !gsym->is_preemptible())
+         && !gsym->is_from_dynobj()
+         && !gsym->is_preemptible())
        break;
       target->make_plt_entry(symtab, layout, gsym);
       break;
@@ -2622,7 +2655,8 @@ Target_sparc<size, big_endian>::Scan::global(
        // Make a dynamic relocation if necessary.
        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
          {
-           if (gsym->may_need_copy_reloc())
+           if (parameters->options().output_is_executable()
+               && gsym->may_need_copy_reloc())
              {
                target->copy_reloc(symtab, layout, object,
                                   data_shndx, output_section, gsym,
@@ -2665,24 +2699,24 @@ Target_sparc<size, big_endian>::Scan::global(
     case elfcpp::R_SPARC_6:
     case elfcpp::R_SPARC_5:
       {
-        // Make a PLT entry if necessary.
-        if (gsym->needs_plt_entry())
-          {
-            target->make_plt_entry(symtab, layout, gsym);
-            // Since this is not a PC-relative relocation, we may be
-            // taking the address of a function. In that case we need to
-            // set the entry in the dynamic symbol table to the address of
-            // the PLT entry.
-            if (gsym->is_from_dynobj() && !parameters->options().shared())
-              gsym->set_needs_dynsym_value();
-          }
-        // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
-          {
+       // Make a PLT entry if necessary.
+       if (gsym->needs_plt_entry())
+         {
+           target->make_plt_entry(symtab, layout, gsym);
+           // Since this is not a PC-relative relocation, we may be
+           // taking the address of a function. In that case we need to
+           // set the entry in the dynamic symbol table to the address of
+           // the PLT entry.
+           if (gsym->is_from_dynobj() && !parameters->options().shared())
+             gsym->set_needs_dynsym_value();
+         }
+       // Make a dynamic relocation if necessary.
+       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. 
+           // for dwarf2 cfi directives.
            switch (r_type)
              {
              case elfcpp::R_SPARC_16:
@@ -2711,11 +2745,12 @@ Target_sparc<size, big_endian>::Scan::global(
                break;
              }
 
-            if (gsym->may_need_copy_reloc())
-              {
-               target->copy_reloc(symtab, layout, object,
-                                  data_shndx, output_section, gsym, reloc);
-              }
+           if (!parameters->options().output_is_position_independent()
+               && gsym->may_need_copy_reloc())
+             {
+               target->copy_reloc(symtab, layout, object,
+                                  data_shndx, output_section, gsym, reloc);
+             }
            else if (((size == 64 && r_type == elfcpp::R_SPARC_64)
                      || (size == 32 && r_type == elfcpp::R_SPARC_32))
                     && gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -2737,19 +2772,19 @@ Target_sparc<size, big_endian>::Scan::global(
                                                       reloc.get_r_offset(),
                                                       reloc.get_r_addend());
              }
-            else if ((r_type == elfcpp::R_SPARC_32
-                     || r_type == elfcpp::R_SPARC_64)
-                     && gsym->can_use_relative_reloc(false))
-              {
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-                rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
+           else if (((size == 64 && r_type == elfcpp::R_SPARC_64)
+                     || (size == 32 && r_type == elfcpp::R_SPARC_32))
+                    && gsym->can_use_relative_reloc(false))
+             {
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+               rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
                                              output_section, object,
                                              data_shndx, reloc.get_r_offset(),
                                              reloc.get_r_addend(), is_ifunc);
-              }
-            else
-              {
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+             }
+           else
+             {
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 
                check_non_pic(object, r_type);
                if (gsym->is_from_dynobj()
@@ -2765,8 +2800,8 @@ Target_sparc<size, big_endian>::Scan::global(
                                                         object, data_shndx,
                                                         reloc.get_r_offset(),
                                                         reloc.get_r_addend());
-              }
-          }
+             }
+         }
       }
       break;
 
@@ -2774,23 +2809,24 @@ Target_sparc<size, big_endian>::Scan::global(
     case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
     case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
       if (gsym->is_defined()
-          && !gsym->is_from_dynobj()
-          && !gsym->is_preemptible()
+         && !gsym->is_from_dynobj()
+         && !gsym->is_preemptible()
          && !is_ifunc)
        {
          // We will optimize this into a GOT relative relocation
          // and code transform the GOT load into an addition.
          break;
        }
+      // Fall through.
     case elfcpp::R_SPARC_GOT10:
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<size, big_endian>* got;
+       // The symbol requires a GOT entry.
+       Output_data_got<size, big_endian>* got;
 
        got = target->got_section(symtab, layout);
-        if (gsym->final_value_is_known())
+       if (gsym->final_value_is_known())
          {
            // For a STT_GNU_IFUNC symbol we want the PLT address.
            if (gsym->type() == elfcpp::STT_GNU_IFUNC)
@@ -2798,10 +2834,10 @@ Target_sparc<size, big_endian>::Scan::global(
            else
              got->add_global(gsym, GOT_TYPE_STANDARD);
          }
-        else
-          {
-            // If this symbol is not fully resolved, we need to add a
-            // GOT entry with a dynamic relocation.
+       else
+         {
+           // If this symbol is not fully resolved, we need to add a
+           // GOT entry with a dynamic relocation.
            bool is_ifunc = gsym->type() == elfcpp::STT_GNU_IFUNC;
 
            // Use a GLOB_DAT rather than a RELATIVE reloc if:
@@ -2816,10 +2852,10 @@ Target_sparc<size, big_endian>::Scan::global(
            //
            // 3) This is a STT_GNU_IFUNC symbol in position dependent
            // code, again so that function address comparisons work.
-            Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-            if (gsym->is_from_dynobj()
-                || gsym->is_undefined()
-                || gsym->is_preemptible()
+           Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+           if (gsym->is_from_dynobj()
+               || gsym->is_undefined()
+               || gsym->is_preemptible()
                || (gsym->visibility() == elfcpp::STV_PROTECTED
                    && parameters->options().shared())
                || (gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -2838,8 +2874,8 @@ Target_sparc<size, big_endian>::Scan::global(
                got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
                                         r_type);
              }
-            else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
-              {
+           else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
+             {
                unsigned int off = got->add_constant(0);
 
                gsym->set_got_offset(GOT_TYPE_STANDARD, off);
@@ -2854,7 +2890,7 @@ Target_sparc<size, big_endian>::Scan::global(
                rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
                                              got, off, 0, is_ifunc);
              }
-          }
+         }
       }
       break;
 
@@ -2881,7 +2917,7 @@ Target_sparc<size, big_endian>::Scan::global(
       {
        const bool is_final = gsym->final_value_is_known();
        const tls::Tls_optimization optimized_type
-            = optimize_tls_reloc(is_final, r_type);
+           = optimize_tls_reloc(is_final, r_type);
        switch (r_type)
          {
          case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic
@@ -2890,11 +2926,11 @@ Target_sparc<size, big_endian>::Scan::global(
          case elfcpp::R_SPARC_TLS_GD_CALL:
            if (optimized_type == tls::TLSOPT_NONE)
              {
-                // Create a pair of GOT entries for the module index and
-                // dtv-relative offset.
-                Output_data_got<size, big_endian>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Output_data_got<size, big_endian>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
                                              target->rela_dyn_section(layout),
                                              (size == 64
                                               ? elfcpp::R_SPARC_TLS_DTPMOD64
@@ -2909,10 +2945,10 @@ Target_sparc<size, big_endian>::Scan::global(
              }
            else if (optimized_type == tls::TLSOPT_TO_IE)
              {
-                // 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_rel(gsym, GOT_TYPE_TLS_OFFSET,
+               // 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_rel(gsym, GOT_TYPE_TLS_OFFSET,
                                         target->rela_dyn_section(layout),
                                         (size == 64 ?
                                          elfcpp::R_SPARC_TLS_TPOFF64 :
@@ -3004,6 +3040,68 @@ Target_sparc<size, big_endian>::Scan::global(
     }
 }
 
+// Make a new symbol table entry.
+// STT_SPARC_REGISTER symbols require special handling,
+// so we intercept these symbols and keep track of them separately.
+// We will resolve register symbols here and output them at symbol
+// finalization time.
+
+template<int size, bool big_endian>
+Sized_symbol<size>*
+Target_sparc<size, big_endian>::make_symbol(const char* name,
+                                           elfcpp::STT type,
+                                           Object* object,
+                                           unsigned int shndx,
+                                           uint64_t value)
+{
+  // REGISTER symbols are used only on SPARC-64.
+  if (size == 64 && type == elfcpp::STT_SPARC_REGISTER)
+    {
+      // Ignore REGISTER symbols in dynamic objects.
+      if (object->is_dynamic())
+       return NULL;
+      // Only registers 2, 3, 6, and 7 can be declared global.
+      int reg = value;
+      switch (reg)
+       {
+       case 2: case 3:
+         reg -= 2;
+         break;
+       case 6: case 7:
+         reg -= 4;
+         break;
+       default:
+         gold_error(_("%s: only registers %%g[2367] can be declared "
+                      "using STT_REGISTER"),
+                    object->name().c_str());
+         return NULL;
+       }
+      Register_symbol& rsym = this->register_syms_[reg];
+      if (rsym.name == NULL)
+       {
+         rsym.name = name;
+         rsym.shndx = shndx;
+         rsym.obj = object;
+       }
+      else
+       {
+         if (strcmp(rsym.name, name) != 0)
+           {
+             gold_error(_("%s: register %%g%d declared as '%s'; "
+                          "previously declared as '%s' in %s"),
+                        object->name().c_str(),
+                        static_cast<int>(value),
+                        *name ? name : "#scratch",
+                        *rsym.name ? rsym.name : "#scratch",
+                        rsym.obj->name().c_str());
+             return NULL;
+           }
+       }
+      return NULL;
+    }
+  return new Sized_symbol<size>();
+}
+
 // Process relocations for gc.
 
 template<int size, bool big_endian>
@@ -3023,9 +3121,10 @@ Target_sparc<size, big_endian>::gc_process_relocs(
 {
   typedef Target_sparc<size, big_endian> Sparc;
   typedef typename Target_sparc<size, big_endian>::Scan Scan;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
-  gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan,
-                         typename Target_sparc::Relocatable_size_for_reloc>(
+  gold::gc_process_relocs<size, big_endian, Sparc, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -3057,7 +3156,8 @@ Target_sparc<size, big_endian>::scan_relocs(
                        const unsigned char* plocal_symbols)
 {
   typedef Target_sparc<size, big_endian> Sparc;
-  typedef typename Target_sparc<size, big_endian>::Scan Scan;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   if (sh_type == elfcpp::SHT_REL)
     {
@@ -3066,7 +3166,7 @@ Target_sparc<size, big_endian>::scan_relocs(
       return;
     }
 
-  gold::scan_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>(
+  gold::scan_relocs<size, big_endian, Sparc, Scan, Classify_reloc>(
     symtab,
     layout,
     this,
@@ -3144,6 +3244,27 @@ Target_sparc<size, big_endian>::do_finalize_sections(
       symtab->define_symbols(layout, 2, syms,
                             layout->script_options()->saw_sections_clause());
     }
+
+  for (int reg = 0; reg < 4; ++reg)
+    {
+      Register_symbol& rsym = this->register_syms_[reg];
+      if (rsym.name != NULL)
+       {
+         int value = reg < 3 ? reg + 2 : reg + 4;
+         Sized_symbol<size>* sym = new Sized_symbol<size>();
+         if (rsym.shndx == elfcpp::SHN_UNDEF)
+           sym->init_undefined(rsym.name, NULL, value,
+                               elfcpp::STT_SPARC_REGISTER, elfcpp::STB_GLOBAL,
+                               elfcpp::STV_DEFAULT, 0);
+         else
+           sym->init_constant(rsym.name, NULL, value, 0,
+                              elfcpp::STT_SPARC_REGISTER, elfcpp::STB_GLOBAL,
+                              elfcpp::STV_DEFAULT, 0, false);
+         symtab->add_target_global_symbol(sym);
+         layout->add_target_specific_dynamic_tag(elfcpp::DT_SPARC_REGISTER,
+                                                 value);
+       }
+    }
 }
 
 // Perform a relocation.
@@ -3152,17 +3273,19 @@ template<int size, bool big_endian>
 inline bool
 Target_sparc<size, big_endian>::Relocate::relocate(
                        const Relocate_info<size, big_endian>* relinfo,
+                       unsigned int,
                        Target_sparc* target,
                        Output_section*,
                        size_t relnum,
-                       const elfcpp::Rela<size, big_endian>& rela,
-                       unsigned int r_type,
+                       const unsigned char* preloc,
                        const Sized_symbol<size>* gsym,
                        const Symbol_value<size>* psymval,
                        unsigned char* view,
                        typename elfcpp::Elf_types<size>::Elf_Addr address,
                        section_size_type view_size)
 {
+  const elfcpp::Rela<size, big_endian> rela(preloc);
+  unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
   bool orig_is_ifunc = psymval->is_ifunc_symbol();
   r_type &= 0xff;
 
@@ -3177,6 +3300,10 @@ Target_sparc<size, big_endian>::Relocate::relocate(
          return false;
        }
     }
+
+  if (view == NULL)
+    return true;
+
   if (this->reloc_adjust_addr_ == view)
     view -= 4;
 
@@ -3190,7 +3317,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
     {
       elfcpp::Elf_Xword value;
 
-      value = target->plt_address_for_global(gsym) + gsym->plt_offset();
+      value = target->plt_address_for_global(gsym);
 
       symval.set_output_value(value);
 
@@ -3201,8 +3328,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
       unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
       if (object->local_has_plt_offset(r_sym))
        {
-         symval.set_output_value(target->plt_address_for_local(object, r_sym)
-                                 + object->local_plt_offset(r_sym));
+         symval.set_output_value(target->plt_address_for_local(object, r_sym));
          psymval = &symval;
        }
     }
@@ -3227,24 +3353,25 @@ Target_sparc<size, big_endian>::Relocate::relocate(
              && !gsym->is_preemptible()
              && !orig_is_ifunc))
        {
-         got_offset = psymval->value(object, 0) - target->got_address();
+         got_offset = psymval->value(object, addend) - target->got_address();
          gdop_valid = true;
          break;
        }
+      // Fall through.
     case elfcpp::R_SPARC_GOT10:
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
       if (gsym != NULL)
-        {
-          gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
-          got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
-        }
+       {
+         gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+         got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
+       }
       else
-        {
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-          gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
-          got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
-        }
+       {
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+         gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+         got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
+       }
       break;
 
     default:
@@ -3268,7 +3395,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
       if (rela.get_r_offset() & 0x1)
        {
          // The assembler can sometimes emit unaligned relocations
-         // for dwarf2 cfi directives. 
+         // for dwarf2 cfi directives.
          Reloc::ua16(view, object, psymval, addend);
        }
       else
@@ -3282,7 +3409,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
          if (rela.get_r_offset() & 0x3)
            {
              // The assembler can sometimes emit unaligned relocations
-             // for dwarf2 cfi directives. 
+             // for dwarf2 cfi directives.
              Reloc::ua32(view, object, psymval, addend);
            }
          else
@@ -3346,6 +3473,13 @@ Target_sparc<size, big_endian>::Relocate::relocate(
       Reloc::lo10(view, object, psymval, addend);
       break;
 
+    case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+      if (gdop_valid)
+       {
+         Reloc::gdop_lox10(view, got_offset);
+         break;
+       }
+      // Fall through.
     case elfcpp::R_SPARC_GOT10:
       Reloc::lo10(view, got_offset, addend);
       break;
@@ -3364,13 +3498,6 @@ Target_sparc<size, big_endian>::Relocate::relocate(
        }
       break;
 
-    case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
-      if (gdop_valid)
-       {
-         Reloc::gdop_lox10(view, got_offset, addend);
-         break;
-       }
-      /* Fall through.  */
     case elfcpp::R_SPARC_GOT13:
       Reloc::rela32_13(view, got_offset, addend);
       break;
@@ -3378,10 +3505,10 @@ Target_sparc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
       if (gdop_valid)
        {
-         Reloc::gdop_hix22(view, got_offset, addend);
+         Reloc::gdop_hix22(view, got_offset);
          break;
        }
-      /* Fall through.  */
+      // Fall through.
     case elfcpp::R_SPARC_GOT22:
       Reloc::hi22(view, got_offset, addend);
       break;
@@ -3435,7 +3562,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
          if (rela.get_r_offset() & 0x7)
            {
              // The assembler can sometimes emit unaligned relocations
-             // for dwarf2 cfi directives. 
+             // for dwarf2 cfi directives.
              Reloc::ua64(view, object, psymval, addend);
            }
          else
@@ -3605,7 +3732,7 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
 
   const bool is_final =
     (gsym == NULL
-     ? !parameters->options().output_is_position_independent()
+     ? !parameters->options().shared()
      : gsym->final_value_is_known());
   const tls::Tls_optimization optimized_type
       = optimize_tls_reloc(is_final, r_type);
@@ -3649,22 +3776,22 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
          break;
        }
       else
-        {
-          unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
-                                   ? GOT_TYPE_TLS_OFFSET
-                                   : GOT_TYPE_TLS_PAIR);
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              value = gsym->got_offset(got_type);
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              value = object->local_got_offset(r_sym, got_type);
-            }
-          if (optimized_type == tls::TLSOPT_TO_IE)
+       {
+         unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+                                  ? GOT_TYPE_TLS_OFFSET
+                                  : GOT_TYPE_TLS_PAIR);
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             value = gsym->got_offset(got_type);
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             value = object->local_got_offset(r_sym, got_type);
+           }
+         if (optimized_type == tls::TLSOPT_TO_IE)
            {
              Insntype* wv = reinterpret_cast<Insntype*>(view);
              Insntype val;
@@ -3729,10 +3856,10 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
                  elfcpp::Swap<32, true>::writeval(wv, 0x9001c008);
                  break;
                }
-              break;
+             break;
            }
-          else if (optimized_type == tls::TLSOPT_NONE)
-            {
+         else if (optimized_type == tls::TLSOPT_NONE)
+           {
              switch (r_type)
                {
                case elfcpp::R_SPARC_TLS_GD_HI22:
@@ -3759,8 +3886,8 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
                  break;
                }
              break;
-            }
-        }
+           }
+       }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
                             _("unsupported reloc %u"),
                             r_type);
@@ -3789,10 +3916,10 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
          break;
        }
       else if (optimized_type == tls::TLSOPT_NONE)
-        {
-          // Relocate the field with the offset of the GOT entry for
-          // the module index.
-          unsigned int got_offset;
+       {
+         // Relocate the field with the offset of the GOT entry for
+         // the module index.
+         unsigned int got_offset;
 
          got_offset = target->got_mod_index_entry(NULL, NULL, NULL);
          switch (r_type)
@@ -3820,8 +3947,8 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
              }
              break;
            }
-          break;
-        }
+         break;
+       }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
                             _("unsupported reloc %u"),
                             r_type);
@@ -4039,7 +4166,7 @@ Target_sparc<size, big_endian>::Relocate::relax_call(
   if (op3 != 0x3d)
     {
       // First check RS1
-      reg = (delay_insn >> 14) & 0x15;
+      reg = (delay_insn >> 14) & 0x1f;
       if (reg == 15)
        return;
 
@@ -4124,11 +4251,13 @@ Target_sparc<size, big_endian>::relocate_section(
 {
   typedef Target_sparc<size, big_endian> Sparc;
   typedef typename Target_sparc<size, big_endian>::Relocate Sparc_relocate;
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
 
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_section<size, big_endian, Sparc, elfcpp::SHT_RELA,
-    Sparc_relocate>(
+  gold::relocate_section<size, big_endian, Sparc, Sparc_relocate,
+                        gold::Default_comdat_behavior, Classify_reloc>(
     relinfo,
     this,
     prelocs,
@@ -4141,20 +4270,6 @@ Target_sparc<size, big_endian>::relocate_section(
     reloc_symbol_changes);
 }
 
-// Return the size of a relocation while scanning during a relocatable
-// link.
-
-template<int size, bool big_endian>
-unsigned int
-Target_sparc<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
-    unsigned int,
-    Relobj*)
-{
-  // We are always SHT_RELA, so we should never get here.
-  gold_unreachable();
-  return 0;
-}
-
 // Scan the relocs during a relocatable link.
 
 template<int size, bool big_endian>
@@ -4173,13 +4288,14 @@ Target_sparc<size, big_endian>::scan_relocatable_relocs(
                        const unsigned char* plocal_symbols,
                        Relocatable_relocs* rr)
 {
-  gold_assert(sh_type == elfcpp::SHT_RELA);
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
+      Scan_relocatable_relocs;
 
-  typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
-    Relocatable_size_for_reloc> Scan_relocatable_relocs;
+  gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA,
-      Scan_relocatable_relocs>(
+  gold::scan_relocatable_relocs<size, big_endian, Scan_relocatable_relocs>(
     symtab,
     layout,
     object,
@@ -4193,33 +4309,73 @@ Target_sparc<size, big_endian>::scan_relocatable_relocs(
     rr);
 }
 
-// Relocate a section during a relocatable link.
+// Scan the relocs for --emit-relocs.
 
 template<int size, bool big_endian>
 void
-Target_sparc<size, big_endian>::relocate_for_relocatable(
+Target_sparc<size, big_endian>::emit_relocs_scan(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_syms,
+    Relocatable_relocs* rr)
+{
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+  typedef gold::Default_emit_relocs_strategy<Classify_reloc>
+      Emit_relocs_strategy;
+
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+
+  gold::scan_relocatable_relocs<size, big_endian, Emit_relocs_strategy>(
+    symtab,
+    layout,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_syms,
+    rr);
+}
+
+// Emit relocations for a section.
+
+template<int size, bool big_endian>
+void
+Target_sparc<size, big_endian>::relocate_relocs(
     const Relocate_info<size, big_endian>* relinfo,
     unsigned int sh_type,
     const unsigned char* prelocs,
     size_t reloc_count,
     Output_section* output_section,
-    off_t offset_in_output_section,
-    const Relocatable_relocs* rr,
+    typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
     unsigned char* view,
     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
     section_size_type view_size,
     unsigned char* reloc_view,
     section_size_type reloc_view_size)
 {
+  typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
+      Classify_reloc;
+
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_for_relocatable<size, big_endian, elfcpp::SHT_RELA>(
+  gold::relocate_relocs<size, big_endian, Classify_reloc>(
     relinfo,
     prelocs,
     reloc_count,
     output_section,
     offset_in_output_section,
-    rr,
     view,
     view_address,
     view_size,
@@ -4255,7 +4411,7 @@ Target_sparc<size, big_endian>::do_make_elf_object(
   elfcpp::Elf_Half machine = ehdr.get_e_machine();
   elfcpp::Elf_Word flags = ehdr.get_e_flags();
   elfcpp::Elf_Word omm, mm;
-  
+
   switch (machine)
     {
     case elfcpp::EM_SPARC32PLUS:
@@ -4324,7 +4480,7 @@ template<int size, bool big_endian>
 void
 Target_sparc<size, big_endian>::do_adjust_elf_header(
     unsigned char* view,
-    int len) const
+    int len)
 {
   elfcpp::Ehdr_write<size, big_endian> oehdr(view);
 
@@ -4346,7 +4502,8 @@ public:
                      (size == 64 ? "elf64_sparc" : "elf32_sparc"))
   { }
 
-  Target* do_recognize(int machine, int, int)
+  virtual Target*
+  do_recognize(Input_file*, off_t, int machine, int, int)
   {
     switch (size)
       {
@@ -4368,7 +4525,8 @@ public:
     return this->instantiate_target();
   }
 
-  Target* do_instantiate_target()
+  virtual Target*
+  do_instantiate_target()
   { return new Target_sparc<size, big_endian>(); }
 };
 
This page took 0.042515 seconds and 4 git commands to generate.