public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [GOLD] Support setting DT_RELACOUNT late
@ 2023-06-23 11:39 Alan Modra
  2023-06-23 11:40 ` [GOLD] PowerPC64 huge branch dynamic relocs Alan Modra
  0 siblings, 1 reply; 2+ messages in thread
From: Alan Modra @ 2023-06-23 11:39 UTC (permalink / raw)
  To: binutils

PowerPC gold adds relative dynamic relocs in do_relax.  These aren't
accounted for in the value set in add_target_dynamic_tags, which is
called before do_relax.  Provide a way of setting DT_RELCOUNT and
DT_RELACOUNT at the point where .dynamic is written.

	* layout.cc (Layout::add_target_dynamic_tags): Add custom_relcount
	parameter.  Emit DT_RELCOUNT/RELACOUNT as a custom target handled
	dynamic tag if set.
	* layout.h(Layout::add_target_dynamic_tags): Update prototype.
	* aarch64.cc (Target_aarch64::do_finalize_sections): Adjust
	add_target_dynamic_tags call.
	* arm.cc (Target_arm::do_finalize_sections): Likewise.
	* i386.cc (Target_i386::do_finalize_sections): Likewise.
	* mips.cc (Target_mips::do_finalize_sections): Likewise.
	* s390.cc (Target_s390::do_finalize_sections): Likewise.
	* sparc.cc (Target_sparc::do_finalize_sections): Likewise.
	* tilegx.cc (Target_tilegx::do_finalize_sections): Likewise.
	* x86_64.cc (Target_x86_64::do_finalize_sections): Likewise.
	* powerpc.cc (Target_powerpc::do_finalize_sections): Likewise.
	(Target_powerpc::do_dynamic_tag_custom_value): New function.

diff --git a/gold/aarch64.cc b/gold/aarch64.cc
index 46a278bd466..7f95c0cf13b 100644
--- a/gold/aarch64.cc
+++ b/gold/aarch64.cc
@@ -6951,7 +6951,7 @@ Target_aarch64<size, big_endian>::do_finalize_sections(
 				  ? NULL
 				  : this->plt_->rela_plt());
   layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
-				  this->rela_dyn_, true, false);
+				  this->rela_dyn_, true, false, false);
 
   // Emit any relocs we saved in an attempt to avoid generating COPY
   // relocs.
diff --git a/gold/arm.cc b/gold/arm.cc
index 1ab8eb5db72..f787c28e0a7 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -9484,7 +9484,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, false);
+				  this->rel_dyn_, true, false, 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 d97e818ba0d..c4ea8798a98 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -2672,7 +2672,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, false);
+				  this->rel_dyn_, true, false, 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 a50086897bb..b94855f8662 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -5138,7 +5138,8 @@ 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 dynrel_includes_plt)
+				bool add_debug, bool dynrel_includes_plt,
+				bool custom_relcount)
 {
   Output_data_dynamic* odyn = this->dynamic_data_;
   if (odyn == NULL)
@@ -5203,11 +5204,15 @@ Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
       if (parameters->options().combreloc() && have_dyn_rel)
 	{
 	  size_t c = dyn_rel->relative_reloc_count();
-	  if (c > 0)
-	    odyn->add_constant((use_rel
-				? elfcpp::DT_RELCOUNT
-				: elfcpp::DT_RELACOUNT),
-			       c);
+	  if (c != 0)
+	    {
+	      elfcpp::DT tag
+		= use_rel ? elfcpp::DT_RELCOUNT : elfcpp::DT_RELACOUNT;
+	      if (custom_relcount)
+		odyn->add_custom(tag);
+	      else
+		odyn->add_constant(tag, c);
+	    }
 	}
     }
 
diff --git a/gold/layout.h b/gold/layout.h
index 5bb9aff5b04..040c98cd9aa 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -950,7 +950,8 @@ 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 dynrel_includes_plt);
+			  bool add_debug, bool dynrel_includes_plt,
+			  bool custom_relcount);
 
   // Add a target-specific dynamic tag with constant value.
   void
diff --git a/gold/mips.cc b/gold/mips.cc
index bd7353b450e..a6a41d7a5e4 100644
--- a/gold/mips.cc
+++ b/gold/mips.cc
@@ -9826,7 +9826,7 @@ Target_mips<size, big_endian>::do_finalize_sections(Layout* layout,
   const Reloc_section* rel_plt = (this->plt_ == NULL
                                   ? NULL : this->plt_->rel_plt());
   layout->add_target_dynamic_tags(true, this->got_, rel_plt,
-                                  this->rel_dyn_, true, false);
+				  this->rel_dyn_, true, false, false);
 
   Output_data_dynamic* const odyn = layout->dynamic_data();
   if (odyn != NULL
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 0c15e1b3721..5838b49e341 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -796,6 +796,10 @@ class Target_powerpc : public Sized_target<size, big_endian>
   void
   do_finalize_sections(Layout*, const Input_objects*, Symbol_table*);
 
+  // Get the custom dynamic tag value.
+  unsigned int
+  do_dynamic_tag_custom_value(elfcpp::DT) const;
+
   // Return the value to use for a dynamic which requires special
   // treatment.
   uint64_t
@@ -10135,7 +10139,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, size == 32);
+				      this->rela_dyn_, true, size == 32, true);
 
       if (size == 32)
 	{
@@ -10206,6 +10210,18 @@ Target_powerpc<size, big_endian>::do_finalize_sections(
     }
 }
 
+// Get the custom dynamic tag value.
+
+template<int size, bool big_endian>
+unsigned int
+Target_powerpc<size, big_endian>::do_dynamic_tag_custom_value(
+    elfcpp::DT tag) const
+{
+  if (tag != elfcpp::DT_RELACOUNT)
+    gold_unreachable();
+  return this->rela_dyn_->relative_reloc_count();
+}
+
 // Merge object attributes from input file called NAME with those of the
 // output.  The input object attributes are in the object pointed by PASD.
 
diff --git a/gold/s390.cc b/gold/s390.cc
index 9e555c9d6c5..6e53735351e 100644
--- a/gold/s390.cc
+++ b/gold/s390.cc
@@ -4043,7 +4043,7 @@ Target_s390<size>::do_finalize_sections(
 				  ? NULL
 				  : this->plt_->rela_plt());
   layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
-				  this->rela_dyn_, true, size == 32);
+				  this->rela_dyn_, true, size == 32, false);
 
   this->layout_ = layout;
 
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 61904f91a41..42c4a3232b1 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -3197,7 +3197,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, true);
+				  this->rela_dyn_, true, true, false);
 
   // Emit any relocs we saved in an attempt to avoid generating COPY
   // relocs.
diff --git a/gold/tilegx.cc b/gold/tilegx.cc
index 69d4e640a1e..a054b6701e4 100644
--- a/gold/tilegx.cc
+++ b/gold/tilegx.cc
@@ -4265,7 +4265,7 @@ Target_tilegx<size, big_endian>::do_finalize_sections(
                                   ? NULL
                                   : this->plt_->rela_plt());
   layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
-                                  this->rela_dyn_, true, true);
+				  this->rela_dyn_, true, true, false);
 
   // 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 6cace049f66..928dfa8ea34 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -4073,7 +4073,7 @@ Target_x86_64<size>::do_finalize_sections(
 				  ? NULL
 				  : this->plt_->rela_plt());
   layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
-				  this->rela_dyn_, true, false);
+				  this->rela_dyn_, true, false, false);
 
   // Fill in some more dynamic tags.
   Output_data_dynamic* const odyn = layout->dynamic_data();

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [GOLD] PowerPC64 huge branch dynamic relocs
  2023-06-23 11:39 [GOLD] Support setting DT_RELACOUNT late Alan Modra
@ 2023-06-23 11:40 ` Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2023-06-23 11:40 UTC (permalink / raw)
  To: binutils

PowerPC64 gold and ld.bfd implement an indirect branch trampoline,
used when the destination of a branch exceeds a bounce through another
"b" instruction.  When generating PIEs or shared libraries, the
addresses need dynamic relocations.  This was implemented in gold
using a dedicated relocation section, but this means the relative
relocations for these addresses are not sorted properly with other
dynamic relative relocations: gold doesn't support merging relocation
sections, then sorting.  Instead we need to use a single .rela.dyn
section.

This is done by increasing the size of rela_dyn_ during do_relax to
account for needed dynamic relocations, delaying adding the actual
relocations until the end of relaxation once the layout has
stabilised.

	* powerpc.cc (Target_powerpc): Add rela_dyn_size_;
	(update_current_size): New function.
	(Target_powerpc::do_relax): Capture the size of rela_dyn_ at
	the start of relaxation.  Artifically increase its size during
	relaxation to account for needed indirect branches, and add
	those relocations at the end.
	(Output_data_brlt_powerpc::rel_, reset_brlt_sizes),
	(finalize_brlt_sizes, add_reloc, set_current_size): Delete.
	(Target_powerpc::make_brlt_section): Don't make reloc section.

diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 5838b49e341..96fef7b8dde 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -1763,6 +1763,8 @@ class Target_powerpc : public Sized_target<size, big_endian>
   Branches branch_info_;
   Tocsave_loc tocsave_loc_;
 
+  off_t rela_dyn_size_;
+
   bool power10_relocs_;
   bool plt_thread_safe_;
   bool plt_localentry0_;
@@ -3687,6 +3689,18 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
   return ok;
 }
 
+// Helper for do_relax, avoiding checks that size, address and offset
+// are not set more than once.
+
+static inline void
+update_current_size(Output_section_data_build* od, off_t cur_size)
+{
+  od->reset_address_and_file_offset();
+  od->set_current_data_size(cur_size);
+  od->finalize_data_size();
+  od->output_section()->set_section_offsets_need_adjustment();
+}
+
 // Relaxation hook.  This is where we do stub generation.
 
 template<int size, bool big_endian>
@@ -3752,10 +3766,11 @@ Target_powerpc<size, big_endian>::do_relax(int pass,
 	    }
 	}
       this->plt_thread_safe_ = thread_safe;
-    }
 
-  if (pass == 1)
-    {
+      if (parameters->options().output_is_position_independent())
+	this->rela_dyn_size_
+	  = this->rela_dyn_section(layout)->current_data_size();
+
       this->stub_group_size_ = parameters->options().stub_group_size();
       bool no_size_errors = true;
       if (this->stub_group_size_ == 1)
@@ -3868,7 +3883,15 @@ Target_powerpc<size, big_endian>::do_relax(int pass,
   if (size == 64 && num_huge_branches != 0)
     this->make_brlt_section(layout);
   if (size == 64 && again)
-    this->brlt_section_->set_current_size(num_huge_branches);
+    {
+      update_current_size(this->brlt_section_, num_huge_branches * 16);
+      if (parameters->options().output_is_position_independent())
+	{
+	  const unsigned int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
+	  off_t cur = this->rela_dyn_size_ + num_huge_branches * reloc_size;
+	  update_current_size(this->rela_dyn_, cur);
+	}
+    }
 
   for (typename Stub_tables::reverse_iterator p = this->stub_tables_.rbegin();
        p != this->stub_tables_.rend();
@@ -3937,15 +3960,21 @@ Target_powerpc<size, big_endian>::do_relax(int pass,
       && parameters->options().output_is_position_independent())
     {
       // Fill in the BRLT relocs.
-      this->brlt_section_->reset_brlt_sizes();
+      this->rela_dyn_->reset_data_size();
+      this->rela_dyn_->set_current_data_size(this->rela_dyn_size_);
       for (typename Branch_lookup_table::const_iterator p
 	     = this->branch_lookup_table_.begin();
 	   p != this->branch_lookup_table_.end();
 	   ++p)
 	{
-	  this->brlt_section_->add_reloc(p->first, p->second);
+	  this->rela_dyn_->add_relative(elfcpp::R_POWERPC_RELATIVE,
+					this->brlt_section_, p->second,
+					p->first);
 	}
-      this->brlt_section_->finalize_brlt_sizes();
+      this->rela_dyn_->finalize_data_size();
+      const unsigned int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
+      gold_assert(this->rela_dyn_->data_size()
+		  == this->rela_dyn_size_ + num_huge_branches * reloc_size);
     }
 
   if (!again
@@ -4554,52 +4583,11 @@ class Output_data_brlt_powerpc : public Output_section_data_build
   typedef Output_data_reloc<elfcpp::SHT_RELA, true,
 			    size, big_endian> Reloc_section;
 
-  Output_data_brlt_powerpc(Target_powerpc<size, big_endian>* targ,
-			   Reloc_section* brlt_rel)
+  Output_data_brlt_powerpc(Target_powerpc<size, big_endian>* targ)
     : Output_section_data_build(size == 32 ? 4 : 8),
-      rel_(brlt_rel),
       targ_(targ)
   { }
 
-  void
-  reset_brlt_sizes()
-  {
-    this->reset_data_size();
-    this->rel_->reset_data_size();
-  }
-
-  void
-  finalize_brlt_sizes()
-  {
-    this->finalize_data_size();
-    this->rel_->finalize_data_size();
-  }
-
-  // Add a reloc for an entry in the BRLT.
-  void
-  add_reloc(Address to, unsigned int off)
-  { this->rel_->add_relative(elfcpp::R_POWERPC_RELATIVE, this, off, to); }
-
-  // Update section and reloc section size.
-  void
-  set_current_size(unsigned int num_branches)
-  {
-    this->reset_address_and_file_offset();
-    this->set_current_data_size(num_branches * 16);
-    this->finalize_data_size();
-    Output_section* os = this->output_section();
-    os->set_section_offsets_need_adjustment();
-    if (this->rel_ != NULL)
-      {
-	const unsigned int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
-	this->rel_->reset_address_and_file_offset();
-	this->rel_->set_current_data_size(num_branches * reloc_size);
-	this->rel_->finalize_data_size();
-	Output_section* os = this->rel_->output_section();
-	os->set_section_offsets_need_adjustment();
-      }
-  }
-
  protected:
   void
   do_adjust_output_section(Output_section* os)
@@ -4617,8 +4605,6 @@ class Output_data_brlt_powerpc : public Output_section_data_build
   void
   do_write(Output_file*);
 
-  // The reloc section.
-  Reloc_section* rel_;
   Target_powerpc<size, big_endian>* targ_;
 };
 
@@ -4630,24 +4616,15 @@ Target_powerpc<size, big_endian>::make_brlt_section(Layout* layout)
 {
   if (size == 64 && this->brlt_section_ == NULL)
     {
-      Reloc_section* brlt_rel = NULL;
       bool is_pic = parameters->options().output_is_position_independent();
       if (is_pic)
 	{
 	  // When PIC we can't fill in .branch_lt but must initialise at
 	  // runtime via dynamic relocations.
 	  this->rela_dyn_section(layout);
-	  // FIXME: This reloc section won't have its relative relocs
-	  // sorted properly among the other relative relocs in rela_dyn_
-	  // but it must be a separate section due to needing to call
-	  // reset_data_size().
-	  brlt_rel = new Reloc_section(false);
-	  if (this->rela_dyn_->output_section())
-	    this->rela_dyn_->output_section()
-	      ->add_output_section_data(brlt_rel);
 	}
       this->brlt_section_
-	= new Output_data_brlt_powerpc<size, big_endian>(this, brlt_rel);
+	= new Output_data_brlt_powerpc<size, big_endian>(this);
       if (this->plt_ && is_pic && this->plt_->output_section())
 	this->plt_->output_section()
 	  ->add_output_section_data(this->brlt_section_);

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-06-23 11:40 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-23 11:39 [GOLD] Support setting DT_RELACOUNT late Alan Modra
2023-06-23 11:40 ` [GOLD] PowerPC64 huge branch dynamic relocs Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).