This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: bug: GOLD handling of Sparc PLTREL


From: Ian Lance Taylor <iant@google.com>
Date: Tue, 09 Feb 2010 07:04:13 -0800

> David Miller <davem@davemloft.net> writes:
> 
>>> I see a few calls to add_local_relative and add_global_relative that
>>> are not passing down elfcpp::R_SPARC_RELATIVE as the reloc type.  That
>>> is rather suspicious and seems like it could cause this sort of
>>> problem.
>>
>> It has nothing to do with these crashes.
> 
> It is a problem, though, because it will cause DT_RELACOUNT to be
> incorrect.

How does this look?

gold/

2010-02-09  David S. Miller  <davem@davemloft.net>

	* sparc.cc (Target_sparc::Scan::local): Do not emit relocs other than
	R_SPARC_RELATIVE using ->add_local_relative().
	(Target_sparc::Scan::global): Likewise for ->add_global_relative().

diff --git a/gold/sparc.cc b/gold/sparc.cc
index d3c9435..234c5f5 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -1675,23 +1675,31 @@ Target_sparc<size, big_endian>::Scan::local(
       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());
 
 	  check_non_pic(object, r_type);
           if (lsym.get_st_type() != elfcpp::STT_SECTION)
             {
-              unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
               rela_dyn->add_local(object, r_sym, orig_r_type, output_section,
 				  data_shndx, reloc.get_r_offset(),
 				  reloc.get_r_addend());
             }
           else
             {
-	      unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+	      unsigned int shndx = lsym.get_st_shndx();
+	      bool is_ordinary;
+
               gold_assert(lsym.get_st_value() == 0);
-              rela_dyn->add_local_relative(object, r_sym, orig_r_type,
-					   output_section, data_shndx,
-					   reloc.get_r_offset(),
-					   reloc.get_r_addend());
+	      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());
             }
         }
       break;
@@ -1839,15 +1847,13 @@ 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);
-		    rela_dyn->add_local_relative(object, r_sym,
-						 (size == 64 ?
-						  elfcpp::R_SPARC_TLS_TPOFF64 :
-						  elfcpp::R_SPARC_TLS_TPOFF32),
-						 got, off, 0);
+
+		    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));
 		  }
 	      }
 	    else if (optimized_type != tls::TLSOPT_TO_LE)
@@ -1863,9 +1869,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_relative(object, r_sym, r_type,
-					     output_section, data_shndx,
-					     reloc.get_r_offset(), 0);
+                rela_dyn->add_local(object, r_sym, r_type,
+				    output_section, data_shndx,
+				    reloc.get_r_offset(), 0);
 	      }
 	    break;
 	  }
@@ -2060,19 +2066,10 @@ Target_sparc<size, big_endian>::Scan::global(
                 Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 
 		check_non_pic(object, r_type);
-		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_global_relative(gsym, orig_r_type,
-						output_section, object,
-						data_shndx,
-						reloc.get_r_offset(),
-						reloc.get_r_addend());
+		rela_dyn->add_global(gsym, orig_r_type, output_section,
+				     object, data_shndx,
+				     reloc.get_r_offset(),
+				     reloc.get_r_addend());
               }
           }
       }
@@ -2204,10 +2201,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_relative(gsym, orig_r_type,
-					      output_section, object,
-					      data_shndx, reloc.get_r_offset(),
-					      0);
+		rela_dyn->add_global(gsym, orig_r_type,
+				     output_section, object,
+				     data_shndx, reloc.get_r_offset(),
+				     0);
 	      }
 	    break;
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]