[GOLD] Support setting DT_RELACOUNT late
authorAlan Modra <amodra@gmail.com>
Fri, 23 Jun 2023 00:08:13 +0000 (09:38 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 23 Jun 2023 11:32:48 +0000 (21:02 +0930)
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.

gold/aarch64.cc
gold/arm.cc
gold/i386.cc
gold/layout.cc
gold/layout.h
gold/mips.cc
gold/powerpc.cc
gold/s390.cc
gold/sparc.cc
gold/tilegx.cc
gold/x86_64.cc

index 46a278bd466bf14dc8f3700963a5882844b7b5c6..7f95c0cf13b059512773a19046825fb41bd5c506 100644 (file)
@@ -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.
index 1ab8eb5db7246c66a321c027d5cde9cfe6f368af..f787c28e0a781830dcb6b3b22265f8a7e1284914 100644 (file)
@@ -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.
index d97e818ba0dda64b48ced65700f1d9691fedd75e..c4ea8798a98728033ca1eced95cca558f387982c 100644 (file)
@@ -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.
index a50086897bbb000b1dc4c7634cf98e60a0f98aad..b94855f86629196460afafe2002a61197a3d413e 100644 (file)
@@ -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);
+           }
        }
     }
 
index 5bb9aff5b0412dc3b73b3c51412b4c84c7c76a17..040c98cd9aaf5aee704fe143975daf43c0d147c0 100644 (file)
@@ -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
index bd7353b450e2d9639c995ac784803412d0719b82..a6a41d7a5e49ce964cb82f01e8bf3d13388f4f7a 100644 (file)
@@ -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
index 0c15e1b37212619c0ff87da2eda9d86207a87869..5838b49e3418ae2f973cc51aa6be12dbd1fcf107 100644 (file)
@@ -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.
 
index 9e555c9d6c59464208960e5040d5a6a5e8d62534..6e53735351e40763a0b9080edceaf68015f87fb1 100644 (file)
@@ -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;
 
index 61904f91a41d784ea39021762aadf42686d48762..42c4a3232b1fe55e7ad2ce97a6e9fea0e5fdc0d3 100644 (file)
@@ -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.
index 69d4e640a1e6b2e6ece57492d5c42ac4f1af0d55..a054b6701e4f6f0b102b6f07c8aeddcdb16b3e73 100644 (file)
@@ -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.
index 6cace049f66eb23f38f427cdc515d359ce4bd48b..928dfa8ea34cd2fd86486a268bf3844e1874e2ed 100644 (file)
@@ -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();