diff options
author | Ian Lance Taylor <ian@airs.com> | 2010-01-08 19:33:18 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2010-01-08 19:33:18 +0000 |
commit | e291e7b9c9cd9e432fdcc63922f2529647f5b930 (patch) | |
tree | df4d976076d4d37f7b062a60f9f6bcb47b7f0ddb /gold/i386.cc | |
parent | dd35de74344bc1dad410ed21fedd14671ab57aff (diff) | |
download | gdb-e291e7b9c9cd9e432fdcc63922f2529647f5b930.zip gdb-e291e7b9c9cd9e432fdcc63922f2529647f5b930.tar.gz 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.cc | 70 |
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) |