summaryrefslogtreecommitdiff
path: root/gold/powerpc.cc
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-08-26 12:17:51 +0930
committerAlan Modra <amodra@gmail.com>2021-09-18 08:20:11 +0930
commit5cdb4f14426a99ec8fcba843fa503efdc55fa078 (patch)
treea3f47ff28cc2d40165b4f61a2e06cebe919990b1 /gold/powerpc.cc
parente4d49a0f908415edb7a7e718ef2008a96dd43f9b (diff)
downloadbinutils-gdb-5cdb4f14426a99ec8fcba843fa503efdc55fa078.tar.gz
[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.
Diffstat (limited to 'gold/powerpc.cc')
-rw-r--r--gold/powerpc.cc148
1 files changed, 74 insertions, 74 deletions
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 0b6405915c2..0cee975f8bd 100644
--- a/gold/powerpc.cc
+++ b/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