diff options
author | Ian Lance Taylor <ian@airs.com> | 2010-08-02 10:07:03 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2010-08-02 10:07:03 +0000 |
commit | a8df5856e2174b21c341d926068f195624d5d089 (patch) | |
tree | ac21be63f1586266d08e42e8052c8f0c1f0be848 /gold/x86_64.cc | |
parent | b27423bb543a28c11bdfb63dc5ea978a4a637f67 (diff) | |
download | gdb-a8df5856e2174b21c341d926068f195624d5d089.zip gdb-a8df5856e2174b21c341d926068f195624d5d089.tar.gz gdb-a8df5856e2174b21c341d926068f195624d5d089.tar.bz2 |
* i386.cc (class Target_i386): Add got_tlsdesc_ field.
(Target_i386::Target_i386):: Initialize got_tlsdesc_.
(Target_i386::got_tlsdesc_section): New function.
(Target_i386::got_section): Create space for GOT entries for
TLSDESC relocations.
(Target_i386::Scan::local): Use TLSDESC GOT for unoptimized
R_386_TLS_GOTDESC.
(Target_i386::Scan::global): Likewise.
(Target_i386::Relocate::relocate_tls): Adjust GOT offset when
using TLSDESC GOT.
* x86_64.cc (class Target_x86_64): Add got_tlsdesc_ field.
(Target_x86_64::Target_x86_64):: Initialize got_tlsdesc_.
(Target_x86_64::got_tlsdesc_section): New function.
(Target_x86_64::got_section): Create space for GOT entries for
TLSDESC relocations.
(Target_x86_64::Scan::local): Use TLSDESC GOT for unoptimized
R_386_TLS_GOTDESC.
(Target_x86_64::Scan::global): Likewise.
(Target_x86_64::Relocate::relocate_tls): Adjust GOT offset when
using TLSDESC GOT.
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r-- | gold/x86_64.cc | 63 |
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) { |