PR30794, PowerPC gold: internal error in add_output_section_to_load

Caused by commit 5a97377e55, specifically this code added to
Target_powerpc::do_relax
+      if (parameters->options().output_is_position_independent())
+       this->rela_dyn_size_
+         = this->rela_dyn_section(layout)->current_data_size();

The problem here is that if .rela.dyn isn't already created then the
call to rela_dyn_section creates it, and as this comment in
Target_powerpc::do_finalize_sections says:
	  // Annoyingly, we need to make these sections now whether or
	  // not we need them.  If we delay until do_relax then we
	  // need to mess with the relaxation machinery checkpointing.
We can't be creating sections in do_relax.

	PR 30794
	* powerpc.cc (Target_powerpc::do_relax): Only set rela_dyn_size_
	for size == 64, and assert that rela_dyn_ already exists.
	Tidy code setting plt_thread_safe, which also only needs to be
	set when size == 64 for ELFv1.
This commit is contained in:
Alan Modra 2023-08-25 09:12:18 +09:30
parent cbbeee21a2
commit d537f77ef3

View file

@ -3714,12 +3714,7 @@ Target_powerpc<size, big_endian>::do_relax(int pass,
unsigned int prev_brlt_size = 0;
if (pass == 1)
{
bool thread_safe
= this->abiversion() < 2 && parameters->options().plt_thread_safe();
if (size == 64
&& this->abiversion() < 2
&& !thread_safe
&& !parameters->options().user_set_plt_thread_safe())
if (size == 64 && this->abiversion() < 2)
{
static const char* const thread_starter[] =
{
@ -3747,29 +3742,37 @@ Target_powerpc<size, big_endian>::do_relax(int pass,
/* libgo */
"__go_go",
};
bool thread_safe = parameters->options().plt_thread_safe();
if (parameters->options().shared())
thread_safe = true;
else
if (!thread_safe
&& !parameters->options().user_set_plt_thread_safe())
{
for (unsigned int i = 0;
i < sizeof(thread_starter) / sizeof(thread_starter[0]);
i++)
if (parameters->options().shared())
thread_safe = true;
else
{
Symbol* sym = symtab->lookup(thread_starter[i], NULL);
thread_safe = (sym != NULL
&& sym->in_reg()
&& sym->in_real_elf());
if (thread_safe)
break;
for (unsigned int i = 0;
i < sizeof(thread_starter) / sizeof(thread_starter[0]);
i++)
{
Symbol* sym = symtab->lookup(thread_starter[i], NULL);
thread_safe = (sym != NULL
&& sym->in_reg()
&& sym->in_real_elf());
if (thread_safe)
break;
}
}
}
this->plt_thread_safe_ = thread_safe;
}
this->plt_thread_safe_ = thread_safe;
if (parameters->options().output_is_position_independent())
this->rela_dyn_size_
= this->rela_dyn_section(layout)->current_data_size();
if (size == 64
&& parameters->options().output_is_position_independent())
{
gold_assert (this->rela_dyn_);
this->rela_dyn_size_ = this->rela_dyn_->current_data_size();
}
this->stub_group_size_ = parameters->options().stub_group_size();
bool no_size_errors = true;