aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog6
-rw-r--r--gold/x86_64.cc73
2 files changed, 47 insertions, 32 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 6c78bcf..c0dbc26 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,9 @@
+2010-09-14 Cary Coutant <ccoutant@google.com>
+
+ * x86_64.cc (Target_x86_64::saw_tls_block_reloc_): Remove member.
+ (Target_x86_64::Relocate::relocate_tls): Replace check for
+ saw_tls_block_reloc_ with test for executable section.
+
2010-09-12 Cary Coutant <ccoutant@google.com>
* symtab.h (Symbol::needs_dynamic_reloc): Non-PIC calls from
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 4fec45c..1396fb3 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -420,7 +420,7 @@ class Target_x86_64 : public Target_freebsd<64, false>
{
public:
Relocate()
- : skip_call_tls_get_addr_(false), saw_tls_block_reloc_(false)
+ : skip_call_tls_get_addr_(false)
{ }
~Relocate()
@@ -511,12 +511,6 @@ class Target_x86_64 : public Target_freebsd<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,
@@ -2492,18 +2486,29 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
const Sized_relobj<64, false>* object = relinfo->object;
const elfcpp::Elf_Xword addend = rela.get_r_addend();
+ elfcpp::Shdr<64, false> data_shdr(relinfo->data_shdr);
+ bool is_executable = (data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0;
elfcpp::Elf_types<64>::Elf_Addr value = psymval->value(relinfo->object, 0);
const bool is_final = (gsym == NULL
? !parameters->options().shared()
: gsym->final_value_is_known());
- const tls::Tls_optimization optimized_type
+ tls::Tls_optimization optimized_type
= Target_x86_64::optimize_tls_reloc(is_final, r_type);
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
- this->saw_tls_block_reloc_ = true;
+ if (!is_executable && optimized_type == tls::TLSOPT_TO_LE)
+ {
+ // If this code sequence is used in a non-executable section,
+ // we will not optimize the R_X86_64_DTPOFF32/64 relocation,
+ // on the assumption that it's being used by itself in a debug
+ // section. Therefore, in the unlikely event that the code
+ // sequence appears in a non-executable section, we simply
+ // leave it unoptimized.
+ optimized_type = tls::TLSOPT_NONE;
+ }
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
@@ -2554,7 +2559,11 @@ 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 (!is_executable && optimized_type == tls::TLSOPT_TO_LE)
+ {
+ // See above comment for R_X86_64_TLSGD.
+ optimized_type = tls::TLSOPT_NONE;
+ }
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
@@ -2617,7 +2626,11 @@ 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 (!is_executable && optimized_type == tls::TLSOPT_TO_LE)
+ {
+ // See above comment for R_X86_64_TLSGD.
+ optimized_type = tls::TLSOPT_NONE;
+ }
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
@@ -2642,31 +2655,27 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
break;
case elfcpp::R_X86_64_DTPOFF32:
- if (optimized_type == tls::TLSOPT_TO_LE)
- {
- // 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_)
- {
- gold_assert(tls_segment != NULL);
- value -= tls_segment->memsz();
- }
- }
+ // This relocation type is used in debugging information.
+ // In that case we need to not optimize the value. If the
+ // section is not executable, then we assume we should not
+ // optimize this reloc. See comments above for R_X86_64_TLSGD,
+ // R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC_CALL, and
+ // R_X86_64_TLSLD.
+ if (optimized_type == tls::TLSOPT_TO_LE && is_executable)
+ {
+ gold_assert(tls_segment != NULL);
+ value -= tls_segment->memsz();
+ }
Relocate_functions<64, false>::rela32(view, value, addend);
break;
case elfcpp::R_X86_64_DTPOFF64:
- if (optimized_type == tls::TLSOPT_TO_LE)
- {
- // See R_X86_64_DTPOFF32, just above, for why we test this.
- if (this->saw_tls_block_reloc_)
- {
- gold_assert(tls_segment != NULL);
- value -= tls_segment->memsz();
- }
- }
+ // See R_X86_64_DTPOFF32, just above, for why we check for is_executable.
+ if (optimized_type == tls::TLSOPT_TO_LE && is_executable)
+ {
+ gold_assert(tls_segment != NULL);
+ value -= tls_segment->memsz();
+ }
Relocate_functions<64, false>::rela64(view, value, addend);
break;