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 | |
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')
-rw-r--r-- | gold/ChangeLog | 23 | ||||
-rw-r--r-- | gold/i386.cc | 63 | ||||
-rw-r--r-- | gold/x86_64.cc | 63 |
3 files changed, 123 insertions, 26 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index f0062d5..2a5a289 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,28 @@ 2010-08-02 Ian Lance Taylor <iant@google.com> + * 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. + +2010-08-02 Ian Lance Taylor <iant@google.com> + * testsuite/final_layout.sh: Use dc to convert from hex to decimal. diff --git a/gold/i386.cc b/gold/i386.cc index 19728c5..ce07588 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -1,6 +1,6 @@ // i386.cc -- i386 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. @@ -59,8 +59,9 @@ class Target_i386 : public Target_freebsd<32, false> Target_i386() : Target_freebsd<32, false>(&i386_info), - got_(NULL), plt_(NULL), got_plt_(NULL), global_offset_table_(NULL), - rel_dyn_(NULL), copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL), + got_(NULL), plt_(NULL), got_plt_(NULL), got_tlsdesc_(NULL), + global_offset_table_(NULL), rel_dyn_(NULL), + copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL), got_mod_index_offset_(-1U), tls_base_symbol_defined_(false) { } @@ -385,6 +386,14 @@ class Target_i386 : public Target_freebsd<32, false> return this->got_plt_; } + // Get the GOT section for TLSDESC entries. + Output_data_got<32, false>* + got_tlsdesc_section() const + { + gold_assert(this->got_tlsdesc_ != NULL); + return this->got_tlsdesc_; + } + // Create a PLT entry for a global symbol. void make_plt_entry(Symbol_table*, Layout*, Symbol*); @@ -447,6 +456,8 @@ class Target_i386 : public Target_freebsd<32, false> Output_data_plt_i386* plt_; // The GOT PLT section. Output_data_space* got_plt_; + // The GOT section for TLSDESC relocations. + Output_data_got<32, false>* got_tlsdesc_; // The _GLOBAL_OFFSET_TABLE_ symbol. Symbol* global_offset_table_; // The dynamic reloc section. @@ -521,6 +532,15 @@ Target_i386::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<32, 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_; @@ -1117,9 +1137,13 @@ Target_i386::Scan::local(Symbol_table* symtab, target->define_tls_base_symbol(symtab, layout); if (optimized_type == tls::TLSOPT_NONE) { - // Create a double GOT entry with an R_386_TLS_DESC reloc. - Output_data_got<32, false>* got - = target->got_section(symtab, layout); + // Create a double GOT entry with an R_386_TLS_DESC + // reloc. The R_386_TLS_DESC 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<32, false>* got = target->got_tlsdesc_section(); unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC)) { @@ -1501,9 +1525,13 @@ Target_i386::Scan::global(Symbol_table* symtab, target->define_tls_base_symbol(symtab, layout); if (optimized_type == tls::TLSOPT_NONE) { - // Create a double GOT entry with an R_386_TLS_DESC reloc. - Output_data_got<32, false>* got - = target->got_section(symtab, layout); + // Create a double GOT entry with an R_386_TLS_DESC + // reloc. The R_386_TLS_DESC 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<32, false>* got = target->got_tlsdesc_section(); Reloc_section* rt = target->rel_tls_desc_section(layout); got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt, elfcpp::R_386_TLS_DESC, 0); @@ -2046,18 +2074,27 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo, unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE ? GOT_TYPE_TLS_NOFFSET : GOT_TYPE_TLS_DESC); - unsigned int got_offset; + unsigned int got_offset = 0; + if (r_type == elfcpp::R_386_TLS_GOTDESC + && 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<32>(rel.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) { 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) { |