From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1062) id 57A2A3858C50; Fri, 23 Jun 2023 11:41:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 57A2A3858C50 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Alan Modra To: bfd-cvs@sourceware.org Subject: [binutils-gdb] [GOLD] PowerPC64 huge branch dynamic relocs X-Act-Checkin: binutils-gdb X-Git-Author: Alan Modra X-Git-Refname: refs/heads/master X-Git-Oldrev: bdad2ad579f7e7a6307f61e67ef70315506a26f6 X-Git-Newrev: 5a97377e55134b585a4f92569e9b6bf958af8daf Message-Id: <20230623114103.57A2A3858C50@sourceware.org> Date: Fri, 23 Jun 2023 11:41:03 +0000 (GMT) X-BeenThere: binutils-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Jun 2023 11:41:03 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D5a97377e5513= 4b585a4f92569e9b6bf958af8daf commit 5a97377e55134b585a4f92569e9b6bf958af8daf Author: Alan Modra Date: Fri Jun 23 10:37:53 2023 +0930 [GOLD] PowerPC64 huge branch dynamic relocs =20 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. =20 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. =20 * 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: --- gold/powerpc.cc | 99 ++++++++++++++++++++++-------------------------------= ---- 1 file changed, 38 insertions(+), 61 deletions(-) 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 Branches branch_info_; Tocsave_loc tocsave_loc_; =20 + off_t rela_dyn_size_; + bool power10_relocs_; bool plt_thread_safe_; bool plt_localentry0_; @@ -3687,6 +3689,18 @@ Target_powerpc::Branch_info::make_= stub( return ok; } =20 +// 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. =20 template @@ -3752,10 +3766,11 @@ Target_powerpc::do_relax(int pass, } } this->plt_thread_safe_ =3D thread_safe; - } =20 - if (pass =3D=3D 1) - { + if (parameters->options().output_is_position_independent()) + this->rela_dyn_size_ + =3D this->rela_dyn_section(layout)->current_data_size(); + this->stub_group_size_ =3D parameters->options().stub_group_size(); bool no_size_errors =3D true; if (this->stub_group_size_ =3D=3D 1) @@ -3868,7 +3883,15 @@ Target_powerpc::do_relax(int pass, if (size =3D=3D 64 && num_huge_branches !=3D 0) this->make_brlt_section(layout); if (size =3D=3D 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 =3D elfcpp::Elf_sizes::rela_size; + off_t cur =3D this->rela_dyn_size_ + num_huge_branches * reloc_size; + update_current_size(this->rela_dyn_, cur); + } + } =20 for (typename Stub_tables::reverse_iterator p =3D this->stub_tables_.rbe= gin(); p !=3D this->stub_tables_.rend(); @@ -3937,15 +3960,21 @@ Target_powerpc::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 =3D this->branch_lookup_table_.begin(); p !=3D 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 =3D elfcpp::Elf_sizes::rela_size; + gold_assert(this->rela_dyn_->data_size() + =3D=3D this->rela_dyn_size_ + num_huge_branches * reloc_size); } =20 if (!again @@ -4554,52 +4583,11 @@ class Output_data_brlt_powerpc : public Output_sect= ion_data_build typedef Output_data_reloc Reloc_section; =20 - Output_data_brlt_powerpc(Target_powerpc* targ, - Reloc_section* brlt_rel) + Output_data_brlt_powerpc(Target_powerpc* targ) : Output_section_data_build(size =3D=3D 32 ? 4 : 8), - rel_(brlt_rel), targ_(targ) { } =20 - 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 =3D this->output_section(); - os->set_section_offsets_need_adjustment(); - if (this->rel_ !=3D NULL) - { - const unsigned int reloc_size =3D elfcpp::Elf_sizes::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 =3D 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_sectio= n_data_build void do_write(Output_file*); =20 - // The reloc section. - Reloc_section* rel_; Target_powerpc* targ_; }; =20 @@ -4630,24 +4616,15 @@ Target_powerpc::make_brlt_section= (Layout* layout) { if (size =3D=3D 64 && this->brlt_section_ =3D=3D NULL) { - Reloc_section* brlt_rel =3D NULL; bool is_pic =3D 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 =3D new Reloc_section(false); - if (this->rela_dyn_->output_section()) - this->rela_dyn_->output_section() - ->add_output_section_data(brlt_rel); } this->brlt_section_ - =3D new Output_data_brlt_powerpc(this, brlt_rel); + =3D new Output_data_brlt_powerpc(this); if (this->plt_ && is_pic && this->plt_->output_section()) this->plt_->output_section() ->add_output_section_data(this->brlt_section_);