* [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).