diff options
Diffstat (limited to 'binutils-2.27/gold/x86_64.cc')
-rw-r--r-- | binutils-2.27/gold/x86_64.cc | 187 |
1 files changed, 150 insertions, 37 deletions
diff --git a/binutils-2.27/gold/x86_64.cc b/binutils-2.27/gold/x86_64.cc index 83fa130f..7b736188 100644 --- a/binutils-2.27/gold/x86_64.cc +++ b/binutils-2.27/gold/x86_64.cc @@ -444,14 +444,15 @@ class Target_x86_64 : public Sized_target<size, false> // In the x86_64 ABI (p 68), it says "The AMD64 ABI architectures // uses only Elf64_Rela relocation entries with explicit addends." typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section; + typedef Output_data_reloc<elfcpp::SHT_RELR, true, size, false> Relr_section; Target_x86_64(const Target::Target_info* info = &x86_64_info) : Sized_target<size, false>(info), got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL), got_tlsdesc_(NULL), global_offset_table_(NULL), rela_dyn_(NULL), - rela_irelative_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY), - got_mod_index_offset_(-1U), tlsdesc_reloc_info_(), - tls_base_symbol_defined_(false) + rela_irelative_(NULL), relr_dyn_(NULL), + copy_relocs_(elfcpp::R_X86_64_COPY), got_mod_index_offset_(-1U), + tlsdesc_reloc_info_(), tls_base_symbol_defined_(false) { } // The safe value for data segment size for PIE links. @@ -740,6 +741,43 @@ class Target_x86_64 : public Sized_target<size, false> plt_count); } + bool + do_may_relax() const + { + // If generating '.relr.dyn' section, we need a relaxation pass + // to do the shrinking after all the offsets have been populated. + return parameters->options().experimental_use_relr(); + } + + bool + do_relax (int pass, const Input_objects*, Symbol_table*, Layout* layout, const Task*) + { + if (pass > 1) + return false; + + Layout::Section_list::const_iterator p = layout->section_list().begin(); + for ( ; p != layout->section_list().end(); ++p) + { + if (is_prefix_of(".relr.dyn", (*p)->name())) + break; + } + + if (p == layout->section_list().end()) + return false; + + Output_section * const os = *p; + for (Output_section::Input_section_list::iterator ip = os->input_sections().begin(); + ip != os->input_sections().end(); + ++ip) + { + Relr_section *od = static_cast<Relr_section *>(ip->output_section_data()); + od->shrink_relocs(); + } + + return true; + } + + private: // The class which scans relocations. class Scan @@ -1044,6 +1082,10 @@ class Target_x86_64 : public Sized_target<size, false> Reloc_section* rela_irelative_section(Layout*); + // Get the RELR dynamic reloc section, creating it if necessary. + Relr_section* + relr_dyn_section(Layout*); + // Add a potential copy relocation. void copy_reloc(Symbol_table* symtab, Layout* layout, @@ -1107,6 +1149,8 @@ class Target_x86_64 : public Sized_target<size, false> Reloc_section* rela_dyn_; // The section to use for IRELATIVE relocs. Reloc_section* rela_irelative_; + // The RELR dynamic reloc section. + Relr_section* relr_dyn_; // Relocs saved to avoid a COPY reloc. Copy_relocs<elfcpp::SHT_RELA, size, false> copy_relocs_; // Offset of the GOT entry for the TLS module index. @@ -1303,6 +1347,23 @@ Target_x86_64<size>::rela_irelative_section(Layout* layout) return this->rela_irelative_; } +// Get the RELR dynamic reloc section, creating it if necessary. + +template<int size> +typename Target_x86_64<size>::Relr_section* +Target_x86_64<size>::relr_dyn_section(Layout* layout) +{ + if (this->relr_dyn_ == NULL) + { + gold_assert(layout != NULL); + this->relr_dyn_ = new Relr_section(); + layout->add_output_section_data(".relr.dyn", elfcpp::SHT_RELR, + elfcpp::SHF_ALLOC, this->relr_dyn_, + ORDER_DYNAMIC_RELOCS, false); + } + return this->relr_dyn_; +} + // Write the first three reserved words of the .got.plt section. // The remainder of the section is written while writing the PLT // in Output_data_plt_i386::do_write. @@ -2486,14 +2547,25 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab, if (parameters->options().output_is_position_independent()) { unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); - Reloc_section* rela_dyn = target->rela_dyn_section(layout); - rela_dyn->add_local_relative(object, r_sym, - (size == 32 - ? elfcpp::R_X86_64_RELATIVE64 - : elfcpp::R_X86_64_RELATIVE), - output_section, data_shndx, - reloc.get_r_offset(), - reloc.get_r_addend(), is_ifunc); + if (size == 64 + && !is_ifunc + && parameters->options().experimental_use_relr()) + { + Relr_section* relr_dyn = target->relr_dyn_section(layout); + relr_dyn->add_local_relative(object, r_sym, output_section, + data_shndx, reloc.get_r_offset()); + } + else + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_local_relative(object, r_sym, + (size == 32 + ? elfcpp::R_X86_64_RELATIVE64 + : elfcpp::R_X86_64_RELATIVE), + output_section, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend(), is_ifunc); + } } break; @@ -2511,12 +2583,22 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab, if (size == 32 && r_type == elfcpp::R_X86_64_32) { unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); - Reloc_section* rela_dyn = target->rela_dyn_section(layout); - rela_dyn->add_local_relative(object, r_sym, - elfcpp::R_X86_64_RELATIVE, - output_section, data_shndx, - reloc.get_r_offset(), - reloc.get_r_addend(), is_ifunc); + if (!is_ifunc && parameters->options().experimental_use_relr()) + { + Relr_section* relr_dyn = target->relr_dyn_section(layout); + relr_dyn->add_local_relative(object, r_sym, output_section, + data_shndx, + reloc.get_r_offset()); + } + else + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_local_relative(object, r_sym, + elfcpp::R_X86_64_RELATIVE, + output_section, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend(), is_ifunc); + } break; } @@ -2617,24 +2699,33 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab, // dynamic relocation for this symbol's GOT entry. if (parameters->options().output_is_position_independent()) { + unsigned int got_offset = + object->local_got_offset(r_sym, GOT_TYPE_STANDARD); Reloc_section* rela_dyn = target->rela_dyn_section(layout); // R_X86_64_RELATIVE assumes a 64-bit relocation. - if (r_type != elfcpp::R_X86_64_GOT32) - { - unsigned int got_offset = - object->local_got_offset(r_sym, GOT_TYPE_STANDARD); - rela_dyn->add_local_relative(object, r_sym, - elfcpp::R_X86_64_RELATIVE, - got, got_offset, 0, is_ifunc); - } - else + if (r_type == elfcpp::R_X86_64_GOT32) { this->check_non_pic(object, r_type, NULL); gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION); rela_dyn->add_local( object, r_sym, r_type, got, - object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0); + got_offset, 0); + } + else if (size == 64 + && !is_ifunc + && parameters->options().experimental_use_relr()) + { + Relr_section* relr_dyn = + target->relr_dyn_section(layout); + relr_dyn->add_local_relative(object, r_sym, + got, got_offset); + } + else + { + rela_dyn->add_local_relative(object, r_sym, + elfcpp::R_X86_64_RELATIVE, + got, got_offset, 0, is_ifunc); } } } @@ -2998,12 +3089,24 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab, || (size == 32 && r_type == elfcpp::R_X86_64_32)) && gsym->can_use_relative_reloc(false)) { - Reloc_section* rela_dyn = target->rela_dyn_section(layout); - rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE, - output_section, object, - data_shndx, - reloc.get_r_offset(), - reloc.get_r_addend(), false); + if (parameters->options().experimental_use_relr()) + { + Relr_section* relr_dyn = + target->relr_dyn_section(layout); + relr_dyn->add_global_relative(gsym, output_section, + object, data_shndx, + reloc.get_r_offset()); + } + else + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_global_relative(gsym, + elfcpp::R_X86_64_RELATIVE, + output_section, object, + data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend(), false); + } } else { @@ -3135,9 +3238,18 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab, if (is_new) { unsigned int got_off = gsym->got_offset(GOT_TYPE_STANDARD); - rela_dyn->add_global_relative(gsym, - elfcpp::R_X86_64_RELATIVE, - got, got_off, 0, false); + if (parameters->options().experimental_use_relr()) + { + Relr_section* relr_dyn = + target->relr_dyn_section(layout); + relr_dyn->add_global_relative(gsym, got, got_off); + } + else + { + rela_dyn->add_global_relative(gsym, + elfcpp::R_X86_64_RELATIVE, + got, got_off, 0, false); + } } } } @@ -3406,7 +3518,8 @@ Target_x86_64<size>::do_finalize_sections( ? NULL : this->plt_->rela_plt()); layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt, - this->rela_dyn_, true, false); + this->rela_dyn_, true, false, + this->relr_dyn_); // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data(); |