From 497897f98cc3ae32477afbbf00fd871372a69ce7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 16 May 2008 20:44:22 +0000 Subject: * i386.cc (Target_i386::Relocate::relocate_tls): Set dynamic type for TLS_GOTDESC and TLS_DESC_CALL. Only optimize TLS_LDO_32 if we know the dynamic type. * x86_64.cc (Target_x86_64::Relocate): Add saw_tls_block_reloc_ field. Initialize it in constructor. (Target_x86_64::Relocate::relocate_tls): Record that we saw a TLS block reloc for TLSGD, GOTPC32_TLSDESC, TLSDESC_CALL, and TLSLD. Only optimize DTPOFF32 and DTPOFF64 if we have seen a TLS block reloc. --- gold/ChangeLog | 10 ++++++++++ gold/i386.cc | 4 +++- gold/x86_64.cc | 26 +++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 9bac71f..c282214 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,15 @@ 2008-05-16 Ian Lance Taylor + * i386.cc (Target_i386::Relocate::relocate_tls): Set dynamic type + for TLS_GOTDESC and TLS_DESC_CALL. Only optimize TLS_LDO_32 if we + know the dynamic type. + * x86_64.cc (Target_x86_64::Relocate): Add saw_tls_block_reloc_ + field. Initialize it in constructor. + (Target_x86_64::Relocate::relocate_tls): Record that we saw a TLS + block reloc for TLSGD, GOTPC32_TLSDESC, TLSDESC_CALL, and TLSLD. + Only optimize DTPOFF32 and DTPOFF64 if we have seen a TLS block + reloc. + * output.cc (Output_reloc::get_address): Change return type to Elf_Addr. * output.h (class Output_reloc): Update get_address declaration. diff --git a/gold/i386.cc b/gold/i386.cc index 9f86229..1d04f4f 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -1843,6 +1843,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo, case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url) case elfcpp::R_386_TLS_DESC_CALL: + this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU; if (optimized_type == tls::TLSOPT_TO_LE) { gold_assert(tls_segment != NULL); @@ -1927,7 +1928,8 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo, // This reloc can appear in debugging sections, in which case we // won't see the TLS_LDM reloc. The local_dynamic_type field // tells us this. - if (optimized_type == tls::TLSOPT_TO_LE) + if (optimized_type == tls::TLSOPT_TO_LE + && this->local_dynamic_type_ != LOCAL_DYNAMIC_NONE) { gold_assert(tls_segment != NULL); value -= tls_segment->memsz(); diff --git a/gold/x86_64.cc b/gold/x86_64.cc index d787700..b7d4933 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -197,7 +197,7 @@ class Target_x86_64 : public Sized_target<64, false> { public: Relocate() - : skip_call_tls_get_addr_(false) + : skip_call_tls_get_addr_(false), saw_tls_block_reloc_(false) { } ~Relocate() @@ -288,6 +288,12 @@ class Target_x86_64 : public Sized_target<64, false> // This is set if we should skip the next reloc, which should be a // PLT32 reloc against ___tls_get_addr. bool skip_call_tls_get_addr_; + + // This is set if we see a relocation which could load the address + // of the TLS block. Whether we see such a relocation determines + // how we handle the R_X86_64_DTPOFF32 relocation, which is used + // in debugging sections. + bool saw_tls_block_reloc_; }; // A class which returns the size required for a relocation type, @@ -1897,6 +1903,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo, switch (r_type) { case elfcpp::R_X86_64_TLSGD: // Global-dynamic + this->saw_tls_block_reloc_ = true; if (optimized_type == tls::TLSOPT_TO_LE) { gold_assert(tls_segment != NULL); @@ -1947,6 +1954,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo, case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) case elfcpp::R_X86_64_TLSDESC_CALL: + this->saw_tls_block_reloc_ = true; if (optimized_type == tls::TLSOPT_TO_LE) { gold_assert(tls_segment != NULL); @@ -2000,6 +2008,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo, break; case elfcpp::R_X86_64_TLSLD: // Local-dynamic + this->saw_tls_block_reloc_ = true; if (optimized_type == tls::TLSOPT_TO_LE) { gold_assert(tls_segment != NULL); @@ -2026,14 +2035,25 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo, case elfcpp::R_X86_64_DTPOFF32: gold_assert(tls_segment != NULL); if (optimized_type == tls::TLSOPT_TO_LE) - value -= tls_segment->memsz(); + { + // This relocation type is used in debugging information. + // In that case we need to not optimize the value. If we + // haven't seen a TLSLD reloc, then we assume we should not + // optimize this reloc. + if (this->saw_tls_block_reloc_) + value -= tls_segment->memsz(); + } Relocate_functions<64, false>::rela32(view, value, 0); break; case elfcpp::R_X86_64_DTPOFF64: gold_assert(tls_segment != NULL); if (optimized_type == tls::TLSOPT_TO_LE) - value -= tls_segment->memsz(); + { + // See R_X86_64_DTPOFF32, just above, for why we test this. + if (this->saw_tls_block_reloc_) + value -= tls_segment->memsz(); + } Relocate_functions<64, false>::rela64(view, value, 0); break; -- cgit v1.1