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 10:01:14 -0800

> David Miller <davem@davemloft.net> writes:
> 
>> From: Ian Lance Taylor <iant@google.com>
>> Date: Tue, 09 Feb 2010 07:04:13 -0800
>>
>>> Another approach would be to in fact put the PLT into the .rela.dyn
>>> output section.  That could be done by just changing the call to
>>> layout->add_output_section_data to use .rela.dyn in both SHT_RELA
>>> calls in sparc.cc.
>>
>> So I tried this, and it doesn't work, even if I force the .rela.dyn to
>> get created before the PLT relocation section.
>>
>> The dynamic linker doesn't process the PLT relocations properly.
> 
> You may need to change Layout::add_target_dynamic_tags to
> dyn_rel->output_section().

Still fails the same way, even if I do this.

Let's stick to the original game plan.

Ok to commit?

I'll look now at the remaining 11 sparc gold testsuite failures.

gold/

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

	* output.h (Output_data_dynamic::add_section_size): New method
	that takes two Output_data objects.
	(Output_data_dynamic::Dynamic_entry): Create storage for secondary
	entry param.  Handle it in initializers.
	* output.cc (Output_data_dynamic::Dynamic_entry::write): For
	DYNAMIC_SECTION_SIZE, add in second object size if non-NULL.
	* layout.h (Layout::add_target_dynamic_tags): Add dynrel_includes_plt
	arg.
	* layout.cc (Layout::add_target_dynamic_tags): If dynrel_includes_plt,
	and .rela.plt exists, set DT_REL{,A}SZ to sum of .rela.dyn and .rela.plt
	* arm.cc (Target_arm::do_finalize_sections): Update to pass false
	for dynrel_includes_plt.
	* i386.cc (Target_i386::do_finalize_sections): Likewise.
	* x86_64.cc (Target_x86_64::do_finalize_sections): Likewise.
	* sparc.cc (Target_sparc::make_plt_entry): Force .rela.dyn to be output
	before .rela.plt
	(Target_sparc::do_finalize_sections): Update to pass true for
	dynrel_includes_plt.
	* powerpc.cc (Target_powerpc::make_plt_entry): Force .rela.dyn to be
	output before .rela.plt
	(Target_powerpc::do_finalize_sections): Update to pass true for
	dynrel_includes_plt when 32-bit.
---
 gold/arm.cc     |    2 +-
 gold/i386.cc    |    2 +-
 gold/layout.cc  |   10 +++++++---
 gold/layout.h   |    2 +-
 gold/output.cc  |    2 ++
 gold/output.h   |   16 +++++++++++++++-
 gold/powerpc.cc |    7 ++++++-
 gold/sparc.cc   |    7 ++++++-
 gold/x86_64.cc  |    2 +-
 9 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/gold/arm.cc b/gold/arm.cc
index f121f93..902805c 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -7094,7 +7094,7 @@ Target_arm<big_endian>::do_finalize_sections(
 				  ? NULL
 				  : this->plt_->rel_plt());
   layout->add_target_dynamic_tags(true, this->got_plt_, rel_plt,
-				  this->rel_dyn_, true);
+				  this->rel_dyn_, true, false);
 
   // Emit any relocs we saved in an attempt to avoid generating COPY
   // relocs.
diff --git a/gold/i386.cc b/gold/i386.cc
index 2eab3f8..f2a7b53 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -1609,7 +1609,7 @@ Target_i386::do_finalize_sections(
 				  ? NULL
 				  : this->plt_->rel_plt());
   layout->add_target_dynamic_tags(true, this->got_plt_, rel_plt,
-				  this->rel_dyn_, true);
+				  this->rel_dyn_, true, false);
 
   // Emit any relocs we saved in an attempt to avoid generating COPY
   // relocs.
diff --git a/gold/layout.cc b/gold/layout.cc
index 52989a5..faa0c72 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -3240,7 +3240,7 @@ void
 Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
 				const Output_data* plt_rel,
 				const Output_data_reloc_generic* dyn_rel,
-				bool add_debug)
+				bool add_debug, bool dynrel_includes_plt)
 {
   Output_data_dynamic* odyn = this->dynamic_data_;
   if (odyn == NULL)
@@ -3261,8 +3261,12 @@ Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
     {
       odyn->add_section_address(use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA,
 				dyn_rel);
-      odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
-			     dyn_rel);
+      if (plt_rel != NULL && dynrel_includes_plt)
+	odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
+			       dyn_rel, plt_rel);
+      else
+	odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
+			       dyn_rel);
       const int size = parameters->target().get_size();
       elfcpp::DT rel_tag;
       int rel_size;
diff --git a/gold/layout.h b/gold/layout.h
index 15e7548..cd15c98 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -563,7 +563,7 @@ class Layout
   add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
 			  const Output_data* plt_rel,
 			  const Output_data_reloc_generic* dyn_rel,
-			  bool add_debug);
+			  bool add_debug, bool dynrel_includes_plt);
 
   // Compute and write out the build ID if needed.
   void
diff --git a/gold/output.cc b/gold/output.cc
index a8f03e7..5c4cb22 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1560,6 +1560,8 @@ Output_data_dynamic::Dynamic_entry::write(
 
     case DYNAMIC_SECTION_SIZE:
       val = this->u_.od->data_size();
+      if (this->od2)
+	val += this->od2->data_size();
       break;
 
     case DYNAMIC_SYMBOL:
diff --git a/gold/output.h b/gold/output.h
index 60d57de..6a9b1a2 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1997,6 +1997,12 @@ class Output_data_dynamic : public Output_section_data
   add_section_size(elfcpp::DT tag, const Output_data* od)
   { this->add_entry(Dynamic_entry(tag, od, true)); }
 
+  // Add a new dynamic entry with the total size of two output datas.
+  void
+  add_section_size(elfcpp::DT tag, const Output_data* od,
+		   const Output_data* od2)
+  { this->add_entry(Dynamic_entry(tag, od, od2)); }
+
   // Add a new dynamic entry with the address of a symbol.
   void
   add_symbol(elfcpp::DT tag, const Symbol* sym)
@@ -2045,7 +2051,13 @@ class Output_data_dynamic : public Output_section_data
 	offset_(section_size
 		? DYNAMIC_SECTION_SIZE
 		: DYNAMIC_SECTION_ADDRESS)
-    { this->u_.od = od; }
+    { this->u_.od = od; this->od2 = NULL; }
+
+    // Create an entry with the size of two sections.
+    Dynamic_entry(elfcpp::DT tag, const Output_data* od, const Output_data* od2)
+      : tag_(tag),
+	offset_(DYNAMIC_SECTION_SIZE)
+    { this->u_.od = od; this->od2 = od2; }
 
     // Create an entry with the address of a section plus a constant offset.
     Dynamic_entry(elfcpp::DT tag, const Output_data* od, unsigned int offset)
@@ -2101,6 +2113,8 @@ class Output_data_dynamic : public Output_section_data
       // For DYNAMIC_STRING.
       const char* str;
     } u_;
+    // For DYNAMIC_SYMBOL with two sections.
+    const Output_data* od2;
     // The dynamic tag.
     elfcpp::DT tag_;
     // The type of entry (Classification) or offset within a section.
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 83bb992..cc46782 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -948,6 +948,11 @@ Target_powerpc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
       // Create the GOT section first.
       this->got_section(symtab, layout);
 
+      // Ensure that .rela.dyn always appears before .rela.plt  This is
+      // necessary due to how, on PowerPC and some other targets, .rela.dyn
+      // needs to include .rela.plt in it's range.
+      this->rela_dyn_section(layout);
+
       this->plt_ = new Output_data_plt_powerpc<size, big_endian>(layout);
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
@@ -1556,7 +1561,7 @@ Target_powerpc<size, big_endian>::do_finalize_sections(
 				  ? NULL
 				  : this->plt_->rel_plt());
   layout->add_target_dynamic_tags(false, this->plt_, rel_plt,
-				  this->rela_dyn_, true);
+				  this->rela_dyn_, true, size == 32);
 
   // Emit any relocs we saved in an attempt to avoid generating COPY
   // relocs.
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 9bca176..d3c9435 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -1369,6 +1369,11 @@ Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
       // Create the GOT sections first.
       this->got_section(symtab, layout);
 
+      // Ensure that .rela.dyn always appears before .rela.plt  This is
+      // necessary due to how, on Sparc and some other targets, .rela.dyn
+      // needs to include .rela.plt in it's range.
+      this->rela_dyn_section(layout);
+
       this->plt_ = new Output_data_plt_sparc<size, big_endian>(layout);
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
@@ -2341,7 +2346,7 @@ Target_sparc<size, big_endian>::do_finalize_sections(
 				  ? NULL
 				  : this->plt_->rel_plt());
   layout->add_target_dynamic_tags(false, this->plt_, rel_plt,
-				  this->rela_dyn_, true);
+				  this->rela_dyn_, true, true);
 
   // Emit any relocs we saved in an attempt to avoid generating COPY
   // relocs.
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 585a499..fea2ec9 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -1741,7 +1741,7 @@ Target_x86_64::do_finalize_sections(
 				  ? NULL
 				  : this->plt_->rela_plt());
   layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
-				  this->rela_dyn_, true);
+				  this->rela_dyn_, true, false);
 				  
   // Fill in some more dynamic tags.
   Output_data_dynamic* const odyn = layout->dynamic_data();
-- 
1.6.6.1


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