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]

[GOLD] Adjusting --emit-relocs output


This patch arranges to call the target relocate_for_relocatable (which
I rename to relocate_relocs) for --emit-relocs.  The idea being to
adjust relocs for edited code so that -emit-relocs gives you
relocations that make sense.  Unless I'm missing something, the current
Sized_relobj_file::emit_relocs does exactly the same thing as
gold::relocate_for_relocatable with only a minor difference in where
Relocatable_relocs info is found, and all target
relocate_for_relocatable functions except powerpc currently just call 
gold::relocate_for_relocatable.  OK to apply?

gold/
	* object.h (Sized_relobj_file::emit_relocs): Delete.
	(Sized_relobj_file::emit_relocs_reltype): Delete.
	* reloc.cc (Sized_relobj_file::do_relocate_sections): Call target
	relocate_relocs for --emit-relocs.
	(Sized_relobj_file::emit_relocs, emit_relocs_reltype): Delete.
	* output.h: Update comment.
	(Output_segment::first_section): New function.
	(Output_segment::first_section_load_address): Use first_section.
	* output.cc (Output_segment::first_section): New function extracted..
	(Output_segment::first_section_load_address): ..from here.  Delete.
	* target-reloc.h (relocate_for_relocatable): Rename to relocate_relocs.
	* target.h (Sized_target::relocate_for_relocatable): Likewise.
	* arm.cc (Target_arm::relocate_for_relocatable): Likewise, and
	adjust call to target.h function.
	* i386.cc (Target_i386): Likewise.
	* sparc.cc (Target_sparc): Likewise.
	* x86_64.cc (Target_x86_64): Likewise.
	* powerpc.cc (Target_powerpc): Likewise.
	(Target_powerpc::Scan::local, global): Handle R_POWERPC_TLS.  Ensure
	first tls section has section symbol for optimised local dynamic
	output relocs.
	(Target_powerpc::Relocate::relocate): Correct local dynamic value.
	(Target_powerpc::relocate_relocs): Adjust relocs emitted for
	optimised tls code.
gold/testsuite/
	* testfile.cc (Target_test::relocate_for_relocatable): Rename
	to relocate_relocs.  Update error message.

Index: gold/object.h
===================================================================
RCS file: /cvs/src/src/gold/object.h,v
retrieving revision 1.118
diff -u -p -r1.118 object.h
--- gold/object.h	11 Aug 2012 04:41:27 -0000	1.118
+++ gold/object.h	1 Sep 2012 03:19:35 -0000
@@ -2499,27 +2499,6 @@ class Sized_relobj_file : public Sized_r
 			   const Read_relocs_data::Relocs_list::iterator&,
 			   Relocatable_relocs*);
 
-  // Emit the relocs for --emit-relocs.
-  void
-  emit_relocs(const Relocate_info<size, big_endian>*, unsigned int,
-	      unsigned int sh_type, const unsigned char* prelocs,
-	      size_t reloc_count, Output_section*, Address output_offset,
-	      unsigned char* view, Address address,
-	      section_size_type view_size,
-	      unsigned char* reloc_view, section_size_type reloc_view_size);
-
-  // Emit the relocs for --emit-relocs, templatized on the type of the
-  // relocation section.
-  template<int sh_type>
-  void
-  emit_relocs_reltype(const Relocate_info<size, big_endian>*, unsigned int,
-		      const unsigned char* prelocs, size_t reloc_count,
-		      Output_section*, Address output_offset,
-		      unsigned char* view, Address address,
-		      section_size_type view_size,
-		      unsigned char* reloc_view,
-		      section_size_type reloc_view_size);
-
   // Scan the input relocations for --incremental.
   void
   incremental_relocs_scan(const Read_relocs_data::Relocs_list::iterator&);
Index: gold/reloc.cc
===================================================================
RCS file: /cvs/src/src/gold/reloc.cc,v
retrieving revision 1.68
diff -u -p -r1.68 reloc.cc
--- gold/reloc.cc	25 Jun 2011 00:40:56 -0000	1.68
+++ gold/reloc.cc	1 Sep 2012 03:19:36 -0000
@@ -1014,9 +1014,14 @@ Sized_relobj_file<size, big_endian>::do_
 				   output_offset == invalid_address,
 				   view, address, view_size, reloc_map);
 	  if (parameters->options().emit_relocs())
-	    this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count,
-			      os, output_offset, view, address, view_size,
-			      (*pviews)[i].view, (*pviews)[i].view_size);
+	    {
+	      Relocatable_relocs* rr = this->relocatable_relocs(i);
+	      target->relocate_relocs(&relinfo, sh_type, prelocs, reloc_count,
+				      os, output_offset, rr,
+				      view, address, view_size,
+				      (*pviews)[i].view,
+				      (*pviews)[i].view_size);
+	    }
 	  if (parameters->incremental())
 	    this->incremental_relocs_write(&relinfo, sh_type, prelocs,
 					   reloc_count, os, output_offset, of);
@@ -1024,84 +1029,15 @@ Sized_relobj_file<size, big_endian>::do_
       else
 	{
 	  Relocatable_relocs* rr = this->relocatable_relocs(i);
-	  target->relocate_for_relocatable(&relinfo, sh_type, prelocs,
-					   reloc_count, os, output_offset, rr,
-					   view, address, view_size,
-					   (*pviews)[i].view,
-					   (*pviews)[i].view_size);
+	  target->relocate_relocs(&relinfo, sh_type, prelocs, reloc_count,
+				  os, output_offset, rr,
+				  view, address, view_size,
+				  (*pviews)[i].view,
+				  (*pviews)[i].view_size);
 	}
     }
 }
 
-// Emit the relocs for --emit-relocs.
-
-template<int size, bool big_endian>
-void
-Sized_relobj_file<size, big_endian>::emit_relocs(
-    const Relocate_info<size, big_endian>* relinfo,
-    unsigned int i,
-    unsigned int sh_type,
-    const unsigned char* prelocs,
-    size_t reloc_count,
-    Output_section* output_section,
-    typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
-    unsigned char* view,
-    typename elfcpp::Elf_types<size>::Elf_Addr address,
-    section_size_type view_size,
-    unsigned char* reloc_view,
-    section_size_type reloc_view_size)
-{
-  if (sh_type == elfcpp::SHT_REL)
-    this->emit_relocs_reltype<elfcpp::SHT_REL>(relinfo, i, prelocs,
-					       reloc_count, output_section,
-					       offset_in_output_section,
-					       view, address, view_size,
-					       reloc_view, reloc_view_size);
-  else
-    {
-      gold_assert(sh_type == elfcpp::SHT_RELA);
-      this->emit_relocs_reltype<elfcpp::SHT_RELA>(relinfo, i, prelocs,
-						  reloc_count, output_section,
-						  offset_in_output_section,
-						  view, address, view_size,
-						  reloc_view, reloc_view_size);
-    }
-}
-
-// Emit the relocs for --emit-relocs, templatized on the type of the
-// relocation section.
-
-template<int size, bool big_endian>
-template<int sh_type>
-void
-Sized_relobj_file<size, big_endian>::emit_relocs_reltype(
-    const Relocate_info<size, big_endian>* relinfo,
-    unsigned int i,
-    const unsigned char* prelocs,
-    size_t reloc_count,
-    Output_section* output_section,
-    typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
-    unsigned char* view,
-    typename elfcpp::Elf_types<size>::Elf_Addr address,
-    section_size_type view_size,
-    unsigned char* reloc_view,
-    section_size_type reloc_view_size)
-{
-  const Relocatable_relocs* rr = this->relocatable_relocs(i);
-  relocate_for_relocatable<size, big_endian, sh_type>(
-    relinfo,
-    prelocs,
-    reloc_count,
-    output_section,
-    offset_in_output_section,
-    rr,
-    view,
-    address,
-    view_size,
-    reloc_view,
-    reloc_view_size);
-}
-
 // Write the incremental relocs.
 
 template<int size, bool big_endian>
Index: gold/output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.138
diff -u -p -r1.138 output.h
--- gold/output.h	30 Aug 2012 05:54:59 -0000	1.138
+++ gold/output.h	1 Sep 2012 03:19:36 -0000
@@ -2123,7 +2123,7 @@ class Output_data_reloc<elfcpp::SHT_RELA
 
 // Output_relocatable_relocs represents a relocation section in a
 // relocatable link.  The actual data is written out in the target
-// hook relocate_for_relocatable.  This just saves space for it.
+// hook relocate_relocs.  This just saves space for it.
 
 template<int sh_type, int size, bool big_endian>
 class Output_relocatable_relocs : public Output_section_data
@@ -4406,9 +4406,17 @@ class Output_segment
   bool
   has_dynamic_reloc() const;
 
+  // Return the first section.
+  Output_section*
+  first_section() const;
+
   // Return the address of the first section.
   uint64_t
-  first_section_load_address() const;
+  first_section_load_address() const
+  {
+    const Output_section* os = this->first_section();
+    return os->has_load_address() ? os->load_address() : os->address();
+  }
 
   // Return whether the addresses have been set already.
   bool
Index: gold/output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.170
diff -u -p -r1.170 output.cc
--- gold/output.cc	30 Aug 2012 05:54:59 -0000	1.170
+++ gold/output.cc	1 Sep 2012 03:19:36 -0000
@@ -4613,10 +4613,10 @@ Output_segment::set_tls_offsets()
     (*p)->set_tls_offset(this->vaddr_);
 }
 
-// Return the load address of the first section.
+// Return the first section.
 
-uint64_t
-Output_segment::first_section_load_address() const
+Output_section*
+Output_segment::first_section() const
 {
   for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
     {
@@ -4626,9 +4626,7 @@ Output_segment::first_section_load_addre
 	   ++p)
 	{
 	  if ((*p)->is_section())
-	    return ((*p)->has_load_address()
-		    ? (*p)->load_address()
-		    : (*p)->address());
+	    return static_cast<Output_section*>(*p);
 	}
     }
   gold_unreachable();
Index: gold/target-reloc.h
===================================================================
RCS file: /cvs/src/src/gold/target-reloc.h,v
retrieving revision 1.52
diff -u -p -r1.52 target-reloc.h
--- gold/target-reloc.h	15 Dec 2011 23:29:24 -0000	1.52
+++ gold/target-reloc.h	1 Sep 2012 03:19:36 -0000
@@ -590,12 +590,12 @@ scan_relocatable_relocs(
     }
 }
 
-// Relocate relocs during a relocatable link.  This is a default
-// definition which should work for most targets.
+// Relocate relocs.  Called for a relocatable link, and for --emit-relocs.
+// This is a default definition which should work for most targets.
 
 template<int size, bool big_endian, int sh_type>
 void
-relocate_for_relocatable(
+relocate_relocs(
     const Relocate_info<size, big_endian>* relinfo,
     const unsigned char* prelocs,
     size_t reloc_count,
Index: gold/target.h
===================================================================
RCS file: /cvs/src/src/gold/target.h,v
retrieving revision 1.67
diff -u -p -r1.67 target.h
--- gold/target.h	14 Aug 2012 03:39:03 -0000	1.67
+++ gold/target.h	1 Sep 2012 03:19:36 -0000
@@ -801,23 +801,22 @@ class Sized_target : public Target
 			  const unsigned char* plocal_symbols,
 			  Relocatable_relocs*) = 0;
 
-  // Relocate a section during a relocatable link.  The parameters are
-  // like relocate_section, with additional parameters for the view of
-  // the output reloc section.
-  virtual 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) = 0;
+  // Emit relocations for a section during a relocatable link, and for
+  // --emit-relocs.  The parameters are like relocate_section, with
+  // additional parameters for the view of the output reloc section.
+  virtual 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,
+		  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) = 0;
 
   // Perform target-specific processing in a relocatable link.  This is
   // only used if we use the relocation strategy RELOC_SPECIAL.
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.152
diff -u -p -r1.152 arm.cc
--- gold/arm.cc	11 Jul 2012 14:18:39 -0000	1.152
+++ gold/arm.cc	1 Sep 2012 03:19:35 -0000
@@ -2286,20 +2286,20 @@ class Target_arm : public Sized_target<3
 			  const unsigned char* plocal_symbols,
 			  Relocatable_relocs*);
 
-  // Relocate a section during a relocatable link.
+  // Emit relocations for a section.
   void
-  relocate_for_relocatable(const Relocate_info<32, 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,
-			   Arm_address view_address,
-			   section_size_type view_size,
-			   unsigned char* reloc_view,
-			   section_size_type reloc_view_size);
+  relocate_relocs(const Relocate_info<32, 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,
+		  Arm_address view_address,
+		  section_size_type view_size,
+		  unsigned char* reloc_view,
+		  section_size_type reloc_view_size);
 
   // Perform target-specific processing in a relocatable link.  This is
   // only used if we use the relocation strategy RELOC_SPECIAL.
@@ -9588,11 +9588,11 @@ Target_arm<big_endian>::scan_relocatable
     rr);
 }
 
-// Relocate a section during a relocatable link.
+// Emit relocations for a section.
 
 template<bool big_endian>
 void
-Target_arm<big_endian>::relocate_for_relocatable(
+Target_arm<big_endian>::relocate_relocs(
     const Relocate_info<32, big_endian>* relinfo,
     unsigned int sh_type,
     const unsigned char* prelocs,
@@ -9608,7 +9608,7 @@ Target_arm<big_endian>::relocate_for_rel
 {
   gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::relocate_for_relocatable<32, big_endian, elfcpp::SHT_REL>(
+  gold::relocate_relocs<32, big_endian, elfcpp::SHT_REL>(
     relinfo,
     prelocs,
     reloc_count,
Index: gold/i386.cc
===================================================================
RCS file: /cvs/src/src/gold/i386.cc,v
retrieving revision 1.145
diff -u -p -r1.145 i386.cc
--- gold/i386.cc	2 May 2012 21:37:23 -0000	1.145
+++ gold/i386.cc	1 Sep 2012 03:19:35 -0000
@@ -407,20 +407,20 @@ class Target_i386 : public Sized_target<
 			  const unsigned char* plocal_symbols,
 			  Relocatable_relocs*);
 
-  // Relocate a section during a relocatable link.
+  // Emit relocations for a section.
   void
-  relocate_for_relocatable(const Relocate_info<32, false>*,
-			   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,
-			   elfcpp::Elf_types<32>::Elf_Addr view_address,
-			   section_size_type view_size,
-			   unsigned char* reloc_view,
-			   section_size_type reloc_view_size);
+  relocate_relocs(const Relocate_info<32, false>*,
+		  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,
+		  elfcpp::Elf_types<32>::Elf_Addr view_address,
+		  section_size_type view_size,
+		  unsigned char* reloc_view,
+		  section_size_type reloc_view_size);
 
   // Return a string used to fill a code section with nops.
   std::string
@@ -3602,10 +3602,10 @@ Target_i386::scan_relocatable_relocs(Sym
     rr);
 }
 
-// Relocate a section during a relocatable link.
+// Emit relocations for a section.
 
 void
-Target_i386::relocate_for_relocatable(
+Target_i386::relocate_relocs(
     const Relocate_info<32, false>* relinfo,
     unsigned int sh_type,
     const unsigned char* prelocs,
@@ -3621,7 +3621,7 @@ Target_i386::relocate_for_relocatable(
 {
   gold_assert(sh_type == elfcpp::SHT_REL);
 
-  gold::relocate_for_relocatable<32, false, elfcpp::SHT_REL>(
+  gold::relocate_relocs<32, false, elfcpp::SHT_REL>(
     relinfo,
     prelocs,
     reloc_count,
Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.51
diff -u -p -r1.51 powerpc.cc
--- gold/powerpc.cc	31 Aug 2012 01:09:52 -0000	1.51
+++ gold/powerpc.cc	1 Sep 2012 03:19:36 -0000
@@ -261,20 +261,20 @@ class Target_powerpc : public Sized_targ
 			  const unsigned char* plocal_symbols,
 			  Relocatable_relocs*);
 
-  // Relocate a section during a relocatable link.
+  // Emit relocations for a section.
   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*,
-			   Address view_address,
-			   section_size_type,
-			   unsigned char* reloc_view,
-			   section_size_type reloc_view_size);
+  relocate_relocs(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*,
+		  Address view_address,
+		  section_size_type,
+		  unsigned char* reloc_view,
+		  section_size_type reloc_view_size);
 
   // Return whether SYM is defined by the ABI.
   bool
@@ -2291,6 +2291,7 @@ Target_powerpc<size, big_endian>::Scan::
     case elfcpp::R_POWERPC_GNU_VTENTRY:
     case elfcpp::R_PPC64_TOCSAVE:
     case elfcpp::R_PPC_EMB_MRKREF:
+    case elfcpp::R_POWERPC_TLS:
       break;
 
     case elfcpp::R_PPC64_TOC:
@@ -2482,6 +2483,12 @@ Target_powerpc<size, big_endian>::Scan::
 	else if (tls_type == tls::TLSOPT_TO_LE)
 	  {
 	    // no GOT relocs needed for Local Exec.
+	    if (parameters->options().emit_relocs())
+	      {
+		Output_section* os = layout->tls_segment()->first_section();
+		gold_assert(os != NULL);
+		os->set_needs_symtab_index();
+	      }
 	  }
 	else
 	  gold_unreachable();
@@ -2570,6 +2577,7 @@ Target_powerpc<size, big_endian>::Scan::
     case elfcpp::R_POWERPC_GNU_VTENTRY:
     case elfcpp::R_PPC_LOCAL24PC:
     case elfcpp::R_PPC_EMB_MRKREF:
+    case elfcpp::R_POWERPC_TLS:
       break;
 
     case elfcpp::R_PPC64_TOC:
@@ -2814,6 +2822,12 @@ Target_powerpc<size, big_endian>::Scan::
 	else if (tls_type == tls::TLSOPT_TO_LE)
 	  {
 	    // no GOT relocs needed for Local Exec.
+	    if (parameters->options().emit_relocs())
+	      {
+		Output_section* os = layout->tls_segment()->first_section();
+		gold_assert(os != NULL);
+		os->set_needs_symtab_index();
+	      }
 	  }
 	else
 	  gold_unreachable();
@@ -3198,7 +3212,7 @@ Target_powerpc<size, big_endian>::Reloca
 		insn = addis_3_2;
 	      elfcpp::Swap<32, big_endian>::writeval(iview, insn);
 	      r_type = elfcpp::R_POWERPC_TPREL16_HA;
-	      value = relinfo->layout->tls_segment()->vaddr() + dtp_offset;
+	      value = dtp_offset;
 	    }
 	  else
 	    {
@@ -3324,7 +3338,7 @@ Target_powerpc<size, big_endian>::Reloca
 	  this->call_tls_get_addr_ = CALL_SKIP;
 	  r_type = elfcpp::R_POWERPC_TPREL16_LO;
 	  view += 2 * big_endian;
-	  value = relinfo->layout->tls_segment()->vaddr() + dtp_offset;
+	  value = dtp_offset;
 	}
     }
   else if (r_type == elfcpp::R_POWERPC_TLS)
@@ -3880,7 +3894,7 @@ Target_powerpc<size, big_endian>::scan_r
     rr);
 }
 
-// Relocate a section during a relocatable link.
+// Emit relocations for a section.
 // This is a modified version of the function by the same name in
 // target-reloc.h.  Using relocate_special_relocatable for
 // R_PPC_PLTREL24 would require duplication of the entire body of the
@@ -3888,7 +3902,7 @@ Target_powerpc<size, big_endian>::scan_r
 
 template<int size, bool big_endian>
 void
-Target_powerpc<size, big_endian>::relocate_for_relocatable(
+Target_powerpc<size, big_endian>::relocate_relocs(
     const Relocate_info<size, big_endian>* relinfo,
     unsigned int sh_type,
     const unsigned char* prelocs,
@@ -3923,7 +3937,7 @@ Target_powerpc<size, big_endian>::reloca
     }
 
   unsigned char* pwrite = reloc_view;
-
+  bool zap_next = false;
   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
     {
       Relocatable_relocs::Reloc_strategy strategy = rr->strategy(i);
@@ -3933,25 +3947,35 @@ Target_powerpc<size, big_endian>::reloca
       Reltype reloc(prelocs);
       Reltype_write reloc_write(pwrite);
 
+      Address offset = reloc.get_r_offset();
       typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
-      const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
-      const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
+      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
+      unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
+      const unsigned int orig_r_sym = r_sym;
+      typename elfcpp::Elf_types<size>::Elf_Swxword addend
+	= reloc.get_r_addend();
+      const Symbol* gsym = NULL;
+
+      if (zap_next)
+	{
+	  // We could arrange to discard these and other relocs for
+	  // tls optimised sequences in the strategy methods, but for
+	  // now do as BFD ld does.
+	  r_type = elfcpp::R_POWERPC_NONE;
+	  zap_next = false;
+	}
 
       // Get the new symbol index.
-
-      unsigned int new_symndx;
       if (r_sym < local_count)
 	{
 	  switch (strategy)
 	    {
 	    case Relocatable_relocs::RELOC_COPY:
 	    case Relocatable_relocs::RELOC_SPECIAL:
-	      if (r_sym == 0)
-		new_symndx = 0;
-	      else
+	      if (r_sym != 0)
 		{
-		  new_symndx = object->symtab_index(r_sym);
-		  gold_assert(new_symndx != -1U);
+		  r_sym = object->symtab_index(r_sym);
+		  gold_assert(r_sym != -1U);
 		}
 	      break;
 
@@ -3969,7 +3993,7 @@ Target_powerpc<size, big_endian>::reloca
 		Output_section* os = object->output_section(shndx);
 		gold_assert(os != NULL);
 		gold_assert(os->needs_symtab_index());
-		new_symndx = os->symtab_index();
+		r_sym = os->symtab_index();
 	      }
 	      break;
 
@@ -3979,22 +4003,19 @@ Target_powerpc<size, big_endian>::reloca
 	}
       else
 	{
-	  const Symbol* gsym = object->global_symbol(r_sym);
+	  gsym = object->global_symbol(r_sym);
 	  gold_assert(gsym != NULL);
 	  if (gsym->is_forwarder())
 	    gsym = relinfo->symtab->resolve_forwards(gsym);
 
 	  gold_assert(gsym->has_symtab_index());
-	  new_symndx = gsym->symtab_index();
+	  r_sym = gsym->symtab_index();
 	}
 
       // Get the new offset--the location in the output section where
       // this relocation should be applied.
-
-      Address offset = reloc.get_r_offset();
-      Address new_offset;
       if (static_cast<Address>(offset_in_output_section) != invalid_address)
-	new_offset = offset + offset_in_output_section;
+	offset += offset_in_output_section;
       else
 	{
 	  section_offset_type sot_offset =
@@ -4003,34 +4024,25 @@ Target_powerpc<size, big_endian>::reloca
 	    output_section->output_offset(object, relinfo->data_shndx,
 					  sot_offset);
 	  gold_assert(new_sot_offset != -1);
-	  new_offset = new_sot_offset;
+	  offset = new_sot_offset;
 	}
 
       // In an object file, r_offset is an offset within the section.
       // In an executable or dynamic object, generated by
       // --emit-relocs, r_offset is an absolute address.
-      // FIXME: Arrange to call this function for --emit-relocs too,
-      // so that we can make emitted relocs match edited TLS code.
-      if (0 && !parameters->options().relocatable())
+      if (!parameters->options().relocatable())
 	{
-	  new_offset += view_address;
+	  offset += view_address;
 	  if (static_cast<Address>(offset_in_output_section) != invalid_address)
-	    new_offset -= offset_in_output_section;
+	    offset -= offset_in_output_section;
 	}
 
-      reloc_write.put_r_offset(new_offset);
-      reloc_write.put_r_info(elfcpp::elf_r_info<size>(new_symndx, r_type));
-
       // Handle the reloc addend based on the strategy.
-      typename elfcpp::Elf_types<size>::Elf_Swxword addend;
-      addend = Reloc_types<elfcpp::SHT_RELA, size, big_endian>::
-	get_reloc_addend(&reloc);
-
       if (strategy == Relocatable_relocs::RELOC_COPY)
 	;
       else if (strategy == Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA)
 	{
-	  const Symbol_value<size>* psymval = object->local_symbol(r_sym);
+	  const Symbol_value<size>* psymval = object->local_symbol(orig_r_sym);
 	  addend = psymval->value(object, addend);
 	}
       else if (strategy == Relocatable_relocs::RELOC_SPECIAL)
@@ -4041,8 +4053,136 @@ Target_powerpc<size, big_endian>::reloca
       else
 	gold_unreachable();
 
-      Reloc_types<elfcpp::SHT_RELA, size, big_endian>::
-	set_reloc_addend(&reloc_write, addend);
+      if (!parameters->options().relocatable())
+	{
+	  if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16
+	      || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO
+	      || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_HI
+	      || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_HA)
+	    {
+	      // First instruction of a global dynamic sequence,
+	      // arg setup insn.
+	      const bool final = gsym == NULL || gsym->final_value_is_known();
+	      switch (this->optimize_tls_gd(final))
+		{
+		case tls::TLSOPT_TO_IE:
+		  r_type += (elfcpp::R_POWERPC_GOT_TPREL16
+			     - elfcpp::R_POWERPC_GOT_TLSGD16);
+		  break;
+		case tls::TLSOPT_TO_LE:
+		  if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16
+		      || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO)
+		    r_type = elfcpp::R_POWERPC_TPREL16_HA;
+		  else
+		    {
+		      r_type = elfcpp::R_POWERPC_NONE;
+		      offset -= 2 * big_endian;
+		    }
+		  break;
+		default:
+		  break;
+		}
+	    }
+	  else if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16
+		   || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO
+		   || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_HI
+		   || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_HA)
+	    {
+	      // First instruction of a local dynamic sequence,
+	      // arg setup insn.
+	      if (this->optimize_tls_ld() == tls::TLSOPT_TO_LE)
+		{
+		  if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16
+		      || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO)
+		    {
+		      r_type = elfcpp::R_POWERPC_TPREL16_HA;
+		      Output_section* os = relinfo->layout->tls_segment()
+			->first_section();
+		      gold_assert(os != NULL);
+		      gold_assert(os->needs_symtab_index());
+		      r_sym = os->symtab_index();
+		      addend = dtp_offset;
+		    }
+		  else
+		    {
+		      r_type = elfcpp::R_POWERPC_NONE;
+		      offset -= 2 * big_endian;
+		    }
+		}
+	    }
+	  else if (r_type == elfcpp::R_POWERPC_GOT_TPREL16
+		   || r_type == elfcpp::R_POWERPC_GOT_TPREL16_LO
+		   || r_type == elfcpp::R_POWERPC_GOT_TPREL16_HI
+		   || r_type == elfcpp::R_POWERPC_GOT_TPREL16_HA)
+	    {
+	      // First instruction of initial exec sequence.
+	      const bool final = gsym == NULL || gsym->final_value_is_known();
+	      if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE)
+		{
+		  if (r_type == elfcpp::R_POWERPC_GOT_TPREL16
+		      || r_type == elfcpp::R_POWERPC_GOT_TPREL16_LO)
+		    r_type = elfcpp::R_POWERPC_TPREL16_HA;
+		  else
+		    {
+		      r_type = elfcpp::R_POWERPC_NONE;
+		      offset -= 2 * big_endian;
+		    }
+		}
+	    }
+	  else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSGD)
+		   || (size == 32 && r_type == elfcpp::R_PPC_TLSGD))
+	    {
+	      // Second instruction of a global dynamic sequence,
+	      // the __tls_get_addr call
+	      const bool final = gsym == NULL || gsym->final_value_is_known();
+	      switch (this->optimize_tls_gd(final))
+		{
+		case tls::TLSOPT_TO_IE:
+		  r_type = elfcpp::R_POWERPC_NONE;
+		  zap_next = true;
+		  break;
+		case tls::TLSOPT_TO_LE:
+		  r_type = elfcpp::R_POWERPC_TPREL16_LO;
+		  offset += 2 * big_endian;
+		  zap_next = true;
+		  break;
+		default:
+		  break;
+		}
+	    }
+	  else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSLD)
+		   || (size == 32 && r_type == elfcpp::R_PPC_TLSLD))
+	    {
+	      // Second instruction of a local dynamic sequence,
+	      // the __tls_get_addr call
+	      if (this->optimize_tls_ld() == tls::TLSOPT_TO_LE)
+		{
+		  Output_section* os = relinfo->layout->tls_segment()
+		    ->first_section();
+		  gold_assert(os != NULL);
+		  gold_assert(os->needs_symtab_index());
+		  r_sym = os->symtab_index();
+		  addend = dtp_offset;
+		  r_type = elfcpp::R_POWERPC_TPREL16_LO;
+		  offset += 2 * big_endian;
+		  zap_next = true;
+		}
+	    }
+	  else if (r_type == elfcpp::R_POWERPC_TLS)
+	    {
+	      // Second instruction of an initial exec sequence
+	      const bool final = gsym == NULL || gsym->final_value_is_known();
+	      if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE)
+		{
+		  r_type = elfcpp::R_POWERPC_TPREL16_LO;
+		  offset += 2 * big_endian;
+		}
+	    }
+	}
+
+      reloc_write.put_r_offset(offset);
+      reloc_write.put_r_info(elfcpp::elf_r_info<size>(r_sym, r_type));
+      reloc_write.put_r_addend(addend);
 
       pwrite += reloc_size;
     }
Index: gold/sparc.cc
===================================================================
RCS file: /cvs/src/src/gold/sparc.cc,v
retrieving revision 1.58
diff -u -p -r1.58 sparc.cc
--- gold/sparc.cc	2 May 2012 21:37:23 -0000	1.58
+++ gold/sparc.cc	1 Sep 2012 03:19:36 -0000
@@ -131,20 +131,21 @@ class Target_sparc : public Sized_target
 			  const unsigned char* plocal_symbols,
 			  Relocatable_relocs*);
 
-  // Relocate a section during a relocatable link.
+  // Emit relocations for a section.
   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);
+  relocate_relocs(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);
+
   // Return whether SYM is defined by the ABI.
   bool
   do_is_defined_by_abi(const Symbol* sym) const
@@ -4197,11 +4198,11 @@ Target_sparc<size, big_endian>::scan_rel
     rr);
 }
 
-// Relocate a section during a relocatable link.
+// Emit relocations for a section.
 
 template<int size, bool big_endian>
 void
-Target_sparc<size, big_endian>::relocate_for_relocatable(
+Target_sparc<size, big_endian>::relocate_relocs(
     const Relocate_info<size, big_endian>* relinfo,
     unsigned int sh_type,
     const unsigned char* prelocs,
@@ -4217,7 +4218,7 @@ Target_sparc<size, big_endian>::relocate
 {
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_for_relocatable<size, big_endian, elfcpp::SHT_RELA>(
+  gold::relocate_relocs<size, big_endian, elfcpp::SHT_RELA>(
     relinfo,
     prelocs,
     reloc_count,
Index: gold/x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.154
diff -u -p -r1.154 x86_64.cc
--- gold/x86_64.cc	15 Aug 2012 04:03:54 -0000	1.154
+++ gold/x86_64.cc	1 Sep 2012 03:19:36 -0000
@@ -469,9 +469,9 @@ class Target_x86_64 : public Sized_targe
 			  const unsigned char* plocal_symbols,
 			  Relocatable_relocs*);
 
-  // Relocate a section during a relocatable link.
+  // Emit relocations for a section.
   void
-  relocate_for_relocatable(
+  relocate_relocs(
       const Relocate_info<size, false>*,
       unsigned int sh_type,
       const unsigned char* prelocs,
@@ -4208,7 +4208,7 @@ Target_x86_64<size>::scan_relocatable_re
 
 template<int size>
 void
-Target_x86_64<size>::relocate_for_relocatable(
+Target_x86_64<size>::relocate_relocs(
     const Relocate_info<size, false>* relinfo,
     unsigned int sh_type,
     const unsigned char* prelocs,
@@ -4224,7 +4224,7 @@ Target_x86_64<size>::relocate_for_reloca
 {
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_for_relocatable<size, false, elfcpp::SHT_RELA>(
+  gold::relocate_relocs<size, false, elfcpp::SHT_RELA>(
     relinfo,
     prelocs,
     reloc_count,
Index: gold/testsuite/testfile.cc
===================================================================
RCS file: /cvs/src/src/gold/testsuite/testfile.cc,v
retrieving revision 1.22
diff -u -p -r1.22 testfile.cc
--- gold/testsuite/testfile.cc	2 May 2012 21:37:24 -0000	1.22
+++ gold/testsuite/testfile.cc	1 Sep 2012 03:19:36 -0000
@@ -72,14 +72,14 @@ class Target_test : public Sized_target<
   { ERROR("call to Target_test::scan_relocatable_relocs"); }
 
   void
-  relocate_for_relocatable(const Relocate_info<size, big_endian>*,
-			   unsigned int, const unsigned char*, size_t,
-			   Output_section*, off_t, const Relocatable_relocs*,
-			   unsigned char*,
-			   typename elfcpp::Elf_types<size>::Elf_Addr,
-			   section_size_type, unsigned char*,
-			   section_size_type)
-  { ERROR("call to Target_test::relocate_for_relocatable"); }
+  relocate_relocs(const Relocate_info<size, big_endian>*,
+		  unsigned int, const unsigned char*, size_t,
+		  Output_section*, off_t, const Relocatable_relocs*,
+		  unsigned char*,
+		  typename elfcpp::Elf_types<size>::Elf_Addr,
+		  section_size_type, unsigned char*,
+		  section_size_type)
+  { ERROR("call to Target_test::relocate_relocs"); }
 
   static const Target::Target_info test_target_info;
 };

-- 
Alan Modra
Australia Development Lab, IBM


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