Branches branch_info_;
Tocsave_loc tocsave_loc_;
+ off_t rela_dyn_size_;
+
bool power10_relocs_;
bool plt_thread_safe_;
bool plt_localentry0_;
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>
}
}
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)
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();
&& 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
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)
void
do_write(Output_file*);
- // The reloc section.
- Reloc_section* rel_;
Target_powerpc<size, big_endian>* targ_;
};
{
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_);