From fd6fc0c5f6ec26b3b526655a721b7b0af0b14644 Mon Sep 17 00:00:00 2001 From: Andrew Hsieh Date: Tue, 24 Feb 2015 18:17:57 +0800 Subject: Update binutils-2.25/gold to ToT commit be66981e1605eff305ac9c561825f4bd6801fca2 Author: H.J. Lu Date: Sun Feb 22 05:18:50 2015 -0800 Set GOLD_DEFAULT_SIZE to 32 for x32 * configure.ac (default_size): Set to 32 for x32. * configure: Regenerated. Change-Id: I4b2d8927e4e41cf2fac3c92d00e8aef69b5ce21f --- binutils-2.25/gold/x86_64.cc | 83 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 19 deletions(-) (limited to 'binutils-2.25/gold/x86_64.cc') diff --git a/binutils-2.25/gold/x86_64.cc b/binutils-2.25/gold/x86_64.cc index f58c843..4543c8a 100644 --- a/binutils-2.25/gold/x86_64.cc +++ b/binutils-2.25/gold/x86_64.cc @@ -1,6 +1,6 @@ // x86_64.cc -- x86_64 target support for gold. -// Copyright (C) 2006-2014 Free Software Foundation, Inc. +// Copyright (C) 2006-2015 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -1516,11 +1516,16 @@ Output_data_plt_x86_64_standard::do_fill_plt_entry( unsigned int plt_offset, unsigned int plt_index) { + // Check PC-relative offset overflow in PLT entry. + uint64_t plt_got_pcrel_offset = (got_address + got_offset + - (plt_address + plt_offset + 6)); + if (Bits<32>::has_overflow(plt_got_pcrel_offset)) + gold_error(_("PC-relative offset overflow in PLT entry %d"), + plt_index + 1); + memcpy(pov, plt_entry, plt_entry_size); elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, - (got_address + got_offset - - (plt_address + plt_offset - + 6))); + plt_got_pcrel_offset); elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_index); elfcpp::Swap<32, false>::writeval(pov + 12, @@ -2923,11 +2928,6 @@ Target_x86_64::Scan::global(Symbol_table* symtab, } } } - // For GOTPLT64, we also need a PLT entry (but only if the - // symbol is not fully resolved). - if (r_type == elfcpp::R_X86_64_GOTPLT64 - && !gsym->final_value_is_known()) - target->make_plt_entry(symtab, layout, gsym); } break; @@ -2983,7 +2983,12 @@ Target_x86_64::Scan::global(Symbol_table* symtab, case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec case elfcpp::R_X86_64_TPOFF32: // Local-exec { - const bool is_final = gsym->final_value_is_known(); + // For the Initial-Exec model, we can treat undef symbols as final + // when building an executable. + const bool is_final = (gsym->final_value_is_known() || + (r_type == elfcpp::R_X86_64_GOTTPOFF && + gsym->is_undefined() && + parameters->options().output_is_executable())); const tls::Tls_optimization optimized_type = Target_x86_64::optimize_tls_reloc(is_final, r_type); switch (r_type) @@ -3454,9 +3459,9 @@ Target_x86_64::Relocate::relocate( break; case elfcpp::R_X86_64_GOT64: - // The ABI doc says "Like GOT64, but indicates a PLT entry is needed." - // Since we always add a PLT entry, this is equivalent. case elfcpp::R_X86_64_GOTPLT64: + // R_X86_64_GOTPLT64 is obsolete and treated the the same as + // GOT64. gold_assert(have_got_offset); Relocate_functions::rela64(view, got_offset, addend); break; @@ -3779,7 +3784,17 @@ Target_x86_64::Relocate::relocate_tls( break; case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec - if (optimized_type == tls::TLSOPT_TO_LE) + if (gsym != NULL + && gsym->is_undefined() + && parameters->options().output_is_executable()) + { + Target_x86_64::Relocate::tls_ie_to_le(relinfo, relnum, + NULL, rela, + r_type, value, view, + view_size); + break; + } + else if (optimized_type == tls::TLSOPT_TO_LE) { if (tls_segment == NULL) { @@ -4100,6 +4115,8 @@ Target_x86_64::Relocate::tls_ie_to_le( // movq if (op1 == 0x4c) view[-3] = 0x49; + else if (size == 32 && op1 == 0x44) + view[-3] = 0x41; view[-2] = 0xc7; view[-1] = 0xc0 | reg; } @@ -4108,6 +4125,8 @@ Target_x86_64::Relocate::tls_ie_to_le( // Special handling for %rsp. if (op1 == 0x4c) view[-3] = 0x49; + else if (size == 32 && op1 == 0x44) + view[-3] = 0x41; view[-2] = 0x81; view[-1] = 0xc0 | reg; } @@ -4116,11 +4135,14 @@ Target_x86_64::Relocate::tls_ie_to_le( // addq if (op1 == 0x4c) view[-3] = 0x4d; + else if (size == 32 && op1 == 0x44) + view[-3] = 0x45; view[-2] = 0x8d; view[-1] = 0x80 | reg | (reg << 3); } - value -= tls_segment->memsz(); + if (tls_segment != NULL) + value -= tls_segment->memsz(); Relocate_functions::rela32(view, value, 0); } @@ -4457,6 +4479,14 @@ Target_x86_64::do_ehframe_datarel_base() const // code. We have to change the function so that it always ensures // that it has enough stack space to run some random function. +static const unsigned char cmp_insn_32[] = { 0x64, 0x3b, 0x24, 0x25 }; +static const unsigned char lea_r10_insn_32[] = { 0x44, 0x8d, 0x94, 0x24 }; +static const unsigned char lea_r11_insn_32[] = { 0x44, 0x8d, 0x9c, 0x24 }; + +static const unsigned char cmp_insn_64[] = { 0x64, 0x48, 0x3b, 0x24, 0x25 }; +static const unsigned char lea_r10_insn_64[] = { 0x4c, 0x8d, 0x94, 0x24 }; +static const unsigned char lea_r11_insn_64[] = { 0x4c, 0x8d, 0x9c, 0x24 }; + template void Target_x86_64::do_calls_non_split(Relobj* object, unsigned int shndx, @@ -4467,25 +4497,40 @@ Target_x86_64::do_calls_non_split(Relobj* object, unsigned int shndx, std::string* from, std::string* to) const { + const char* const cmp_insn = reinterpret_cast + (size == 32 ? cmp_insn_32 : cmp_insn_64); + const char* const lea_r10_insn = reinterpret_cast + (size == 32 ? lea_r10_insn_32 : lea_r10_insn_64); + const char* const lea_r11_insn = reinterpret_cast + (size == 32 ? lea_r11_insn_32 : lea_r11_insn_64); + + const size_t cmp_insn_len = + (size == 32 ? sizeof(cmp_insn_32) : sizeof(cmp_insn_64)); + const size_t lea_r10_insn_len = + (size == 32 ? sizeof(lea_r10_insn_32) : sizeof(lea_r10_insn_64)); + const size_t lea_r11_insn_len = + (size == 32 ? sizeof(lea_r11_insn_32) : sizeof(lea_r11_insn_64)); + const size_t nop_len = (size == 32 ? 7 : 8); + // The function starts with a comparison of the stack pointer and a // field in the TCB. This is followed by a jump. // cmp %fs:NN,%rsp - if (this->match_view(view, view_size, fnoffset, "\x64\x48\x3b\x24\x25", 5) - && fnsize > 9) + if (this->match_view(view, view_size, fnoffset, cmp_insn, cmp_insn_len) + && fnsize > nop_len + 1) { // We will call __morestack if the carry flag is set after this // comparison. We turn the comparison into an stc instruction // and some nops. view[fnoffset] = '\xf9'; - this->set_view_to_nop(view, view_size, fnoffset + 1, 8); + this->set_view_to_nop(view, view_size, fnoffset + 1, nop_len); } // lea NN(%rsp),%r10 // lea NN(%rsp),%r11 else if ((this->match_view(view, view_size, fnoffset, - "\x4c\x8d\x94\x24", 4) + lea_r10_insn, lea_r10_insn_len) || this->match_view(view, view_size, fnoffset, - "\x4c\x8d\x9c\x24", 4)) + lea_r11_insn, lea_r11_insn_len)) && fnsize > 8) { // This is loading an offset from the stack pointer for a -- cgit v1.1