diff --git a/gold/ChangeLog b/gold/ChangeLog index e6c0d92db6..82dae337bb 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,16 @@ +2021-03-30 Alan Modra + + PR gold/27625 + * powerpc.cc (Powerpc_relobj): Add no_tls_marker_, tls_marker_, + and tls_opt_error_ variables and accessors. + (Target_powerpc::Scan::local, global): Call set_tls_marker and + set_no_tls_marker for GD and LD code sequence relocations. + (Target_powerpc::Relocate::relocate): Downgrade the "lacks marker + reloc" error to a warning when safe to do so, and omit the error + entirely if not optimising TLS sequences. Do not optimise GD and + LD sequences for objects lacking marker relocs. + (Target_powerpc::relocate_relocs): Heed no_tls_marker here too. + 2021-03-19 Cary Coutant PR gold/27615 diff --git a/gold/powerpc.cc b/gold/powerpc.cc index ec6f950eb2..6b12ed8869 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -101,6 +101,7 @@ public: : Sized_relobj_file(name, input_file, offset, ehdr), uniq_(object_id++), special_(0), relatoc_(0), toc_(0), has_small_toc_reloc_(false), opd_valid_(false), + no_tls_marker_(false), tls_marker_(false), tls_opt_error_(false), e_flags_(ehdr.get_e_flags()), no_toc_opt_(), opd_ent_(), access_from_map_(), has14_(), stub_table_index_(), st_other_(), attributes_section_data_(NULL) @@ -161,6 +162,30 @@ public: return this->no_toc_opt_[off]; } + void + set_no_tls_marker() + { + if (!this->no_tls_marker_ && this->tls_marker_) + this->tls_opt_error_ = true; + this->no_tls_marker_ = true; + } + + bool + no_tls_marker() const + { return this->no_tls_marker_; } + + void + set_tls_marker() + { this->tls_marker_ = true; } + + bool + tls_marker() const + { return this->tls_marker_; } + + bool + tls_opt_error() const + { return this->tls_opt_error_; } + // The .got2 section shndx. unsigned int got2_shndx() const @@ -454,6 +479,19 @@ private: // access_from_map_. bool opd_valid_; + // Set when finding a __tls_get_addr call without marker relocs. + // Such a call disables GD and LD tls optimisations for the object file. + bool no_tls_marker_; + + // Set when finding a __tls_get_addr call with marker relocs, or + // when finding a relocation that needs __tls_get_addr calls with + // marker relocs. + bool tls_marker_; + + // Set when seeing a __tls_get_addr call without marker relocs after + // seeing some __tls_get_addr calls with marker relocs. + bool tls_opt_error_; + // Header e_flags elfcpp::Elf_Word e_flags_; @@ -7863,28 +7901,47 @@ Target_powerpc::Scan::local( const elfcpp::Sym& lsym, bool is_discarded) { - this->maybe_skip_tls_get_addr_call(target, r_type, NULL); + Powerpc_relobj* ppc_object + = static_cast*>(object); + + switch (this->maybe_skip_tls_get_addr_call(target, r_type, NULL)) + { + case Track_tls::NOT_EXPECTED: + ppc_object->set_no_tls_marker(); + break; + default: + break; + } if ((size == 64 && r_type == elfcpp::R_PPC64_TLSGD) || (size == 32 && r_type == elfcpp::R_PPC_TLSGD)) { this->expect_tls_get_addr_call(); - const tls::Tls_optimization tls_type = target->optimize_tls_gd(true); - if (tls_type != tls::TLSOPT_NONE) - this->skip_next_tls_get_addr_call(); + if (!ppc_object->no_tls_marker()) + { + tls::Tls_optimization tls_type = target->optimize_tls_gd(true); + if (tls_type != tls::TLSOPT_NONE) + { + this->skip_next_tls_get_addr_call(); + ppc_object->set_tls_marker(); + } + } } else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSLD) || (size == 32 && r_type == elfcpp::R_PPC_TLSLD)) { this->expect_tls_get_addr_call(); - const tls::Tls_optimization tls_type = target->optimize_tls_ld(); - if (tls_type != tls::TLSOPT_NONE) - this->skip_next_tls_get_addr_call(); + if (!ppc_object->no_tls_marker()) + { + tls::Tls_optimization tls_type = target->optimize_tls_ld(); + if (tls_type != tls::TLSOPT_NONE) + { + this->skip_next_tls_get_addr_call(); + ppc_object->set_tls_marker(); + } + } } - Powerpc_relobj* ppc_object - = static_cast*>(object); - if (is_discarded) { if (size == 64 @@ -8179,7 +8236,9 @@ Target_powerpc::Scan::local( case elfcpp::R_POWERPC_GOT_TLSGD16_HI: case elfcpp::R_POWERPC_GOT_TLSGD16_HA: { - const tls::Tls_optimization tls_type = target->optimize_tls_gd(true); + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!ppc_object->no_tls_marker()) + tls_type = target->optimize_tls_gd(true); if (tls_type == tls::TLSOPT_NONE) { Output_data_got_powerpc* got @@ -8192,6 +8251,7 @@ Target_powerpc::Scan::local( else if (tls_type == tls::TLSOPT_TO_LE) { // no GOT relocs needed for Local Exec. + ppc_object->set_tls_marker(); } else gold_unreachable(); @@ -8204,7 +8264,9 @@ Target_powerpc::Scan::local( case elfcpp::R_POWERPC_GOT_TLSLD16_HI: case elfcpp::R_POWERPC_GOT_TLSLD16_HA: { - const tls::Tls_optimization tls_type = target->optimize_tls_ld(); + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!ppc_object->no_tls_marker()) + tls_type = target->optimize_tls_ld(); if (tls_type == tls::TLSOPT_NONE) target->tlsld_got_offset(symtab, layout, object); else if (tls_type == tls::TLSOPT_TO_LE) @@ -8216,6 +8278,7 @@ Target_powerpc::Scan::local( gold_assert(os != NULL); os->set_needs_symtab_index(); } + ppc_object->set_tls_marker(); } else gold_unreachable(); @@ -8241,7 +8304,7 @@ Target_powerpc::Scan::local( case elfcpp::R_POWERPC_GOT_TPREL16_HI: case elfcpp::R_POWERPC_GOT_TPREL16_HA: { - const tls::Tls_optimization tls_type = target->optimize_tls_ie(true); + tls::Tls_optimization tls_type = target->optimize_tls_ie(true); if (tls_type == tls::TLSOPT_NONE) { unsigned int r_sym = elfcpp::elf_r_sym(reloc.get_r_info()); @@ -8545,9 +8608,19 @@ Target_powerpc::Scan::global( unsigned int r_type, Symbol* gsym) { - if (this->maybe_skip_tls_get_addr_call(target, r_type, gsym) - == Track_tls::SKIP) - return; + Powerpc_relobj* ppc_object + = static_cast*>(object); + + switch (this->maybe_skip_tls_get_addr_call(target, r_type, gsym)) + { + case Track_tls::NOT_EXPECTED: + ppc_object->set_no_tls_marker(); + break; + case Track_tls::SKIP: + return; + default: + break; + } if (target->replace_tls_get_addr(gsym)) // Change a __tls_get_addr reference to __tls_get_addr_opt @@ -8558,23 +8631,32 @@ Target_powerpc::Scan::global( || (size == 32 && r_type == elfcpp::R_PPC_TLSGD)) { this->expect_tls_get_addr_call(); - const bool final = gsym->final_value_is_known(); - const tls::Tls_optimization tls_type = target->optimize_tls_gd(final); - if (tls_type != tls::TLSOPT_NONE) - this->skip_next_tls_get_addr_call(); + if (!ppc_object->no_tls_marker()) + { + bool final = gsym->final_value_is_known(); + tls::Tls_optimization tls_type = target->optimize_tls_gd(final); + if (tls_type != tls::TLSOPT_NONE) + { + this->skip_next_tls_get_addr_call(); + ppc_object->set_tls_marker(); + } + } } else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSLD) || (size == 32 && r_type == elfcpp::R_PPC_TLSLD)) { this->expect_tls_get_addr_call(); - const tls::Tls_optimization tls_type = target->optimize_tls_ld(); - if (tls_type != tls::TLSOPT_NONE) - this->skip_next_tls_get_addr_call(); + if (!ppc_object->no_tls_marker()) + { + tls::Tls_optimization tls_type = target->optimize_tls_ld(); + if (tls_type != tls::TLSOPT_NONE) + { + this->skip_next_tls_get_addr_call(); + ppc_object->set_tls_marker(); + } + } } - Powerpc_relobj* ppc_object - = static_cast*>(object); - // A STT_GNU_IFUNC symbol may require a PLT entry. bool is_ifunc = gsym->type() == elfcpp::STT_GNU_IFUNC; bool pushed_ifunc = false; @@ -8951,8 +9033,12 @@ Target_powerpc::Scan::global( case elfcpp::R_POWERPC_GOT_TLSGD16_HI: case elfcpp::R_POWERPC_GOT_TLSGD16_HA: { - const bool final = gsym->final_value_is_known(); - const tls::Tls_optimization tls_type = target->optimize_tls_gd(final); + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!ppc_object->no_tls_marker()) + { + bool final = gsym->final_value_is_known(); + tls_type = target->optimize_tls_gd(final); + } if (tls_type == tls::TLSOPT_NONE) { Output_data_got_powerpc* got @@ -8984,10 +9070,12 @@ Target_powerpc::Scan::global( got, off, 0); } } + ppc_object->set_tls_marker(); } else if (tls_type == tls::TLSOPT_TO_LE) { // no GOT relocs needed for Local Exec. + ppc_object->set_tls_marker(); } else gold_unreachable(); @@ -9000,7 +9088,9 @@ Target_powerpc::Scan::global( case elfcpp::R_POWERPC_GOT_TLSLD16_HI: case elfcpp::R_POWERPC_GOT_TLSLD16_HA: { - const tls::Tls_optimization tls_type = target->optimize_tls_ld(); + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!ppc_object->no_tls_marker()) + tls_type = target->optimize_tls_ld(); if (tls_type == tls::TLSOPT_NONE) target->tlsld_got_offset(symtab, layout, object); else if (tls_type == tls::TLSOPT_TO_LE) @@ -9012,6 +9102,7 @@ Target_powerpc::Scan::global( gold_assert(os != NULL); os->set_needs_symtab_index(); } + ppc_object->set_tls_marker(); } else gold_unreachable(); @@ -9044,8 +9135,8 @@ Target_powerpc::Scan::global( case elfcpp::R_POWERPC_GOT_TPREL16_HI: case elfcpp::R_POWERPC_GOT_TPREL16_HA: { - const bool final = gsym->final_value_is_known(); - const tls::Tls_optimization tls_type = target->optimize_tls_ie(final); + bool final = gsym->final_value_is_known(); + tls::Tls_optimization tls_type = target->optimize_tls_ie(final); if (tls_type == tls::TLSOPT_NONE) { if (!gsym->has_got_offset(GOT_TYPE_TPREL)) @@ -10357,11 +10448,25 @@ Target_powerpc::Relocate::relocate( const elfcpp::Rela rela(preloc); unsigned int r_type = elfcpp::elf_r_type(rela.get_r_info()); + Powerpc_relobj* const object + = static_cast*>(relinfo->object); switch (this->maybe_skip_tls_get_addr_call(target, r_type, gsym)) { case Track_tls::NOT_EXPECTED: - gold_error_at_location(relinfo, relnum, rela.get_r_offset(), - _("__tls_get_addr call lacks marker reloc")); + if (!parameters->options().shared() + && parameters->options().tls_optimize()) + { + // It is a hard error to see a __tls_get_addr call without + // marker relocs after seeing calls with marker relocs in the + // same object file, because dynamic relocation accounting + // will be wrong. + if (object->tls_opt_error()) + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("__tls_get_addr call lacks marker reloc")); + else + gold_warning_at_location(relinfo, relnum, rela.get_r_offset(), + _("__tls_get_addr call lacks marker reloc")); + } break; case Track_tls::EXPECTED: // We have already complained. @@ -10394,8 +10499,6 @@ Target_powerpc::Relocate::relocate( // Offset from start of insn to d-field reloc. const int d_offset = big_endian ? 2 : 0; - Powerpc_relobj* const object - = static_cast*>(relinfo->object); Address value = 0; bool has_stub_value = false; bool localentry0 = false; @@ -10646,8 +10749,12 @@ Target_powerpc::Relocate::relocate( || r_type == elfcpp::R_PPC64_GOT_TLSGD_PCREL34) { // First instruction of a global dynamic sequence, arg setup insn. - const bool final = gsym == NULL || gsym->final_value_is_known(); - const tls::Tls_optimization tls_type = target->optimize_tls_gd(final); + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!object->no_tls_marker()) + { + bool final = gsym == NULL || gsym->final_value_is_known(); + tls_type = target->optimize_tls_gd(final); + } enum Got_type got_type = GOT_TYPE_STANDARD; if (tls_type == tls::TLSOPT_NONE) got_type = GOT_TYPE_TLSGD; @@ -10752,7 +10859,9 @@ Target_powerpc::Relocate::relocate( || r_type == elfcpp::R_PPC64_GOT_TLSLD_PCREL34) { // First instruction of a local dynamic sequence, arg setup insn. - const tls::Tls_optimization tls_type = target->optimize_tls_ld(); + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!object->no_tls_marker()) + tls_type = target->optimize_tls_ld(); if (tls_type == tls::TLSOPT_NONE) { value = target->tlsld_got_offset(); @@ -10831,8 +10940,8 @@ Target_powerpc::Relocate::relocate( || r_type == elfcpp::R_PPC64_GOT_TPREL_PCREL34) { // First instruction of initial exec sequence. - const bool final = gsym == NULL || gsym->final_value_is_known(); - const tls::Tls_optimization tls_type = target->optimize_tls_ie(final); + bool final = gsym == NULL || gsym->final_value_is_known(); + tls::Tls_optimization tls_type = target->optimize_tls_ie(final); if (tls_type == tls::TLSOPT_NONE) { if (gsym != NULL) @@ -10897,8 +11006,12 @@ Target_powerpc::Relocate::relocate( // Second instruction of a global dynamic sequence, // the __tls_get_addr call this->expect_tls_get_addr_call(relinfo, relnum, rela.get_r_offset()); - const bool final = gsym == NULL || gsym->final_value_is_known(); - const tls::Tls_optimization tls_type = target->optimize_tls_gd(final); + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!object->no_tls_marker()) + { + bool final = gsym == NULL || gsym->final_value_is_known(); + tls_type = target->optimize_tls_gd(final); + } if (tls_type != tls::TLSOPT_NONE) { if (tls_type == tls::TLSOPT_TO_IE) @@ -10949,7 +11062,9 @@ Target_powerpc::Relocate::relocate( // Second instruction of a local dynamic sequence, // the __tls_get_addr call this->expect_tls_get_addr_call(relinfo, relnum, rela.get_r_offset()); - const tls::Tls_optimization tls_type = target->optimize_tls_ld(); + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!object->no_tls_marker()) + tls_type = target->optimize_tls_ld(); if (tls_type == tls::TLSOPT_TO_LE) { bool is_pcrel = false; @@ -10985,8 +11100,8 @@ Target_powerpc::Relocate::relocate( else if (r_type == elfcpp::R_POWERPC_TLS) { // Second instruction of an initial exec sequence - const bool final = gsym == NULL || gsym->final_value_is_known(); - const tls::Tls_optimization tls_type = target->optimize_tls_ie(final); + bool final = gsym == NULL || gsym->final_value_is_known(); + tls::Tls_optimization tls_type = target->optimize_tls_ie(final); if (tls_type == tls::TLSOPT_TO_LE) { Address roff = rela.get_r_offset() & 3; @@ -12439,8 +12554,13 @@ Target_powerpc::relocate_relocs( { // First instruction of a global dynamic sequence, // arg setup insn. - const bool final = gsym == NULL || gsym->final_value_is_known(); - switch (this->optimize_tls_gd(final)) + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!object->no_tls_marker()) + { + bool final = gsym == NULL || gsym->final_value_is_known(); + tls_type = this->optimize_tls_gd(final); + } + switch (tls_type) { case tls::TLSOPT_TO_IE: r_type += (elfcpp::R_POWERPC_GOT_TPREL16 @@ -12467,7 +12587,10 @@ Target_powerpc::relocate_relocs( { // First instruction of a local dynamic sequence, // arg setup insn. - if (this->optimize_tls_ld() == tls::TLSOPT_TO_LE) + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!object->no_tls_marker()) + tls_type = this->optimize_tls_ld(); + if (tls_type == tls::TLSOPT_TO_LE) { if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16 || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO) @@ -12493,7 +12616,7 @@ Target_powerpc::relocate_relocs( || r_type == elfcpp::R_POWERPC_GOT_TPREL16_HA) { // First instruction of initial exec sequence. - const bool final = gsym == NULL || gsym->final_value_is_known(); + bool final = gsym == NULL || gsym->final_value_is_known(); if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE) { if (r_type == elfcpp::R_POWERPC_GOT_TPREL16 @@ -12511,8 +12634,13 @@ Target_powerpc::relocate_relocs( { // Second instruction of a global dynamic sequence, // the __tls_get_addr call - const bool final = gsym == NULL || gsym->final_value_is_known(); - switch (this->optimize_tls_gd(final)) + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!object->no_tls_marker()) + { + bool final = gsym == NULL || gsym->final_value_is_known(); + tls_type = this->optimize_tls_gd(final); + } + switch (tls_type) { case tls::TLSOPT_TO_IE: r_type = elfcpp::R_POWERPC_NONE; @@ -12532,7 +12660,10 @@ Target_powerpc::relocate_relocs( { // Second instruction of a local dynamic sequence, // the __tls_get_addr call - if (this->optimize_tls_ld() == tls::TLSOPT_TO_LE) + tls::Tls_optimization tls_type = tls::TLSOPT_NONE; + if (!object->no_tls_marker()) + tls_type = this->optimize_tls_ld(); + if (tls_type == tls::TLSOPT_TO_LE) { const Output_section* os = relinfo->layout->tls_segment() ->first_section(); @@ -12548,7 +12679,7 @@ Target_powerpc::relocate_relocs( else if (r_type == elfcpp::R_POWERPC_TLS) { // Second instruction of an initial exec sequence - const bool final = gsym == NULL || gsym->final_value_is_known(); + bool final = gsym == NULL || gsym->final_value_is_known(); if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE) { r_type = elfcpp::R_POWERPC_TPREL16_LO;