[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:
parent
e4d49a0f90
commit
5cdb4f1442
148
gold/powerpc.cc
148
gold/powerpc.cc
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user