* 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.
This commit is contained in:
Ian Lance Taylor 2010-08-02 10:07:03 +00:00
parent b27423bb54
commit a8df5856e2
3 changed files with 123 additions and 26 deletions

View file

@ -1,3 +1,26 @@
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

View file

@ -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)
{

View file

@ -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)
{