[GOLD] PowerPC64 support for sym+addend GOT entries

Pass addends to all the GOT handling functions, plus remove some
extraneous asserts.

	PR 28192
	* powerpc.cc (Output_data_got_powerpc): Add addend parameter to
	all methods creating got entries.
	(Target_powerpc::Scan::local): Pass reloc addend to got handling
	functions, and when creating dynamic got relocations.
	(Target_powerpc::Scan::global): Likewise.
	(Target_powerpc::Relocate::relocate): Likewise.  Remove extraneous
	assertions.
This commit is contained in:
Alan Modra 2021-08-26 12:17:51 +09:30
parent e4d49a0f90
commit 5cdb4f1442

View File

@ -2970,77 +2970,85 @@ public:
// Override all the Output_data_got methods we use so as to first call
// reserve_ent().
bool
add_global(Symbol* gsym, unsigned int got_type)
add_global(Symbol* gsym, unsigned int got_type, uint64_t addend)
{
this->reserve_ent();
return Output_data_got<size, big_endian>::add_global(gsym, got_type);
return Output_data_got<size, big_endian>::add_global(gsym, got_type,
addend);
}
bool
add_global_plt(Symbol* gsym, unsigned int got_type)
add_global_plt(Symbol* gsym, unsigned int got_type, uint64_t addend)
{
this->reserve_ent();
return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type);
return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type,
addend);
}
bool
add_global_tls(Symbol* gsym, unsigned int got_type)
{ return this->add_global_plt(gsym, got_type); }
add_global_tls(Symbol* gsym, unsigned int got_type, uint64_t addend)
{ return this->add_global_plt(gsym, got_type, addend); }
void
add_global_with_rel(Symbol* gsym, unsigned int got_type,
Output_data_reloc_generic* rel_dyn, unsigned int r_type)
Output_data_reloc_generic* rel_dyn,
unsigned int r_type, uint64_t addend)
{
this->reserve_ent();
Output_data_got<size, big_endian>::
add_global_with_rel(gsym, got_type, rel_dyn, r_type);
add_global_with_rel(gsym, got_type, rel_dyn, r_type, addend);
}
void
add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1, unsigned int r_type_2)
unsigned int r_type_1, unsigned int r_type_2,
uint64_t addend)
{
if (gsym->has_got_offset(got_type))
return;
this->reserve_ent(2);
Output_data_got<size, big_endian>::
add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2);
add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2,
addend);
}
bool
add_local(Relobj* object, unsigned int sym_index, unsigned int got_type)
add_local(Relobj* object, unsigned int sym_index, unsigned int got_type,
uint64_t addend)
{
this->reserve_ent();
return Output_data_got<size, big_endian>::add_local(object, sym_index,
got_type);
got_type, addend);
}
bool
add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type)
add_local_plt(Relobj* object, unsigned int sym_index,
unsigned int got_type, uint64_t addend)
{
this->reserve_ent();
return Output_data_got<size, big_endian>::add_local_plt(object, sym_index,
got_type);
got_type, addend);
}
bool
add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type)
{ return this->add_local_plt(object, sym_index, got_type); }
add_local_tls(Relobj* object, unsigned int sym_index,
unsigned int got_type, uint64_t addend)
{ return this->add_local_plt(object, sym_index, got_type, addend); }
void
add_local_tls_pair(Relobj* object, unsigned int sym_index,
unsigned int got_type,
Output_data_reloc_generic* rel_dyn,
unsigned int r_type)
unsigned int r_type, uint64_t addend)
{
if (object->local_has_got_offset(sym_index, got_type))
if (object->local_has_got_offset(sym_index, got_type, addend))
return;
this->reserve_ent(2);
Output_data_got<size, big_endian>::
add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type);
add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type, addend);
}
unsigned int
@ -8195,29 +8203,30 @@ Target_powerpc<size, big_endian>::Scan::local(
Output_data_got_powerpc<size, big_endian>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
if (!parameters->options().output_is_position_independent())
{
if (is_ifunc
&& (size == 32 || target->abiversion() >= 2))
got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD, addend);
else
got->add_local(object, r_sym, GOT_TYPE_STANDARD);
got->add_local(object, r_sym, GOT_TYPE_STANDARD, addend);
}
else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD))
else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD, addend))
{
// If we are generating a shared object or a pie, this
// symbol's GOT entry will be set by a dynamic relocation.
unsigned int off;
off = got->add_constant(0);
object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off, addend);
Reloc_section* rela_dyn = target->rela_dyn_section(symtab, layout,
is_ifunc);
unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE
: elfcpp::R_POWERPC_RELATIVE);
rela_dyn->add_local_relative(object, r_sym, dynrel,
got, off, 0, false);
got, off, addend, false);
}
}
break;
@ -8246,9 +8255,11 @@ Target_powerpc<size, big_endian>::Scan::local(
Output_data_got_powerpc<size, big_endian>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
got->add_local_tls_pair(object, r_sym, GOT_TYPE_TLSGD,
rela_dyn, elfcpp::R_POWERPC_DTPMOD);
rela_dyn, elfcpp::R_POWERPC_DTPMOD,
addend);
}
else if (tls_type == tls::TLSOPT_TO_LE)
{
@ -8296,7 +8307,8 @@ Target_powerpc<size, big_endian>::Scan::local(
Output_data_got_powerpc<size, big_endian>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL);
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL, addend);
}
break;
@ -8310,17 +8322,18 @@ Target_powerpc<size, big_endian>::Scan::local(
if (tls_type == tls::TLSOPT_NONE)
{
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL))
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL, addend))
{
Output_data_got_powerpc<size, big_endian>* got
= target->got_section(symtab, layout);
unsigned int off = got->add_constant(0);
object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off);
object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off, addend);
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
rela_dyn->add_symbolless_local_addend(object, r_sym,
elfcpp::R_POWERPC_TPREL,
got, off, 0);
got, off, addend);
}
}
else if (tls_type == tls::TLSOPT_TO_LE)
@ -8980,22 +8993,23 @@ Target_powerpc<size, big_endian>::Scan::global(
{
// The symbol requires a GOT entry.
Output_data_got_powerpc<size, big_endian>* got;
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
got = target->got_section(symtab, layout);
if (gsym->final_value_is_known())
{
if (is_ifunc
&& (size == 32 || target->abiversion() >= 2))
got->add_global_plt(gsym, GOT_TYPE_STANDARD);
got->add_global_plt(gsym, GOT_TYPE_STANDARD, addend);
else
got->add_global(gsym, GOT_TYPE_STANDARD);
got->add_global(gsym, GOT_TYPE_STANDARD, addend);
}
else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
else if (!gsym->has_got_offset(GOT_TYPE_STANDARD, addend))
{
// If we are generating a shared object or a pie, this
// symbol's GOT entry will be set by a dynamic relocation.
unsigned int off = got->add_constant(0);
gsym->set_got_offset(GOT_TYPE_STANDARD, off);
gsym->set_got_offset(GOT_TYPE_STANDARD, off, addend);
Reloc_section* rela_dyn
= target->rela_dyn_section(symtab, layout, is_ifunc);
@ -9008,12 +9022,13 @@ Target_powerpc<size, big_endian>::Scan::global(
{
unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE
: elfcpp::R_POWERPC_RELATIVE);
rela_dyn->add_global_relative(gsym, dynrel, got, off, 0, false);
rela_dyn->add_global_relative(gsym, dynrel, got, off,
addend, false);
}
else
{
unsigned int dynrel = elfcpp::R_POWERPC_GLOB_DAT;
rela_dyn->add_global(gsym, dynrel, got, off, 0);
rela_dyn->add_global(gsym, dynrel, got, off, addend);
}
}
}
@ -9046,9 +9061,11 @@ Target_powerpc<size, big_endian>::Scan::global(
Output_data_got_powerpc<size, big_endian>* got
= target->got_section(symtab, layout);
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLSGD, rela_dyn,
elfcpp::R_POWERPC_DTPMOD,
elfcpp::R_POWERPC_DTPREL);
elfcpp::R_POWERPC_DTPREL,
addend);
}
else if (tls_type == tls::TLSOPT_TO_IE)
{
@ -9057,11 +9074,12 @@ Target_powerpc<size, big_endian>::Scan::global(
Output_data_got_powerpc<size, big_endian>* got
= target->got_section(symtab, layout);
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
if (gsym->is_undefined()
|| gsym->is_from_dynobj())
{
got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn,
elfcpp::R_POWERPC_TPREL);
elfcpp::R_POWERPC_TPREL, addend);
}
else
{
@ -9069,7 +9087,7 @@ Target_powerpc<size, big_endian>::Scan::global(
gsym->set_got_offset(GOT_TYPE_TPREL, off);
unsigned int dynrel = elfcpp::R_POWERPC_TPREL;
rela_dyn->add_symbolless_global_addend(gsym, dynrel,
got, off, 0);
got, off, addend);
}
}
ppc_object->set_tls_marker();
@ -9119,15 +9137,16 @@ Target_powerpc<size, big_endian>::Scan::global(
{
Output_data_got_powerpc<size, big_endian>* got
= target->got_section(symtab, layout);
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
if (!gsym->final_value_is_known()
&& (gsym->is_from_dynobj()
|| gsym->is_undefined()
|| gsym->is_preemptible()))
got->add_global_with_rel(gsym, GOT_TYPE_DTPREL,
target->rela_dyn_section(layout),
elfcpp::R_POWERPC_DTPREL);
elfcpp::R_POWERPC_DTPREL, addend);
else
got->add_global_tls(gsym, GOT_TYPE_DTPREL);
got->add_global_tls(gsym, GOT_TYPE_DTPREL, addend);
}
break;
@ -9146,11 +9165,12 @@ Target_powerpc<size, big_endian>::Scan::global(
Output_data_got_powerpc<size, big_endian>* got
= target->got_section(symtab, layout);
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
if (gsym->is_undefined()
|| gsym->is_from_dynobj())
{
got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn,
elfcpp::R_POWERPC_TPREL);
elfcpp::R_POWERPC_TPREL, addend);
}
else
{
@ -9158,7 +9178,7 @@ Target_powerpc<size, big_endian>::Scan::global(
gsym->set_got_offset(GOT_TYPE_TPREL, off);
unsigned int dynrel = elfcpp::R_POWERPC_TPREL;
rela_dyn->add_symbolless_global_addend(gsym, dynrel,
got, off, 0);
got, off, addend);
}
}
}
@ -10655,16 +10675,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
}
else if (is_got_reloc(r_type))
{
uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
value = gsym->got_offset(GOT_TYPE_STANDARD);
}
value = gsym->got_offset(GOT_TYPE_STANDARD, addend);
else
{
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
}
value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD, addend);
if (r_type == elfcpp::R_PPC64_GOT_PCREL34)
value += target->got_section()->address();
else
@ -10764,16 +10779,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
got_type = GOT_TYPE_TPREL;
if (got_type != GOT_TYPE_STANDARD)
{
uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(got_type));
value = gsym->got_offset(got_type);
}
value = gsym->got_offset(got_type, addend);
else
{
gold_assert(object->local_has_got_offset(r_sym, got_type));
value = object->local_got_offset(r_sym, got_type);
}
value = object->local_got_offset(r_sym, got_type, addend);
if (r_type == elfcpp::R_PPC64_GOT_TLSGD_PCREL34)
value += target->got_section()->address();
else
@ -10920,16 +10930,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
{
// Accesses relative to a local dynamic sequence address,
// no optimisation here.
uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(GOT_TYPE_DTPREL));
value = gsym->got_offset(GOT_TYPE_DTPREL);
}
value = gsym->got_offset(GOT_TYPE_DTPREL, addend);
else
{
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_DTPREL));
value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL);
}
value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL, addend);
if (r_type == elfcpp::R_PPC64_GOT_DTPREL_PCREL34)
value += target->got_section()->address();
else
@ -10946,16 +10951,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
if (tls_type == tls::TLSOPT_NONE)
{
uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(GOT_TYPE_TPREL));
value = gsym->got_offset(GOT_TYPE_TPREL);
}
value = gsym->got_offset(GOT_TYPE_TPREL, addend);
else
{
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_TPREL));
value = object->local_got_offset(r_sym, GOT_TYPE_TPREL);
}
value = object->local_got_offset(r_sym, GOT_TYPE_TPREL, addend);
if (r_type == elfcpp::R_PPC64_GOT_TPREL_PCREL34)
value += target->got_section()->address();
else