aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog10
-rw-r--r--gold/i386.cc4
-rw-r--r--gold/x86_64.cc26
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 <iant@google.com>
+ * 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;