aboutsummaryrefslogtreecommitdiff
path: root/gold/i386.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2010-01-08 19:33:18 +0000
committerIan Lance Taylor <ian@airs.com>2010-01-08 19:33:18 +0000
commite291e7b9c9cd9e432fdcc63922f2529647f5b930 (patch)
treedf4d976076d4d37f7b062a60f9f6bcb47b7f0ddb /gold/i386.cc
parentdd35de74344bc1dad410ed21fedd14671ab57aff (diff)
downloadfsf-binutils-gdb-e291e7b9c9cd9e432fdcc63922f2529647f5b930.zip
fsf-binutils-gdb-e291e7b9c9cd9e432fdcc63922f2529647f5b930.tar.gz
fsf-binutils-gdb-e291e7b9c9cd9e432fdcc63922f2529647f5b930.tar.bz2
PR 10287
PR 11063 * i386.cc (class Target_i386): Change return type of plt_section to be non-const. (class Output_data_plt_i386): Add tls_desc_rel_ field. (Output_data_plt_i386::Output_data_plt_i386): Initialize tls_desc_rel_ field. (Output_data_plt_i386::rel_tls_desc): New function. (Target_i386::rel_tls_desc_section): New function. (Target_i386::Scan::local): Rewrite R_386_TLS_GOTDESC handling. (Target_i386::Scan::global): For R_386_TLS_GOTDESC put R_386_TLS_DESC reloc in rel_tls_desc_section. * x86_64.cc (class Target_x86_64): Add tlsdesc_reloc_info_ field. Define struct Tlsdesc_info. (Target_x86_64::Target_x86_64): Initialize tlsdesc_reloc_info_. (Target_x86_64::do_reloc_symbol_index): New function. (Target_x86_64::add_tlsdesc_info): New function. (class Output_data_plt_x86_64): Add tlsdesc_rel_ field. (Output_data_plt_x86_64::Output_data_plt_x86_64): Initialize tlsdesc_rel_ field. (Output_data_plt_x86_64::rela_plt): Rename from rel_plt. Change all callers. (Output_data_plt_x86_64::rela_tlsdesc): New function. (Target_x86_64::rela_tlsdesc_section): New function. (Target_x86_64::Scan::local): Rewrite R_X86_64_GOTPC32_TLSDESC handling. (Target_x86_64::Scan::global): For R_X86_64_GOTPC32_TLSDESC put (Target_x86_64::do_reloc_addend): New function. R_X86_64_TLSDESC reloc in rela_tlsdesc_section. * output.h (class Output_reloc) [SHT_REL]: Add new constructor declarations. Define TARGET_CODE. Add arg field to u1_ union. (Output_reloc::type): New function. (Output_reloc::is_local_section_symbol): Check for TARGET_CODE. (Output_reloc::is_target_specific): New function. (Output_reloc::target_arg): New function. (class Output_reloc) [SHT_RELA]: Add four new constructors for absolute relocs and target specific relocs. (class Output_data_reloc) [SHT_REL]: Add add_absolute and add_target_specific. (class Output_data_reloc) [SHT_RELA]: Likewise. * output.cc (Output_reloc::Output_reloc): Add four new versions for absolute relocs and target specific relocs. (Output_reloc::set_needs_dynsym_index): Add TARGET_CODE case. (Output_reloc::get_symbol_index): Likewise. (Output_reloc::local_section_offset): Check that local_sym_index_ is not TARGET_CODE or 0. (Output_reloc::symbol_value): Likewise. (Output_reloc::write) [SHT_RELA]: Call target for target specific reloc. * target.h (class Target): Add reloc_symbol_index and reloc_addend functions. Add do_reloc_symbol_index and do_reloc_addend virtual functions. * layout.cc (add_target_dynamic_tags): Use output section for DT_PLTRELSZ and DT_JMPREL.
Diffstat (limited to 'gold/i386.cc')
-rw-r--r--gold/i386.cc70
1 files changed, 55 insertions, 15 deletions
diff --git a/gold/i386.cc b/gold/i386.cc
index e1b32e7..2eab3f8 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -368,7 +368,7 @@ class Target_i386 : public Target_freebsd<32, false>
Sized_relobj<32, false>* object);
// Get the PLT section.
- const Output_data_plt_i386*
+ Output_data_plt_i386*
plt_section() const
{
gold_assert(this->plt_ != NULL);
@@ -379,6 +379,10 @@ class Target_i386 : public Target_freebsd<32, false>
Reloc_section*
rel_dyn_section(Layout*);
+ // Get the section to use for TLS_DESC relocations.
+ Reloc_section*
+ rel_tls_desc_section(Layout*) const;
+
// Add a potential copy relocation.
void
copy_reloc(Symbol_table* symtab, Layout* layout,
@@ -527,6 +531,10 @@ class Output_data_plt_i386 : public Output_section_data
rel_plt() const
{ return this->rel_; }
+ // Return where the TLS_DESC relocations should go.
+ Reloc_section*
+ rel_tls_desc(Layout*);
+
protected:
void
do_adjust_output_section(Output_section* os);
@@ -563,6 +571,9 @@ class Output_data_plt_i386 : public Output_section_data
// The reloc section.
Reloc_section* rel_;
+ // The TLS_DESC relocations, if necessary. These must follow the
+ // regular PLT relocs.
+ Reloc_section* tls_desc_rel_;
// The .got.plt section.
Output_data_space* got_plt_;
// The number of PLT entries.
@@ -575,7 +586,7 @@ class Output_data_plt_i386 : public Output_section_data
Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
Output_data_space* got_plt)
- : Output_section_data(4), got_plt_(got_plt), count_(0)
+ : Output_section_data(4), tls_desc_rel_(NULL), got_plt_(got_plt), count_(0)
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
@@ -621,6 +632,24 @@ Output_data_plt_i386::add_entry(Symbol* gsym)
// appear in the relocations.
}
+// Return where the TLS_DESC relocations should go, creating it if
+// necessary. These follow the JUMP_SLOT relocations.
+
+Output_data_plt_i386::Reloc_section*
+Output_data_plt_i386::rel_tls_desc(Layout* layout)
+{
+ if (this->tls_desc_rel_ == NULL)
+ {
+ this->tls_desc_rel_ = new Reloc_section(false);
+ layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
+ elfcpp::SHF_ALLOC, this->tls_desc_rel_,
+ true, false, false, false);
+ gold_assert(this->tls_desc_rel_->output_section() ==
+ this->rel_->output_section());
+ }
+ return this->tls_desc_rel_;
+}
+
// The first entry in the PLT for an executable.
unsigned char Output_data_plt_i386::exec_first_plt_entry[plt_entry_size] =
@@ -771,6 +800,14 @@ Target_i386::make_plt_entry(Symbol_table* symtab, Layout* layout, Symbol* gsym)
this->plt_->add_entry(gsym);
}
+// Get the section to use for TLS_DESC relocations.
+
+Target_i386::Reloc_section*
+Target_i386::rel_tls_desc_section(Layout* layout) const
+{
+ return this->plt_section()->rel_tls_desc(layout);
+}
+
// Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
void
@@ -1055,17 +1092,20 @@ Target_i386::Scan::local(Symbol_table* symtab,
Output_data_got<32, false>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- unsigned int shndx = lsym.get_st_shndx();
- bool is_ordinary;
- shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
- if (!is_ordinary)
- object->error(_("local symbol %u has bad shndx %u"),
- r_sym, shndx);
- else
- got->add_local_pair_with_rel(object, r_sym, shndx,
- GOT_TYPE_TLS_DESC,
- target->rel_dyn_section(layout),
- elfcpp::R_386_TLS_DESC, 0);
+ if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
+ {
+ unsigned int got_offset = got->add_constant(0);
+ // The local symbol value is stored in the second
+ // GOT entry.
+ got->add_local(object, r_sym, GOT_TYPE_TLS_DESC);
+ // That set the GOT offset of the local symbol to
+ // point to the second entry, but we want it to
+ // point to the first.
+ object->set_local_got_offset(r_sym, GOT_TYPE_TLS_DESC,
+ got_offset);
+ Reloc_section* rt = target->rel_tls_desc_section(layout);
+ rt->add_absolute(elfcpp::R_386_TLS_DESC, got, got_offset);
+ }
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
@@ -1386,8 +1426,8 @@ Target_i386::Scan::global(Symbol_table* symtab,
// Create a double GOT entry with an R_386_TLS_DESC reloc.
Output_data_got<32, false>* got
= target->got_section(symtab, layout);
- got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC,
- target->rel_dyn_section(layout),
+ 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);
}
else if (optimized_type == tls::TLSOPT_TO_IE)