aboutsummaryrefslogtreecommitdiff
path: root/gold/x86_64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r--gold/x86_64.cc63
1 files changed, 50 insertions, 13 deletions
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 2a5cecb..54f07db 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -1,6 +1,6 @@
// x86_64.cc -- x86_64 target support for gold.
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -64,8 +64,9 @@ class Target_x86_64 : public Target_freebsd<64, false>
Target_x86_64()
: Target_freebsd<64, false>(&x86_64_info),
- got_(NULL), plt_(NULL), got_plt_(NULL), global_offset_table_(NULL),
- rela_dyn_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL),
+ got_(NULL), plt_(NULL), got_plt_(NULL), got_tlsdesc_(NULL),
+ global_offset_table_(NULL), rela_dyn_(NULL),
+ copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL),
got_mod_index_offset_(-1U), tlsdesc_reloc_info_(),
tls_base_symbol_defined_(false)
{ }
@@ -403,6 +404,14 @@ class Target_x86_64 : public Target_freebsd<64, false>
return this->got_plt_;
}
+ // Get the GOT section for TLSDESC entries.
+ Output_data_got<64, false>*
+ got_tlsdesc_section() const
+ {
+ gold_assert(this->got_tlsdesc_ != NULL);
+ return this->got_tlsdesc_;
+ }
+
// Create the PLT section.
void
make_plt_section(Symbol_table* symtab, Layout* layout);
@@ -486,6 +495,8 @@ class Target_x86_64 : public Target_freebsd<64, false>
Output_data_plt_x86_64* plt_;
// The GOT PLT section.
Output_data_space* got_plt_;
+ // The GOT section for TLSDESC relocations.
+ Output_data_got<64, false>* got_tlsdesc_;
// The _GLOBAL_OFFSET_TABLE_ symbol.
Symbol* global_offset_table_;
// The dynamic reloc section.
@@ -574,6 +585,15 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0,
false, false);
+
+ // If there are any TLSDESC relocations, they get GOT entries in
+ // .got.plt after the jump slot entries.
+ this->got_tlsdesc_ = new Output_data_got<64, false>();
+ layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ this->got_tlsdesc_, false, false, false,
+ true);
}
return this->got_;
@@ -1306,9 +1326,13 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
// Create reserved PLT and GOT entries for the resolver.
target->reserve_tlsdesc_entries(symtab, layout);
- // Generate a double GOT entry with an R_X86_64_TLSDESC reloc.
- Output_data_got<64, false>* got
- = target->got_section(symtab, layout);
+ // Generate a double GOT entry with an
+ // R_X86_64_TLSDESC reloc. The R_X86_64_TLSDESC reloc
+ // is resolved lazily, so the GOT entry needs to be in
+ // an area in .got.plt, not .got. Call got_section to
+ // make sure the section has been created.
+ target->got_section(symtab, layout);
+ Output_data_got<64, false>* got = target->got_tlsdesc_section();
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
{
@@ -1687,9 +1711,13 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
// Create reserved PLT and GOT entries for the resolver.
target->reserve_tlsdesc_entries(symtab, layout);
- // Create a double GOT entry with an R_X86_64_TLSDESC reloc.
- Output_data_got<64, false>* got
- = target->got_section(symtab, layout);
+ // Create a double GOT entry with an R_X86_64_TLSDESC
+ // reloc. The R_X86_64_TLSDESC reloc is resolved
+ // lazily, so the GOT entry needs to be in an area in
+ // .got.plt, not .got. Call got_section to make sure
+ // the section has been created.
+ target->got_section(symtab, layout);
+ Output_data_got<64, false>* got = target->got_tlsdesc_section();
Reloc_section *rt = target->rela_tlsdesc_section(layout);
got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt,
elfcpp::R_X86_64_TLSDESC, 0);
@@ -2229,18 +2257,27 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
? GOT_TYPE_TLS_OFFSET
: GOT_TYPE_TLS_DESC);
- unsigned int got_offset;
+ unsigned int got_offset = 0;
+ if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
+ && optimized_type == tls::TLSOPT_NONE)
+ {
+ // We created GOT entries in the .got.tlsdesc portion of
+ // the .got.plt section, but the offset stored in the
+ // symbol is the offset within .got.tlsdesc.
+ got_offset = (target->got_size()
+ + target->got_plt_section()->data_size());
+ }
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(got_type));
- got_offset = gsym->got_offset(got_type) - target->got_size();
+ got_offset += gsym->got_offset(got_type) - target->got_size();
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, got_type));
- got_offset = (object->local_got_offset(r_sym, got_type)
- - target->got_size());
+ got_offset += (object->local_got_offset(r_sym, got_type)
+ - target->got_size());
}
if (optimized_type == tls::TLSOPT_TO_IE)
{