PR 9812
[binutils-gdb.git] / gold / sparc.cc
index ded63daf30d1d5ddc171b7678e25673ecc983bc2..476aa3286d673a6803f19bf0f9ec8791a2e0d764 100644 (file)
@@ -1,6 +1,6 @@
 // sparc.cc -- sparc target support for gold.
 
-// Copyright 2008 Free Software Foundation, Inc.
+// Copyright 2008, 2009 Free Software Foundation, Inc.
 // Written by David S. Miller <davem@davemloft.net>.
 
 // This file is part of gold.
@@ -63,6 +63,22 @@ class Target_sparc : public Sized_target<size, big_endian>
   {
   }
 
+  // Process the relocations to determine unreferenced sections for 
+  // garbage collection.
+  void
+  gc_process_relocs(const General_options& options,
+                   Symbol_table* symtab,
+                   Layout* layout,
+                   Sized_relobj<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
   scan_relocs(const General_options& options,
@@ -130,7 +146,7 @@ class Target_sparc : public Sized_target<size, big_endian>
                           section_size_type reloc_view_size);
   // Return whether SYM is defined by the ABI.
   bool
-  do_is_defined_by_abi(Symbol* sym) const
+  do_is_defined_by_abi(const Symbol* sym) const
   {
     // XXX Really need to support this better...
     if (sym->type() == elfcpp::STT_SPARC_REGISTER)
@@ -2211,6 +2227,42 @@ Target_sparc<size, big_endian>::Scan::global(
     }
 }
 
+// Process relocations for gc.
+
+template<int size, bool big_endian>
+void
+Target_sparc<size, big_endian>::gc_process_relocs(
+                       const General_options& options,
+                       Symbol_table* symtab,
+                       Layout* layout,
+                       Sized_relobj<size, big_endian>* object,
+                       unsigned int data_shndx,
+                       unsigned int,
+                       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)
+{
+  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>(
+    options,
+    symtab,
+    layout,
+    this,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols);
+}
+
 // Scan relocations for a section.
 
 template<int size, bool big_endian>
@@ -2332,10 +2384,19 @@ Target_sparc<size, big_endian>::Relocate::relocate(
   // Pick the value to use for symbols defined in shared objects.
   Symbol_value<size> symval;
   if (gsym != NULL
-      && (gsym->is_from_dynobj()
-          || (parameters->options().shared()
-              && (gsym->is_undefined() || gsym->is_preemptible())))
-      && gsym->has_plt_offset())
+      && 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))
     {
       elfcpp::Elf_Xword value;