diff -rup ../binutils-2.27/gold/aarch64.cc gold/aarch64.cc --- ../binutils-2.27/gold/aarch64.cc 2016-09-26 11:22:18.728811436 +0100 +++ gold/aarch64.cc 2016-11-03 15:05:31.000000000 +0000 @@ -6026,6 +6026,23 @@ Target_aarch64::Scan:: } break; + case elfcpp::R_AARCH64_MOVW_UABS_G0: // 263 + case elfcpp::R_AARCH64_MOVW_UABS_G0_NC: // 264 + case elfcpp::R_AARCH64_MOVW_UABS_G1: // 265 + case elfcpp::R_AARCH64_MOVW_UABS_G1_NC: // 266 + case elfcpp::R_AARCH64_MOVW_UABS_G2: // 267 + case elfcpp::R_AARCH64_MOVW_UABS_G2_NC: // 268 + case elfcpp::R_AARCH64_MOVW_UABS_G3: // 269 + case elfcpp::R_AARCH64_MOVW_SABS_G0: // 270 + case elfcpp::R_AARCH64_MOVW_SABS_G1: // 271 + case elfcpp::R_AARCH64_MOVW_SABS_G2: // 272 + if (parameters->options().output_is_position_independent()) + { + gold_error(_("%s: unsupported reloc %u in pos independent link."), + object->name().c_str(), r_type); + } + break; + case elfcpp::R_AARCH64_LD_PREL_LO19: // 273 case elfcpp::R_AARCH64_ADR_PREL_LO21: // 274 case elfcpp::R_AARCH64_ADR_PREL_PG_HI21: // 275 @@ -6311,6 +6328,23 @@ Target_aarch64::Scan:: } break; + case elfcpp::R_AARCH64_MOVW_UABS_G0: // 263 + case elfcpp::R_AARCH64_MOVW_UABS_G0_NC: // 264 + case elfcpp::R_AARCH64_MOVW_UABS_G1: // 265 + case elfcpp::R_AARCH64_MOVW_UABS_G1_NC: // 266 + case elfcpp::R_AARCH64_MOVW_UABS_G2: // 267 + case elfcpp::R_AARCH64_MOVW_UABS_G2_NC: // 268 + case elfcpp::R_AARCH64_MOVW_UABS_G3: // 269 + case elfcpp::R_AARCH64_MOVW_SABS_G0: // 270 + case elfcpp::R_AARCH64_MOVW_SABS_G1: // 271 + case elfcpp::R_AARCH64_MOVW_SABS_G2: // 272 + if (parameters->options().output_is_position_independent()) + { + gold_error(_("%s: unsupported reloc %u in pos independent link."), + object->name().c_str(), r_type); + } + break; + case elfcpp::R_AARCH64_LD_PREL_LO19: // 273 case elfcpp::R_AARCH64_ADR_PREL_LO21: // 274 case elfcpp::R_AARCH64_ADR_PREL_PG_HI21: // 275 @@ -6993,6 +7027,23 @@ Target_aarch64::Reloca view, object, psymval, addend, address, reloc_property); break; + case elfcpp::R_AARCH64_MOVW_UABS_G0: + case elfcpp::R_AARCH64_MOVW_UABS_G0_NC: + case elfcpp::R_AARCH64_MOVW_UABS_G1: + case elfcpp::R_AARCH64_MOVW_UABS_G1_NC: + case elfcpp::R_AARCH64_MOVW_UABS_G2: + case elfcpp::R_AARCH64_MOVW_UABS_G2_NC: + case elfcpp::R_AARCH64_MOVW_UABS_G3: + reloc_status = Reloc::template rela_general<32>( + view, object, psymval, addend, reloc_property); + break; + case elfcpp::R_AARCH64_MOVW_SABS_G0: + case elfcpp::R_AARCH64_MOVW_SABS_G1: + case elfcpp::R_AARCH64_MOVW_SABS_G2: + reloc_status = Reloc::movnz(view, psymval->value(object, addend), + reloc_property); + break; + case elfcpp::R_AARCH64_LD_PREL_LO19: reloc_status = Reloc::template pcrela_general<32>( view, object, psymval, addend, address, reloc_property); @@ -8075,7 +8126,7 @@ Target_aarch64::is_err typename elfcpp::Swap<32,big_endian>::Valtype insn2) { uint32_t rt; - uint32_t rt2; + uint32_t rt2 = 0; uint32_t rn; uint32_t rm; uint32_t ra; diff -rup ../binutils-2.27/gold/aarch64-reloc.def gold/aarch64-reloc.def --- ../binutils-2.27/gold/aarch64-reloc.def 2016-08-03 08:36:53.000000000 +0100 +++ gold/aarch64-reloc.def 2016-11-03 14:38:22.000000000 +0000 @@ -43,6 +43,20 @@ ARD(PREL32 , STATI ARD(PREL16 , STATIC , DATA , Y, -1, 15,16 , 0,0 , Symbol::RELATIVE_REF , DATA ) // Above is from Table 4-6, Data relocations, 257-262. +ARD(MOVW_UABS_G0 , STATIC , AARCH64 , Y, 0, 0,16 , 0,15 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G0_NC , STATIC , AARCH64 , Y, 0, 0,0 , 0,15 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G1 , STATIC , AARCH64 , Y, 0, 0,32 , 16,31 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G1_NC , STATIC , AARCH64 , Y, 0, 0,0 , 16,31 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G2 , STATIC , AARCH64 , Y, 0, 0,48 , 32,47 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G2_NC , STATIC , AARCH64 , Y, 0, 0,0 , 32,47 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G3 , STATIC , AARCH64 , Y, 0, 0,0 , 48,63 , Symbol::ABSOLUTE_REF , MOVW ) +// Above is from Table 4-7, Group relocations to create a 16-, 32-, 48-, or 64-bit unsigned data value or address inline. + +ARD(MOVW_SABS_G0 , STATIC , AARCH64 , Y, 0, 16,16 , 0,15 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_SABS_G1 , STATIC , AARCH64 , Y, 0, 32,32 , 16,31 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_SABS_G2 , STATIC , AARCH64 , Y, 0, 48,48 , 32,47 , Symbol::ABSOLUTE_REF , MOVW ) +// Above is from Table 4-8, Group relocations to create a 16, 32, 48, or 64 bit signed data or offset value inline. + ARD(LD_PREL_LO19 , STATIC , AARCH64 , Y, -1, 20,20 , 2,20 , Symbol::RELATIVE_REF , LDST ) ARD(ADR_PREL_LO21 , STATIC , AARCH64 , Y, -1, 20,20 , 0,20 , Symbol::RELATIVE_REF , ADR ) ARD(ADR_PREL_PG_HI21 , STATIC , AARCH64 , Y, -1, 32,32 , 12,32 , Symbol::RELATIVE_REF , ADRP ) diff -rup ../binutils-2.27/gold/aarch64-reloc-property.cc gold/aarch64-reloc-property.cc --- ../binutils-2.27/gold/aarch64-reloc-property.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/aarch64-reloc-property.cc 2016-11-03 15:05:32.000000000 +0000 @@ -59,17 +59,51 @@ template<> bool rvalue_checkup<0, 0>(int64_t) { return true; } +namespace +{ + template -uint64_t -rvalue_bit_select(uint64_t x) +class Rvalue_bit_select_impl { - if (U == 63) return x >> L; - return (x & (((uint64_t)1 << (U+1)) - 1)) >> L; -} +public: + static uint64_t + calc(uint64_t x) + { + return (x & ((1ULL << (U+1)) - 1)) >> L; + } +}; + +template +class Rvalue_bit_select_impl +{ +public: + static uint64_t + calc(uint64_t x) + { + return x >> L; + } +}; +// By our convention, L=U=0 means that the whole value should be retrieved. template<> +class Rvalue_bit_select_impl<0, 0> +{ +public: + static uint64_t + calc(uint64_t x) + { + return x; + } +}; + +} // End anonymous namespace. + +template uint64_t -rvalue_bit_select<0, 0>(uint64_t x) { return x; } +rvalue_bit_select(uint64_t x) +{ + return Rvalue_bit_select_impl::calc(x); +} AArch64_reloc_property::AArch64_reloc_property( unsigned int code, diff -rup ../binutils-2.27/gold/arm.cc gold/arm.cc --- ../binutils-2.27/gold/arm.cc 2016-09-26 11:22:18.629810833 +0100 +++ gold/arm.cc 2016-11-03 15:05:33.000000000 +0000 @@ -2128,8 +2128,36 @@ class Target_arm : public Sized_target<3 stub_tables_(), stub_factory_(Stub_factory::get_instance()), should_force_pic_veneer_(false), arm_input_section_map_(), attributes_section_data_(NULL), - fix_cortex_a8_(false), cortex_a8_relocs_info_() - { } + fix_cortex_a8_(false), cortex_a8_relocs_info_(), + target1_reloc_(elfcpp::R_ARM_ABS32), + // This can be any reloc type but usually is R_ARM_GOT_PREL. + target2_reloc_(elfcpp::R_ARM_GOT_PREL) + { + if (parameters->options().user_set_target1_rel()) + { + // FIXME: This is not strictly compatible with ld, which allows both + // --target1-abs and --target-rel to be given. + if (parameters->options().user_set_target1_abs()) + gold_error(_("Cannot use both --target1-abs and --target1-rel.")); + else + this->target1_reloc_ = elfcpp::R_ARM_REL32; + } + // We don't need to handle --target1-abs because target1_reloc_ is set + // to elfcpp::R_ARM_ABS32 in the member initializer list. + + if (parameters->options().user_set_target2()) + { + const char* target2 = parameters->options().target2(); + if (strcmp(target2, "rel") == 0) + this->target2_reloc_ = elfcpp::R_ARM_REL32; + else if (strcmp(target2, "abs") == 0) + this->target2_reloc_ = elfcpp::R_ARM_ABS32; + else if (strcmp(target2, "got-rel") == 0) + this->target2_reloc_ = elfcpp::R_ARM_GOT_PREL; + else + gold_unreachable(); + } + } // Whether we force PCI branch veneers. bool @@ -2391,8 +2419,8 @@ class Target_arm : public Sized_target<3 rel_irelative_section(Layout*); // Map platform-specific reloc types - static unsigned int - get_real_reloc_type(unsigned int r_type); + unsigned int + get_real_reloc_type(unsigned int r_type) const; // // Methods to support stub-generations. @@ -3002,6 +3030,11 @@ class Target_arm : public Sized_target<3 bool fix_cortex_a8_; // Map addresses to relocs for Cortex-A8 erratum. Cortex_a8_relocs_info cortex_a8_relocs_info_; + // What R_ARM_TARGET1 maps to. It can be R_ARM_REL32 or R_ARM_ABS32. + unsigned int target1_reloc_; + // What R_ARM_TARGET2 maps to. It should be one of R_ARM_REL32, R_ARM_ABS32 + // and R_ARM_GOT_PREL. + unsigned int target2_reloc_; }; template @@ -6639,6 +6672,80 @@ Arm_relobj::do_relocate_sect section_address, section_size); } + // BE8 swapping + if (parameters->options().be8()) + { + section_size_type span_start, span_end; + elfcpp::Shdr<32, big_endian> + shdr(pshdrs + i * elfcpp::Elf_sizes<32>::shdr_size); + Mapping_symbol_position section_start(i, 0); + typename Mapping_symbols_info::const_iterator p = + this->mapping_symbols_info_.lower_bound(section_start); + unsigned char* view = (*pviews)[i].view; + Arm_address view_address = (*pviews)[i].address; + section_size_type view_size = (*pviews)[i].view_size; + while (p != this->mapping_symbols_info_.end() + && p->first.first == i) + { + typename Mapping_symbols_info::const_iterator next = + this->mapping_symbols_info_.upper_bound(p->first); + + // Only swap arm or thumb code. + if ((p->second == 'a') || (p->second == 't')) + { + Output_section* os = this->output_section(i); + gold_assert(os != NULL); + Arm_address section_address = + this->simple_input_section_output_address(i, os); + span_start = convert_to_section_size_type(p->first.second); + if (next != this->mapping_symbols_info_.end() + && next->first.first == i) + span_end = + convert_to_section_size_type(next->first.second); + else + span_end = + convert_to_section_size_type(shdr.get_sh_size()); + unsigned char* section_view = + view + (section_address - view_address); + uint64_t section_size = this->section_size(i); + + gold_assert(section_address >= view_address + && ((section_address + section_size) + <= (view_address + view_size))); + + // Set Output view for swapping + unsigned char *oview = section_view + span_start; + unsigned int index = 0; + if (p->second == 'a') + { + while (index + 3 < (span_end - span_start)) + { + typedef typename elfcpp::Swap<32, big_endian> + ::Valtype Valtype; + Valtype* wv = + reinterpret_cast(oview+index); + uint32_t val = elfcpp::Swap<32, false>::readval(wv); + elfcpp::Swap<32, true>::writeval(wv, val); + index += 4; + } + } + else if (p->second == 't') + { + while (index + 1 < (span_end - span_start)) + { + typedef typename elfcpp::Swap<16, big_endian> + ::Valtype Valtype; + Valtype* wv = + reinterpret_cast(oview+index); + uint16_t val = elfcpp::Swap<16, false>::readval(wv); + elfcpp::Swap<16, true>::writeval(wv, val); + index += 2; + } + } + } + p = next; + } + } } } @@ -7785,7 +7892,18 @@ Output_data_plt_arm_standard const size_t num_first_plt_words = (sizeof(first_plt_entry) / sizeof(first_plt_entry[0])); for (size_t i = 0; i < num_first_plt_words - 1; i++) - elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]); + { + if (parameters->options().be8()) + { + elfcpp::Swap<32, false>::writeval(pov + i * 4, + first_plt_entry[i]); + } + else + { + elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, + first_plt_entry[i]); + } + } // Last word in first PLT entry is &GOT[0] - . elfcpp::Swap<32, big_endian>::writeval(pov + 16, got_address - (plt_address + 16)); @@ -7846,11 +7964,21 @@ Output_data_plt_arm_short::d gold_error(_("PLT offset too large, try linking with --long-plt")); uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff); - elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0); uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff); - elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1); uint32_t plt_insn2 = plt_entry[2] | (offset & 0xfff); - elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); + + if (parameters->options().be8()) + { + elfcpp::Swap<32, false>::writeval(pov, plt_insn0); + elfcpp::Swap<32, false>::writeval(pov + 4, plt_insn1); + elfcpp::Swap<32, false>::writeval(pov + 8, plt_insn2); + } + else + { + elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0); + elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1); + elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); + } } // This class generates long (16-byte) entries, for arbitrary displacements. @@ -7906,13 +8034,24 @@ Output_data_plt_arm_long::do - (plt_address + plt_offset + 8)); uint32_t plt_insn0 = plt_entry[0] | (offset >> 28); - elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0); uint32_t plt_insn1 = plt_entry[1] | ((offset >> 20) & 0xff); - elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1); uint32_t plt_insn2 = plt_entry[2] | ((offset >> 12) & 0xff); - elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); uint32_t plt_insn3 = plt_entry[3] | (offset & 0xfff); - elfcpp::Swap<32, big_endian>::writeval(pov + 12, plt_insn3); + + if (parameters->options().be8()) + { + elfcpp::Swap<32, false>::writeval(pov, plt_insn0); + elfcpp::Swap<32, false>::writeval(pov + 4, plt_insn1); + elfcpp::Swap<32, false>::writeval(pov + 8, plt_insn2); + elfcpp::Swap<32, false>::writeval(pov + 12, plt_insn3); + } + else + { + elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0); + elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1); + elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); + elfcpp::Swap<32, big_endian>::writeval(pov + 12, plt_insn3); + } } // Write out the PLT. This uses the hand-coded instructions above, @@ -8414,7 +8553,7 @@ Target_arm::Scan::local(Symb if (is_discarded) return; - r_type = get_real_reloc_type(r_type); + r_type = target->get_real_reloc_type(r_type); // A local STT_GNU_IFUNC symbol may require a PLT entry. bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC; @@ -8820,7 +8959,7 @@ Target_arm::Scan::global(Sym && this->reloc_needs_plt_for_ifunc(object, r_type)) target->make_plt_entry(symtab, layout, gsym); - r_type = get_real_reloc_type(r_type); + r_type = target->get_real_reloc_type(r_type); switch (r_type) { case elfcpp::R_ARM_NONE: @@ -9446,7 +9585,7 @@ Target_arm::Relocate::reloca const elfcpp::Rel<32, big_endian> rel(preloc); unsigned int r_type = elfcpp::elf_r_type<32>(rel.get_r_info()); - r_type = get_real_reloc_type(r_type); + r_type = target->get_real_reloc_type(r_type); const Arm_reloc_property* reloc_property = arm_reloc_property_table->get_implemented_static_reloc_property(r_type); if (reloc_property == NULL) @@ -10156,7 +10295,9 @@ Target_arm::Classify_reloc:: unsigned int r_type, Relobj* object) { - r_type = get_real_reloc_type(r_type); + Target_arm* arm_target = + Target_arm::default_target(); + r_type = arm_target->get_real_reloc_type(r_type); const Arm_reloc_property* arp = arm_reloc_property_table->get_implemented_static_reloc_property(r_type); if (arp != NULL) @@ -10580,17 +10721,15 @@ Target_arm::do_dynsym_value( // template unsigned int -Target_arm::get_real_reloc_type(unsigned int r_type) +Target_arm::get_real_reloc_type(unsigned int r_type) const { switch (r_type) { case elfcpp::R_ARM_TARGET1: - // This is either R_ARM_ABS32 or R_ARM_REL32; - return elfcpp::R_ARM_ABS32; + return this->target1_reloc_; case elfcpp::R_ARM_TARGET2: - // This can be any reloc type but usually is R_ARM_GOT_PREL - return elfcpp::R_ARM_GOT_PREL; + return this->target2_reloc_; default: return r_type; @@ -10683,7 +10822,14 @@ Target_arm::do_adjust_elf_he e_ident[elfcpp::EI_OSABI] = 0; e_ident[elfcpp::EI_ABIVERSION] = 0; - // FIXME: Do EF_ARM_BE8 adjustment. + // Do EF_ARM_BE8 adjustment. + if (parameters->options().be8() && !big_endian) + gold_error("BE8 images only valid in big-endian mode."); + if (parameters->options().be8()) + { + flags |= elfcpp::EF_ARM_BE8; + this->set_processor_specific_flags(flags); + } // If we're working in EABI_VER5, set the hard/soft float ABI flags // as appropriate. diff -rup ../binutils-2.27/gold/configure gold/configure --- ../binutils-2.27/gold/configure 2016-09-26 11:22:19.027813254 +0100 +++ gold/configure 2016-11-03 14:38:22.000000000 +0000 @@ -609,6 +609,7 @@ GOLD_LDFLAGS WARN_CXXFLAGS WARN_WRITE_STRINGS NO_WERROR +WARN_CFLAGS_FOR_BUILD WARN_CFLAGS IFUNC_STATIC_FALSE IFUNC_STATIC_TRUE @@ -6723,8 +6724,12 @@ fi # Set the 'development' global. . $srcdir/../bfd/development.sh +# Set acp_cpp_for_build variable +ac_cpp_for_build="$CC_FOR_BUILD -E $CPPFLAGS_FOR_BUILD" + # Default set of GCC warnings to enable. GCC_WARN_CFLAGS="-W -Wall -Wstrict-prototypes -Wmissing-prototypes" +GCC_WARN_CFLAGS_FOR_BUILD="-W -Wall -Wstrict-prototypes -Wmissing-prototypes" # Add -Wshadow if the compiler is a sufficiently recent version of GCC. cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6769,6 +6774,36 @@ fi rm -f conftest* +# Verify CC_FOR_BUILD to be compatible with waring flags + +# Add -Wshadow if the compiler is a sufficiently recent version of GCC. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +__GNUC__ +_ACEOF +if (eval "$ac_cpp_for_build conftest.$ac_ext") 2>&5 | + $EGREP "^[0-3]$" >/dev/null 2>&1; then : + +else + GCC_WARN_CFLAGS_FOR_BUILD="$GCC_WARN_CFLAGS_FOR_BUILD -Wshadow" +fi +rm -f conftest* + + +# Add -Wstack-usage if the compiler is a sufficiently recent version of GCC. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +__GNUC__ +_ACEOF +if (eval "$ac_cpp_for_build conftest.$ac_ext") 2>&5 | + $EGREP "^[0-4]$" >/dev/null 2>&1; then : + +else + GCC_WARN_CFLAGS_FOR_BUILD="$GCC_WARN_CFLAGS_FOR_BUILD -Wstack-usage=262144" +fi +rm -f conftest* + + # Check whether --enable-werror was given. if test "${enable_werror+set}" = set; then : enableval=$enable_werror; case "${enableval}" in @@ -6784,6 +6819,7 @@ case "${host}" in *-*-mingw32*) if test "${GCC}" = yes -a -z "${ERROR_ON_WARNING}" ; then GCC_WARN_CFLAGS="$GCC_WARN_CFLAGS -Wno-format" + GCC_WARN_CFLAGS_FOR_BUILD="$GCC_WARN_CFLAGS_FOR_BUILD -Wno-format" fi ;; *) ;; @@ -6797,25 +6833,32 @@ fi NO_WERROR= if test "${ERROR_ON_WARNING}" = yes ; then GCC_WARN_CFLAGS="$GCC_WARN_CFLAGS -Werror" + GCC_WARN_CFLAGS_FOR_BUILD="$GCC_WARN_CFLAGS_FOR_BUILD -Werror" NO_WERROR="-Wno-error" fi if test "${GCC}" = yes ; then WARN_CFLAGS="${GCC_WARN_CFLAGS}" + WARN_CFLAGS_FOR_BUILD="${GCC_WARN_CFLAGS_FOR_BUILD}" fi # Check whether --enable-build-warnings was given. if test "${enable_build_warnings+set}" = set; then : enableval=$enable_build_warnings; case "${enableval}" in - yes) WARN_CFLAGS="${GCC_WARN_CFLAGS}";; + yes) WARN_CFLAGS="${GCC_WARN_CFLAGS}" + WARN_CFLAGS_FOR_BUILD="${GCC_WARN_CFLAGS_FOR_BUILD}";; no) if test "${GCC}" = yes ; then WARN_CFLAGS="-w" + WARN_CFLAGS_FOR_BUILD="-w" fi;; ,*) t=`echo "${enableval}" | sed -e "s/,/ /g"` - WARN_CFLAGS="${GCC_WARN_CFLAGS} ${t}";; + WARN_CFLAGS="${GCC_WARN_CFLAGS} ${t}" + WARN_CFLAGS_FOR_BUILD="${GCC_WARN_CFLAGS_FOR_BUILD} ${t}";; *,) t=`echo "${enableval}" | sed -e "s/,/ /g"` - WARN_CFLAGS="${t} ${GCC_WARN_CFLAGS}";; - *) WARN_CFLAGS=`echo "${enableval}" | sed -e "s/,/ /g"`;; + WARN_CFLAGS="${t} ${GCC_WARN_CFLAGS}" + WARN_CFLAGS_FOR_BUILD="${t} ${GCC_WARN_CFLAGS_FOR_BUILD}";; + *) WARN_CFLAGS=`echo "${enableval}" | sed -e "s/,/ /g"` + WARN_CFLAGS_FOR_BUILD=`echo "${enableval}" | sed -e "s/,/ /g"`;; esac fi diff -rup ../binutils-2.27/gold/debug.h gold/debug.h --- ../binutils-2.27/gold/debug.h 2016-08-03 08:36:53.000000000 +0100 +++ gold/debug.h 2016-11-03 15:05:05.000000000 +0000 @@ -39,10 +39,11 @@ const int DEBUG_FILES = 0x4; const int DEBUG_RELAXATION = 0x8; const int DEBUG_INCREMENTAL = 0x10; const int DEBUG_LOCATION = 0x20; +const int DEBUG_TARGET = 0x40; const int DEBUG_ALL = (DEBUG_TASK | DEBUG_SCRIPT | DEBUG_FILES | DEBUG_RELAXATION | DEBUG_INCREMENTAL - | DEBUG_LOCATION); + | DEBUG_LOCATION | DEBUG_TARGET); // Convert a debug string to the appropriate enum. inline int @@ -57,6 +58,7 @@ debug_string_to_enum(const char* arg) { "relaxation", DEBUG_RELAXATION }, { "incremental", DEBUG_INCREMENTAL }, { "location", DEBUG_LOCATION }, + { "target", DEBUG_TARGET }, { "all", DEBUG_ALL } }; @@ -70,11 +72,11 @@ debug_string_to_enum(const char* arg) // Print a debug message if TYPE is enabled. This is a macro so that // we only evaluate the arguments if necessary. -#define gold_debug(TYPE, FORMAT, ...) \ +#define gold_debug(TYPE, ...) \ do \ { \ if (is_debugging_enabled(TYPE)) \ - parameters->errors()->debug(FORMAT, __VA_ARGS__); \ + parameters->errors()->debug(__VA_ARGS__); \ } \ while (0) diff -rup ../binutils-2.27/gold/i386.cc gold/i386.cc --- ../binutils-2.27/gold/i386.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/i386.cc 2016-11-03 15:05:40.000000000 +0000 @@ -2794,8 +2794,11 @@ Target_i386::Relocate::relocate(const Re && r_type != elfcpp::R_386_PC32) || gsym == NULL || strcmp(gsym->name(), "___tls_get_addr") != 0) - gold_error_at_location(relinfo, relnum, rel.get_r_offset(), - _("missing expected TLS relocation")); + { + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("missing expected TLS relocation")); + this->skip_call_tls_get_addr_ = false; + } else { this->skip_call_tls_get_addr_ = false; diff -rup ../binutils-2.27/gold/icf.cc gold/icf.cc --- ../binutils-2.27/gold/icf.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/icf.cc 2016-11-03 15:05:40.000000000 +0000 @@ -590,6 +590,7 @@ match_sections(unsigned int iteration_nu std::vector* num_tracked_relocs, std::vector* kept_section_id, const std::vector& id_section, + const std::vector& section_addraligns, std::vector* is_secn_or_group_unique, std::vector* section_contents) { @@ -630,13 +631,7 @@ match_sections(unsigned int iteration_nu { if ((*kept_section_id)[i] != i) { - // This section is already folded into something. See - // if it should point to a different kept section. - unsigned int kept_section = (*kept_section_id)[i]; - if (kept_section != (*kept_section_id)[kept_section]) - { - (*kept_section_id)[i] = (*kept_section_id)[kept_section]; - } + // This section is already folded into something. continue; } this_secn_contents = get_section_contents(false, secn, i, NULL, @@ -671,7 +666,25 @@ match_sections(unsigned int iteration_nu this_secn_contents.c_str(), this_secn_contents.length()) != 0) continue; - (*kept_section_id)[i] = kept_section; + + // Check section alignment here. + // The section with the larger alignment requirement + // should be kept. We assume alignment can only be + // zero or postive integral powers of two. + uint64_t align_i = section_addraligns[i]; + uint64_t align_kept = section_addraligns[kept_section]; + if (align_i <= align_kept) + { + (*kept_section_id)[i] = kept_section; + } + else + { + (*kept_section_id)[kept_section] = i; + it->second = i; + full_section_contents[kept_section].swap( + full_section_contents[i]); + } + converged = false; break; } @@ -688,6 +701,26 @@ match_sections(unsigned int iteration_nu (*is_secn_or_group_unique)[i] = true; } + // If a section was folded into another section that was later folded + // again then the former has to be updated. + for (unsigned int i = 0; i < id_section.size(); i++) + { + // Find the end of the folding chain + unsigned int kept = i; + while ((*kept_section_id)[kept] != kept) + { + kept = (*kept_section_id)[kept]; + } + // Update every element of the chain + unsigned int current = i; + while ((*kept_section_id)[current] != kept) + { + unsigned int next = (*kept_section_id)[current]; + (*kept_section_id)[current] = kept; + current = next; + } + } + return converged; } @@ -719,6 +752,7 @@ Icf::find_identical_sections(const Input { unsigned int section_num = 0; std::vector num_tracked_relocs; + std::vector section_addraligns; std::vector is_secn_or_group_unique; std::vector section_contents; const Target& target = parameters->target(); @@ -759,6 +793,7 @@ Icf::find_identical_sections(const Input this->section_id_[Section_id(*p, i)] = section_num; this->kept_section_id_.push_back(section_num); num_tracked_relocs.push_back(0); + section_addraligns.push_back((*p)->section_addralign(i)); is_secn_or_group_unique.push_back(false); section_contents.push_back(""); section_num++; @@ -779,8 +814,8 @@ Icf::find_identical_sections(const Input num_iterations++; converged = match_sections(num_iterations, symtab, &num_tracked_relocs, &this->kept_section_id_, - this->id_section_, &is_secn_or_group_unique, - §ion_contents); + this->id_section_, section_addraligns, + &is_secn_or_group_unique, §ion_contents); } if (parameters->options().print_icf_sections()) diff -rup ../binutils-2.27/gold/layout.cc gold/layout.cc --- ../binutils-2.27/gold/layout.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/layout.cc 2016-11-03 15:05:42.000000000 +0000 @@ -2135,7 +2135,7 @@ void Layout::create_notes() { this->create_gold_note(); - this->create_executable_stack_info(); + this->create_stack_segment(); this->create_build_id(); } @@ -2785,7 +2785,7 @@ Layout::finalize(const Input_objects* in if (load_seg != NULL) ehdr_start->set_output_segment(load_seg, Symbol::SEGMENT_START); else - ehdr_start->set_undefined(); + ehdr_start->set_undefined(); } // Set the file offsets of all the non-data sections we've seen so @@ -2985,25 +2985,29 @@ Layout::create_gold_note() // executable. Otherwise, if at least one input file a // .note.GNU-stack section, and some input file has no .note.GNU-stack // section, we use the target default for whether the stack should be -// executable. Otherwise, we don't generate a stack note. When -// generating a object file, we create a .note.GNU-stack section with -// the appropriate marking. When generating an executable or shared -// library, we create a PT_GNU_STACK segment. +// executable. If -z stack-size was used to set a p_memsz value for +// PT_GNU_STACK, we generate the segment regardless. Otherwise, we +// don't generate a stack note. When generating a object file, we +// create a .note.GNU-stack section with the appropriate marking. +// When generating an executable or shared library, we create a +// PT_GNU_STACK segment. void -Layout::create_executable_stack_info() +Layout::create_stack_segment() { bool is_stack_executable; if (parameters->options().is_execstack_set()) { is_stack_executable = parameters->options().is_stack_executable(); if (!is_stack_executable - && this->input_requires_executable_stack_ - && parameters->options().warn_execstack()) + && this->input_requires_executable_stack_ + && parameters->options().warn_execstack()) gold_warning(_("one or more inputs require executable stack, " - "but -z noexecstack was given")); + "but -z noexecstack was given")); } - else if (!this->input_with_gnu_stack_note_) + else if (!this->input_with_gnu_stack_note_ + && (!parameters->options().user_set_stack_size() + || parameters->options().relocatable())) return; else { @@ -3032,7 +3036,12 @@ Layout::create_executable_stack_info() int flags = elfcpp::PF_R | elfcpp::PF_W; if (is_stack_executable) flags |= elfcpp::PF_X; - this->make_output_segment(elfcpp::PT_GNU_STACK, flags); + Output_segment* seg = + this->make_output_segment(elfcpp::PT_GNU_STACK, flags); + seg->set_size(parameters->options().stack_size()); + // BFD lets targets override this default alignment, but the only + // targets that do so are ones that Gold does not support so far. + seg->set_minimum_p_align(16); } } @@ -3718,7 +3727,9 @@ Layout::set_segment_offsets(const Target p != this->segment_list_.end(); ++p) { - if ((*p)->type() != elfcpp::PT_LOAD) + // PT_GNU_STACK was set up correctly when it was created. + if ((*p)->type() != elfcpp::PT_LOAD + && (*p)->type() != elfcpp::PT_GNU_STACK) (*p)->set_offset((*p)->type() == elfcpp::PT_GNU_RELRO ? increase_relro : 0); diff -rup ../binutils-2.27/gold/layout.h gold/layout.h --- ../binutils-2.27/gold/layout.h 2016-08-03 08:36:53.000000000 +0100 +++ gold/layout.h 2016-11-03 15:05:12.000000000 +0000 @@ -1037,9 +1037,9 @@ class Layout void create_gold_note(); - // Record whether the stack must be executable. + // Record whether the stack must be executable, and a user-supplied size. void - create_executable_stack_info(); + create_stack_segment(); // Create a build ID note if needed. void diff -rup ../binutils-2.27/gold/Makefile.in gold/Makefile.in --- ../binutils-2.27/gold/Makefile.in 2016-08-03 08:36:53.000000000 +0100 +++ gold/Makefile.in 2016-11-03 14:38:22.000000000 +0000 @@ -87,8 +87,8 @@ subdir = . DIST_COMMON = NEWS README ChangeLog $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(srcdir)/config.in \ - $(srcdir)/../mkinstalldirs $(top_srcdir)/po/Make-in \ - ftruncate.c pread.c mremap.c ffsll.c yyscript.h yyscript.c \ + $(srcdir)/../mkinstalldirs $(top_srcdir)/po/Make-in ffsll.c \ + mremap.c ftruncate.c pread.c yyscript.h yyscript.c \ $(srcdir)/../depcomp $(srcdir)/../ylwrap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ @@ -409,6 +409,7 @@ TARGETOBJS = @TARGETOBJS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ +WARN_CFLAGS_FOR_BUILD = @WARN_CFLAGS_FOR_BUILD@ WARN_CXXFLAGS = @WARN_CXXFLAGS@ WARN_WRITE_STRINGS = @WARN_WRITE_STRINGS@ XGETTEXT = @XGETTEXT@ diff -rup ../binutils-2.27/gold/options.h gold/options.h --- ../binutils-2.27/gold/options.h 2016-08-03 08:36:53.000000000 +0100 +++ gold/options.h 2016-11-03 15:05:13.000000000 +0000 @@ -647,7 +647,7 @@ class General_options DEFINE_bool(apply_dynamic_relocs, options::TWO_DASHES, '\0', true, N_("Apply link-time values for dynamic relocations (default)"), N_("(aarch64 only) Do not apply link-time values " - "for dynamic relocations")); + "for dynamic relocations")); DEFINE_bool(as_needed, options::TWO_DASHES, '\0', false, N_("Only set DT_NEEDED for shared libraries if used"), @@ -674,6 +674,9 @@ class General_options DEFINE_bool_alias(dn, Bdynamic, options::ONE_DASH, '\0', N_("alias for -Bstatic"), NULL, true); + DEFINE_bool(be8,options::TWO_DASHES, '\0', false, + N_("Output BE8 format image"), NULL); + DEFINE_bool(Bgroup, options::ONE_DASH, '\0', false, N_("Use group name lookup rules for shared library"), NULL); @@ -1152,6 +1155,17 @@ class General_options DEFINE_string(sysroot, options::TWO_DASHES, '\0', "", N_("Set target system root directory"), N_("DIR")); + DEFINE_bool(target1_rel, options::TWO_DASHES, '\0', false, + N_("(ARM only) Force R_ARM_TARGET1 type to R_ARM_REL32"), + NULL); + DEFINE_bool(target1_abs, options::TWO_DASHES, '\0', false, + N_("(ARM only) Force R_ARM_TARGET1 type to R_ARM_ABS32"), + NULL); + DEFINE_enum(target2, options::TWO_DASHES, '\0', NULL, + N_("(ARM only) Set R_ARM_TARGET2 relocation type"), + N_("[rel, abs, got-rel"), + {"rel", "abs", "got-rel"}); + DEFINE_bool(trace, options::TWO_DASHES, 't', false, N_("Print the name of each input file"), NULL); @@ -1293,7 +1307,7 @@ class General_options N_("Mark output as requiring executable stack"), NULL); DEFINE_bool(global, options::DASH_Z, '\0', false, N_("Make symbols in DSO available for subsequently loaded " - "objects"), NULL); + "objects"), NULL); DEFINE_bool(initfirst, options::DASH_Z, '\0', false, N_("Mark DSO to be initialized first at runtime"), NULL); @@ -1339,6 +1353,8 @@ class General_options DEFINE_bool(relro, options::DASH_Z, '\0', DEFAULT_LD_Z_RELRO, N_("Where possible mark variables read-only after relocation"), N_("Don't mark variables read-only after relocation")); + DEFINE_uint64(stack_size, options::DASH_Z, '\0', 0, + N_("Set PT_GNU_STACK segment p_memsz to SIZE"), N_("SIZE")); DEFINE_bool(text, options::DASH_Z, '\0', false, N_("Do not permit relocations in read-only segments"), N_("Permit relocations in read-only segments (default)")); diff -rup ../binutils-2.27/gold/output.cc gold/output.cc --- ../binutils-2.27/gold/output.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/output.cc 2016-11-03 15:05:44.000000000 +0000 @@ -4398,7 +4398,7 @@ Output_segment::set_section_addresses(co this->offset_ = orig_off; off_t off = 0; - uint64_t ret; + uint64_t ret = 0; for (int i = 0; i < static_cast(ORDER_MAX); ++i) { if (i == static_cast(ORDER_RELRO_LAST)) diff -rup ../binutils-2.27/gold/output.h gold/output.h --- ../binutils-2.27/gold/output.h 2016-08-03 08:36:53.000000000 +0100 +++ gold/output.h 2016-11-03 15:05:14.000000000 +0000 @@ -2499,7 +2499,7 @@ class Output_data_got : public Output_da // entry. bool add_local(Relobj* object, unsigned int sym_index, unsigned int got_type, - uint64_t addend); + uint64_t addend); // Like add_local, but use the PLT offset of the local symbol if it // has one. @@ -2643,7 +2643,7 @@ class Output_data_got : public Output_da // Create a local symbol entry plus addend. Got_entry(Relobj* object, unsigned int local_sym_index, - bool use_plt_or_tls_offset, uint64_t addend) + bool use_plt_or_tls_offset, uint64_t addend) : local_sym_index_(local_sym_index), use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(addend) { @@ -4796,6 +4796,13 @@ class Output_segment this->min_p_align_ = align; } + // Set the memory size of this segment. + void + set_size(uint64_t size) + { + this->memsz_ = size; + } + // Set the offset of this segment based on the section. This should // only be called for a non-PT_LOAD segment. void diff -rup ../binutils-2.27/gold/powerpc.cc gold/powerpc.cc --- ../binutils-2.27/gold/powerpc.cc 2016-09-26 11:22:18.717811369 +0100 +++ gold/powerpc.cc 2016-11-03 15:05:45.000000000 +0000 @@ -2439,9 +2439,8 @@ class Stub_control // the stubbed branches. Stub_control(int32_t size, bool no_size_errors) : state_(NO_GROUP), stub_group_size_(abs(size)), - stub14_group_size_(abs(size) >> 10), stubs_always_before_branch_(size < 0), - suppress_size_errors_(no_size_errors), + suppress_size_errors_(no_size_errors), group_size_(0), group_end_addr_(0), owner_(NULL), output_section_(NULL) { } @@ -2479,24 +2478,28 @@ class Stub_control State state_; uint32_t stub_group_size_; - uint32_t stub14_group_size_; bool stubs_always_before_branch_; bool suppress_size_errors_; + // Current max size of group. Starts at stub_group_size_ but is + // reduced to stub_group_size_/1024 on seeing a section with + // external conditional branches. + uint32_t group_size_; uint64_t group_end_addr_; + // owner_ and output_section_ specify the section to which stubs are + // attached. The stubs are placed at the end of this section. const Output_section::Input_section* owner_; Output_section* output_section_; }; // Return true iff input section can be handled by current stub -// group. +// group. Sections are presented to this function in reverse order, +// so the first section is the tail of the group. bool Stub_control::can_add_to_stub_group(Output_section* o, const Output_section::Input_section* i, bool has14) { - uint32_t group_size - = has14 ? this->stub14_group_size_ : this->stub_group_size_; bool whole_sec = o->order() == ORDER_INIT || o->order() == ORDER_FINI; uint64_t this_size; uint64_t start_addr = o->address(); @@ -2510,46 +2513,90 @@ Stub_control::can_add_to_stub_group(Outp start_addr += i->relobj()->output_section_offset(i->shndx()); this_size = i->data_size(); } - uint64_t end_addr = start_addr + this_size; - bool toobig = this_size > group_size; - if (toobig && !this->suppress_size_errors_) + uint32_t group_size = this->stub_group_size_; + if (has14) + this->group_size_ = group_size = group_size >> 10; + + if (this_size > group_size && !this->suppress_size_errors_) gold_warning(_("%s:%s exceeds group size"), i->relobj()->name().c_str(), i->relobj()->section_name(i->shndx()).c_str()); - if (this->state_ != HAS_STUB_SECTION - && (!whole_sec || this->output_section_ != o) - && (this->state_ == NO_GROUP - || this->group_end_addr_ - end_addr < group_size)) - { - this->owner_ = i; - this->output_section_ = o; - } - - if (this->state_ == NO_GROUP) - { - this->state_ = FINDING_STUB_SECTION; - this->group_end_addr_ = end_addr; - } - else if (this->group_end_addr_ - start_addr < group_size) - ; - // Adding this section would make the group larger than GROUP_SIZE. - else if (this->state_ == FINDING_STUB_SECTION - && !this->stubs_always_before_branch_ - && !toobig) - { - // But wait, there's more! Input sections up to GROUP_SIZE - // bytes before the stub table can be handled by it too. - this->state_ = HAS_STUB_SECTION; - this->group_end_addr_ = end_addr; + gold_debug(DEBUG_TARGET, "maybe add%s %s:%s size=%#llx total=%#llx", + has14 ? " 14bit" : "", + i->relobj()->name().c_str(), + i->relobj()->section_name(i->shndx()).c_str(), + (long long) this_size, + (long long) this->group_end_addr_ - start_addr); + + uint64_t end_addr = start_addr + this_size; + if (this->state_ == HAS_STUB_SECTION) + { + // Can we add this section, which is before the stubs, to the + // group? + if (this->group_end_addr_ - start_addr <= this->group_size_) + return true; } else { - this->state_ = NO_GROUP; - return false; + // Stubs are added at the end of "owner_". + // The current section can always be the stub owner, except when + // whole_sec is true and the current section isn't the last of + // the pasted sections. (This restriction for the whole_sec + // case is just to simplify the corner case mentioned in + // group_sections.) + // Note that "owner_" itself is not necessarily part of the + // group of sections served by these stubs! + if (!whole_sec || this->output_section_ != o) + { + this->owner_ = i; + this->output_section_ = o; + } + + if (this->state_ == FINDING_STUB_SECTION) + { + if (this->group_end_addr_ - start_addr <= this->group_size_) + return true; + // The group after the stubs has reached maximum size. + // Now see about adding sections before the stubs to the + // group. If the current section has a 14-bit branch and + // the group after the stubs exceeds group_size_ (because + // they didn't have 14-bit branches), don't add sections + // before the stubs: The size of stubs for such a large + // group may exceed the reach of a 14-bit branch. + if (!this->stubs_always_before_branch_ + && this_size <= this->group_size_ + && this->group_end_addr_ - end_addr <= this->group_size_) + { + gold_debug(DEBUG_TARGET, "adding before stubs"); + this->state_ = HAS_STUB_SECTION; + this->group_end_addr_ = end_addr; + return true; + } + } + else if (this->state_ == NO_GROUP) + { + // Only here on very first use of Stub_control + this->state_ = FINDING_STUB_SECTION; + this->group_size_ = group_size; + this->group_end_addr_ = end_addr; + return true; + } + else + gold_unreachable(); } - return true; + + gold_debug(DEBUG_TARGET, "nope, didn't fit\n"); + + // The section fails to fit in the current group. Set up a few + // things for the next group. owner_ and output_section_ will be + // set later after we've retrieved those values for the current + // group. + this->state_ = FINDING_STUB_SECTION; + this->group_size_ = group_size; + this->group_end_addr_ = end_addr; + return false; } // Look over all the input sections, deciding where to place stubs. @@ -2887,7 +2934,7 @@ Target_powerpc::do_rel } this->stub_tables_.clear(); this->stub_group_size_ = this->stub_group_size_ / 4 * 3; - gold_info(_("%s: stub group size is too large; retrying with %d"), + gold_info(_("%s: stub group size is too large; retrying with %#x"), program_name, this->stub_group_size_); this->group_sections(layout, task, true); } @@ -2982,7 +3029,13 @@ Target_powerpc::do_rel Stub_table* stub_table = static_cast*>( i->relaxed_input_section()); - off += stub_table->set_address_and_size(os, off); + Address stub_table_size = stub_table->set_address_and_size(os, off); + off += stub_table_size; + // After a few iterations, set current stub table size + // as min size threshold, so later stub tables can only + // grow in size. + if (pass >= 4) + stub_table->set_min_size_threshold(stub_table_size); } else off += i->data_size(); @@ -3634,8 +3687,8 @@ class Stub_table : public Output_relaxed targ_(targ), plt_call_stubs_(), long_branch_stubs_(), orig_data_size_(owner->current_data_size()), plt_size_(0), last_plt_size_(0), - branch_size_(0), last_branch_size_(0), eh_frame_added_(false), - need_save_res_(false) + branch_size_(0), last_branch_size_(0), min_size_threshold_(0), + eh_frame_added_(false), need_save_res_(false) { this->set_output_section(output_section); @@ -3726,6 +3779,11 @@ class Stub_table : public Output_relaxed off = align_address(off, this->stub_align()); // Include original section size and alignment padding in size my_size += off - start_off; + // Ensure new size is always larger than min size + // threshold. Alignment requirement is included in "my_size", so + // increase "my_size" does not invalidate alignment. + if (my_size < this->min_size_threshold_) + my_size = this->min_size_threshold_; this->reset_address_and_file_offset(); this->set_current_data_size(my_size); this->set_address_and_file_offset(os->address() + start_off, @@ -3751,6 +3809,9 @@ class Stub_table : public Output_relaxed plt_size() const { return this->plt_size_; } + void set_min_size_threshold(Address min_size) + { this->min_size_threshold_ = min_size; } + bool size_update() { @@ -4015,6 +4076,13 @@ class Stub_table : public Output_relaxed section_size_type orig_data_size_; // size of stubs section_size_type plt_size_, last_plt_size_, branch_size_, last_branch_size_; + // Some rare cases cause (PR/20529) fluctuation in stub table + // size, which leads to an endless relax loop. This is to be fixed + // by, after the first few iterations, allowing only increase of + // stub table size. This variable sets the minimal possible size of + // a stub table, it is zero for the first few iterations, then + // increases monotonically. + Address min_size_threshold_; // Whether .eh_frame info has been created for this stub section. bool eh_frame_added_; // Set if this stub group needs a copy of out-of-line register @@ -6024,7 +6092,7 @@ Target_powerpc::Scan:: ppc_object->set_opd_discard(reloc.get_r_offset()); break; } - // Fall thru + // Fall through. case elfcpp::R_PPC64_UADDR64: case elfcpp::R_POWERPC_ADDR32: case elfcpp::R_POWERPC_UADDR32: @@ -6131,7 +6199,7 @@ Target_powerpc::Scan:: || gsym->is_preemptible()))) target->make_plt_entry(symtab, layout, gsym); } - // Fall thru + // Fall through. case elfcpp::R_PPC64_REL64: case elfcpp::R_POWERPC_REL32: @@ -7521,6 +7589,7 @@ Target_powerpc::Reloca if (size != 64) // R_PPC_TLSGD, R_PPC_TLSLD, R_PPC_EMB_RELST_LO, R_PPC_EMB_RELST_HI break; + // Fall through. case elfcpp::R_POWERPC_TPREL16: case elfcpp::R_POWERPC_TPREL16_LO: case elfcpp::R_POWERPC_TPREL16_HI: @@ -7544,6 +7613,7 @@ Target_powerpc::Reloca // R_PPC_EMB_NADDR32, R_PPC_EMB_NADDR16, R_PPC_EMB_NADDR16_LO // R_PPC_EMB_NADDR16_HI, R_PPC_EMB_NADDR16_HA, R_PPC_EMB_SDAI16 break; + // Fall through. case elfcpp::R_POWERPC_DTPREL16: case elfcpp::R_POWERPC_DTPREL16_LO: case elfcpp::R_POWERPC_DTPREL16_HI: @@ -7572,6 +7642,7 @@ Target_powerpc::Reloca case elfcpp::R_POWERPC_ADDR14_BRTAKEN: case elfcpp::R_POWERPC_REL14_BRTAKEN: branch_bit = 1 << 21; + // Fall through. case elfcpp::R_POWERPC_ADDR14_BRNTAKEN: case elfcpp::R_POWERPC_REL14_BRNTAKEN: { @@ -7936,6 +8007,7 @@ Target_powerpc::Reloca maybe_dq_reloc = true; break; } + // Fall through. case elfcpp::R_POWERPC_ADDR16: case elfcpp::R_POWERPC_REL16: case elfcpp::R_PPC64_TOC16: @@ -7970,6 +8042,7 @@ Target_powerpc::Reloca if (size == 32) // R_PPC_EMB_MRKREF, R_PPC_EMB_RELST_LO, R_PPC_EMB_RELST_HA goto unsupp; + // Fall through. case elfcpp::R_POWERPC_ADDR16_HI: case elfcpp::R_POWERPC_REL16_HI: case elfcpp::R_PPC64_TOC16_HI: @@ -7990,6 +8063,7 @@ Target_powerpc::Reloca if (size == 32) // R_PPC_EMB_RELSEC16, R_PPC_EMB_RELST_HI, R_PPC_EMB_BIT_FLD goto unsupp; + // Fall through. case elfcpp::R_POWERPC_ADDR16_HA: case elfcpp::R_POWERPC_REL16_HA: case elfcpp::R_PPC64_TOC16_HA: @@ -8012,6 +8086,7 @@ Target_powerpc::Reloca if (size == 32) // R_PPC_EMB_NADDR16_LO goto unsupp; + // Fall through. case elfcpp::R_PPC64_ADDR16_HIGHER: case elfcpp::R_PPC64_TPREL16_HIGHER: Reloc::addr16_hi2(view, value); @@ -8021,6 +8096,7 @@ Target_powerpc::Reloca if (size == 32) // R_PPC_EMB_NADDR16_HI goto unsupp; + // Fall through. case elfcpp::R_PPC64_ADDR16_HIGHERA: case elfcpp::R_PPC64_TPREL16_HIGHERA: Reloc::addr16_ha2(view, value); @@ -8030,6 +8106,7 @@ Target_powerpc::Reloca if (size == 32) // R_PPC_EMB_NADDR16_HA goto unsupp; + // Fall through. case elfcpp::R_PPC64_ADDR16_HIGHEST: case elfcpp::R_PPC64_TPREL16_HIGHEST: Reloc::addr16_hi3(view, value); @@ -8039,6 +8116,7 @@ Target_powerpc::Reloca if (size == 32) // R_PPC_EMB_SDAI16 goto unsupp; + // Fall through. case elfcpp::R_PPC64_ADDR16_HIGHESTA: case elfcpp::R_PPC64_TPREL16_HIGHESTA: Reloc::addr16_ha3(view, value); @@ -8049,11 +8127,13 @@ Target_powerpc::Reloca if (size == 32) // R_PPC_EMB_NADDR32, R_PPC_EMB_NADDR16 goto unsupp; + // Fall through. case elfcpp::R_PPC64_TPREL16_DS: case elfcpp::R_PPC64_TPREL16_LO_DS: if (size == 32) // R_PPC_TLSGD, R_PPC_TLSLD break; + // Fall through. case elfcpp::R_PPC64_ADDR16_DS: case elfcpp::R_PPC64_ADDR16_LO_DS: case elfcpp::R_PPC64_TOC16_DS: diff -rup ../binutils-2.27/gold/resolve.cc gold/resolve.cc --- ../binutils-2.27/gold/resolve.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/resolve.cc 2016-11-03 15:05:47.000000000 +0000 @@ -193,6 +193,7 @@ symbol_to_bits(elfcpp::STB binding, bool // table. gold_error(_("invalid STB_LOCAL symbol in external symbols")); bits = global_flag; + break; default: // Any target which wants to handle STB_LOOS, etc., needs to diff -rup ../binutils-2.27/gold/script.cc gold/script.cc --- ../binutils-2.27/gold/script.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/script.cc 2016-11-03 15:05:47.000000000 +0000 @@ -1755,6 +1755,7 @@ script_keyword_parsecodes[] = { "FLOAT", FLOAT }, { "FORCE_COMMON_ALLOCATION", FORCE_COMMON_ALLOCATION }, { "GROUP", GROUP }, + { "HIDDEN", HIDDEN }, { "HLL", HLL }, { "INCLUDE", INCLUDE }, { "INFO", INFO }, diff -rup ../binutils-2.27/gold/script-sections.cc gold/script-sections.cc --- ../binutils-2.27/gold/script-sections.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/script-sections.cc 2016-11-03 15:05:48.000000000 +0000 @@ -1503,7 +1503,7 @@ class Input_section_info private: // Input section, can be a relaxed section. Output_section::Input_section input_section_; - // Name of the section. + // Name of the section. std::string section_name_; // Section size. uint64_t size_; @@ -1545,7 +1545,7 @@ Input_section_sorter::get_init_priority( // GCC uses the following section names for the init_priority // attribute with numerical values 101 and 65535 inclusive. A // lower value means a higher priority. - // + // // 1: .init_array.NNNN/.fini_array.NNNN: Where NNNN is the // decimal numerical value of the init_priority attribute. // The order of execution in .init_array is forward and @@ -1666,7 +1666,7 @@ Output_section_element_input::set_sectio while (p != input_sections->end()) { Relobj* relobj = p->relobj(); - unsigned int shndx = p->shndx(); + unsigned int shndx = p->shndx(); Input_section_info isi(*p); // Calling section_name and section_addralign is not very @@ -1758,7 +1758,7 @@ Output_section_element_input::set_sectio uint64_t this_subalign = sis.addralign(); if (!sis.is_input_section()) - sis.output_section_data()->finalize_data_size(); + sis.output_section_data()->finalize_data_size(); uint64_t data_size = sis.data_size(); if (this_subalign < subalign) { @@ -2029,7 +2029,7 @@ class Output_section_definition : public void set_section_vma(Expression* address) { this->address_ = address; } - + void set_section_lma(Expression* address) { this->load_address_ = address; } @@ -2037,7 +2037,7 @@ class Output_section_definition : public const std::string& get_section_name() const { return this->name_; } - + private: static const char* script_section_type_name(Script_section_type); @@ -2402,9 +2402,9 @@ Output_section_definition::set_section_a uint64_t old_load_address = *load_address; // If input section sorting is requested via --section-ordering-file or - // linker plugins, then do it here. This is important because we want + // linker plugins, then do it here. This is important because we want // any sorting specified in the linker scripts, which will be done after - // this, to take precedence. The final order of input sections is then + // this, to take precedence. The final order of input sections is then // guaranteed to be according to the linker script specification. if (this->output_section_ != NULL && this->output_section_->input_section_order_specified()) @@ -2495,7 +2495,7 @@ Output_section_definition::set_section_a // The LMA address was explicitly set to the given region. laddr = lma_region->get_current_address()->eval(symtab, layout, false); - else + else { // We are not going to use the discovered lma_region, so // make sure that we do not update it in the code below. @@ -2987,9 +2987,9 @@ Orphan_output_section::set_section_addre address = align_address(address, this->os_->addralign()); // If input section sorting is requested via --section-ordering-file or - // linker plugins, then do it here. This is important because we want + // linker plugins, then do it here. This is important because we want // any sorting specified in the linker scripts, which will be done after - // this, to take precedence. The final order of input sections is then + // this, to take precedence. The final order of input sections is then // guaranteed to be according to the linker script specification. if (this->os_ != NULL && this->os_->input_section_order_specified()) @@ -3023,7 +3023,7 @@ Orphan_output_section::set_section_addre { uint64_t addralign = p->addralign(); if (!p->is_input_section()) - p->output_section_data()->finalize_data_size(); + p->output_section_data()->finalize_data_size(); uint64_t size = p->data_size(); address = align_address(address, addralign); this->os_->add_script_input_section(*p); @@ -3605,7 +3605,7 @@ Output_segment* Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout) { gold_assert(this->saw_sections_clause_); - + // Implement ONLY_IF_RO/ONLY_IF_RW constraints. These are a pain // for our representation. for (Sections_elements::iterator p = this->sections_elements_->begin(); @@ -3674,7 +3674,7 @@ Script_sections::set_section_addresses(S Output_section* os = (*p)->get_output_section(); // Handle -Ttext, -Tdata and -Tbss options. We do this by looking for - // the special sections by names and doing dot assignments. + // the special sections by names and doing dot assignments. if (use_tsection_options && os != NULL && (os->flags() & elfcpp::SHF_ALLOC) != 0) @@ -3703,7 +3703,7 @@ Script_sections::set_section_addresses(S (*p)->set_section_addresses(symtab, layout, &dot_value, &dot_alignment, &load_address); - } + } if (this->phdrs_elements_ != NULL) { @@ -3890,7 +3890,7 @@ Script_sections::create_segments(Layout* layout->get_allocated_sections(§ions); // Sort the sections by address. - std::stable_sort(sections.begin(), sections.end(), + std::stable_sort(sections.begin(), sections.end(), Sort_output_sections(this->sections_elements_)); this->create_note_and_tls_segments(layout, §ions); @@ -4217,7 +4217,7 @@ Script_sections::attach_sections_using_p // Output sections in the script which do not list segments are // attached to the same set of segments as the immediately preceding // output section. - + String_list* phdr_names = NULL; bool load_segments_only = false; for (Sections_elements::const_iterator p = this->sections_elements_->begin(); @@ -4262,7 +4262,7 @@ Script_sections::attach_sections_using_p // filtering. if (old_phdr_names != phdr_names) load_segments_only = false; - + // If this is an orphan section--one that was not explicitly // mentioned in the linker script--then it should not inherit // any segment type other than PT_LOAD. Otherwise, e.g., the @@ -4459,6 +4459,7 @@ Script_sections::release_segments() ++p) (*p)->release_segment(); } + this->segments_created_ = false; } // Print the SECTIONS clause to F for debugging. diff -rup ../binutils-2.27/gold/sparc.cc gold/sparc.cc --- ../binutils-2.27/gold/sparc.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/sparc.cc 2016-11-03 15:05:48.000000000 +0000 @@ -2150,6 +2150,7 @@ Target_sparc::Scan::ch case elfcpp::R_SPARC_RELATIVE: case elfcpp::R_SPARC_IRELATIVE: case elfcpp::R_SPARC_COPY: + case elfcpp::R_SPARC_32: case elfcpp::R_SPARC_64: case elfcpp::R_SPARC_GLOB_DAT: case elfcpp::R_SPARC_JMP_SLOT: @@ -2304,7 +2305,7 @@ Target_sparc::Scan::lo reloc.get_r_addend(), is_ifunc); break; } - /* Fall through. */ + // Fall through. case elfcpp::R_SPARC_HIX22: case elfcpp::R_SPARC_LOX10: @@ -2814,6 +2815,7 @@ Target_sparc::Scan::gl // and code transform the GOT load into an addition. break; } + // Fall through. case elfcpp::R_SPARC_GOT10: case elfcpp::R_SPARC_GOT13: case elfcpp::R_SPARC_GOT22: @@ -3353,6 +3355,7 @@ Target_sparc::Relocate gdop_valid = true; break; } + // Fall through. case elfcpp::R_SPARC_GOT10: case elfcpp::R_SPARC_GOT13: case elfcpp::R_SPARC_GOT22: @@ -3468,6 +3471,13 @@ Target_sparc::Relocate Reloc::lo10(view, object, psymval, addend); break; + case elfcpp::R_SPARC_GOTDATA_OP_LOX10: + if (gdop_valid) + { + Reloc::gdop_lox10(view, got_offset); + break; + } + // Fall through. case elfcpp::R_SPARC_GOT10: Reloc::lo10(view, got_offset, addend); break; @@ -3486,13 +3496,6 @@ Target_sparc::Relocate } break; - case elfcpp::R_SPARC_GOTDATA_OP_LOX10: - if (gdop_valid) - { - Reloc::gdop_lox10(view, got_offset); - break; - } - /* Fall through. */ case elfcpp::R_SPARC_GOT13: Reloc::rela32_13(view, got_offset, addend); break; @@ -3503,7 +3506,7 @@ Target_sparc::Relocate Reloc::gdop_hix22(view, got_offset); break; } - /* Fall through. */ + // Fall through. case elfcpp::R_SPARC_GOT22: Reloc::hi22(view, got_offset, addend); break; diff -rup ../binutils-2.27/gold/symtab.cc gold/symtab.cc --- ../binutils-2.27/gold/symtab.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/symtab.cc 2016-11-03 15:05:49.000000000 +0000 @@ -882,6 +882,7 @@ Symbol_table::define_default_version(Siz ; else if (pdef->second->is_from_dynobj() && sym->is_from_dynobj() + && pdef->second->is_defined() && pdef->second->object() != sym->object()) ; else @@ -1325,6 +1326,9 @@ Symbol_table::add_from_relobj( res = this->add_from_object(relobj, name, name_key, ver, ver_key, is_default_version, *psym, st_shndx, is_ordinary, orig_st_shndx); + + if (res == NULL) + continue; if (is_forced_local) this->force_local(res); @@ -1406,6 +1410,9 @@ Symbol_table::add_from_pluginobj( is_default_version, *sym, st_shndx, is_ordinary, st_shndx); + if (res == NULL) + return NULL; + if (is_forced_local) this->force_local(res); @@ -1602,6 +1609,9 @@ Symbol_table::add_from_dynobj( } } + if (res == NULL) + continue; + // Note that it is possible that RES was overridden by an // earlier object, in which case it can't be aliased here. if (st_shndx != elfcpp::SHN_UNDEF @@ -1640,7 +1650,6 @@ Symbol_table::add_from_incrobj( Stringpool::Key ver_key = 0; bool is_default_version = false; - bool is_forced_local = false; Stringpool::Key name_key; name = this->namepool_.add(name, true, &name_key); @@ -1650,9 +1659,6 @@ Symbol_table::add_from_incrobj( is_default_version, *sym, st_shndx, is_ordinary, st_shndx); - if (is_forced_local) - this->force_local(res); - return res; } diff -rup ../binutils-2.27/gold/tilegx.cc gold/tilegx.cc --- ../binutils-2.27/gold/tilegx.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/tilegx.cc 2016-11-03 15:05:50.000000000 +0000 @@ -4428,6 +4428,7 @@ Target_tilegx::Relocat psymval = &symval; always_apply_relocation = true; addend = 0; + // Fall through. // when under PIC mode, these relocations are deferred to rtld case elfcpp::R_TILEGX_IMM16_X0_HW0: @@ -4618,6 +4619,7 @@ Target_tilegx::Relocat got_type = GOT_TYPE_TLS_OFFSET; have_got_offset = true; } + // Fall through. do_update_value: if (have_got_offset) { if (gsym != NULL) { @@ -4647,10 +4649,8 @@ Target_tilegx::Relocat } // else if (opt_t == tls::TLSOPT_TO_LE) // both GD/IE are turned into LE, which // is absolute relocation. - // - // | go through - // | - // V + // Fall through. + // LE // // tp diff -rup ../binutils-2.27/gold/x86_64.cc gold/x86_64.cc --- ../binutils-2.27/gold/x86_64.cc 2016-08-03 08:36:53.000000000 +0100 +++ gold/x86_64.cc 2016-11-03 15:05:52.000000000 +0000 @@ -2361,7 +2361,7 @@ Target_x86_64::Scan::check_non_pic && !gsym->is_undefined() && !gsym->is_preemptible())) return; - /* Fall through. */ + // Fall through. case elfcpp::R_X86_64_32: // R_X86_64_32 is OK for x32. if (size == 32 && r_type == elfcpp::R_X86_64_32) @@ -3505,6 +3505,7 @@ Target_x86_64::Relocate::relocate( if (this->skip_call_tls_get_addr_) { if ((r_type != elfcpp::R_X86_64_PLT32 + && r_type != elfcpp::R_X86_64_GOTPCREL && r_type != elfcpp::R_X86_64_GOTPCRELX && r_type != elfcpp::R_X86_64_PLT32_BND && r_type != elfcpp::R_X86_64_PC32_BND @@ -3514,6 +3515,7 @@ Target_x86_64::Relocate::relocate( { gold_error_at_location(relinfo, relnum, rela.get_r_offset(), _("missing expected TLS relocation")); + this->skip_call_tls_get_addr_ = false; } else { diff -rup ../binutils-2.27/gold/yyscript.y gold/yyscript.y --- ../binutils-2.27/gold/yyscript.y 2016-08-03 08:36:53.000000000 +0100 +++ gold/yyscript.y 2016-11-03 15:05:59.000000000 +0000 @@ -137,6 +137,7 @@ %token FORCE_COMMON_ALLOCATION %token GLOBAL /* global */ %token GROUP +%token HIDDEN %token HLL %token INCLUDE %token INHIBIT_COMMON_ALLOCATION @@ -864,6 +865,8 @@ assignment: Expression_ptr e = script_exp_binary_bitwise_or(s, $3); script_set_symbol(closure, $1.value, $1.length, e, 0, 0); } + | HIDDEN '(' string '=' parse_exp ')' + { script_set_symbol(closure, $3.value, $3.length, $5, 0, 1); } | PROVIDE '(' string '=' parse_exp ')' { script_set_symbol(closure, $3.value, $3.length, $5, 1, 0); } | PROVIDE_HIDDEN '(' string '=' parse_exp ')'