From 5cdb4f14426a99ec8fcba843fa503efdc55fa078 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 26 Aug 2021 12:17:51 +0930 Subject: [PATCH] [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. --- gold/powerpc.cc | 148 ++++++++++++++++++++++++------------------------ 1 file 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::add_global(gsym, got_type); + return Output_data_got::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::add_global_plt(gsym, got_type); + return Output_data_got::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:: - 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:: - 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::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::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:: - 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::Scan::local( Output_data_got_powerpc* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym(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::Scan::local( Output_data_got_powerpc* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym(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::Scan::local( Output_data_got_powerpc* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym(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::Scan::local( if (tls_type == tls::TLSOPT_NONE) { unsigned int r_sym = elfcpp::elf_r_sym(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* 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::Scan::global( { // The symbol requires a GOT entry. Output_data_got_powerpc* 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::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::Scan::global( Output_data_got_powerpc* 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::Scan::global( Output_data_got_powerpc* 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::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::Scan::global( { Output_data_got_powerpc* 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::Scan::global( Output_data_got_powerpc* 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::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::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::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::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::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 -- 2.30.2