From 46bdb29b93b05b2805369dd67b34d6860fce15bd Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Fri, 9 Feb 2018 12:46:14 -0800 Subject: binutils: Fix relocation overflow errors with gold WPE Webkit fails to link with gold from binutils 2.27 release Signed-off-by: Khem Raj Signed-off-by: Andre McCurdy Signed-off-by: Armin Kuster --- meta/recipes-devtools/binutils/binutils-2.27.inc | 2 + .../binutils/binutils/PR21152.patch | 480 +++++++++++++++++++++ .../improve-relocation-overflow-errors.patch | 74 ++++ 3 files changed, 556 insertions(+) create mode 100644 meta/recipes-devtools/binutils/binutils/PR21152.patch create mode 100644 meta/recipes-devtools/binutils/binutils/improve-relocation-overflow-errors.patch diff --git a/meta/recipes-devtools/binutils/binutils-2.27.inc b/meta/recipes-devtools/binutils/binutils-2.27.inc index 1311b65847..e631cc12f9 100644 --- a/meta/recipes-devtools/binutils/binutils-2.27.inc +++ b/meta/recipes-devtools/binutils/binutils-2.27.inc @@ -39,6 +39,8 @@ SRC_URI = "\ file://0016-Fix-seg-fault-in-ARM-linker-when-trying-to-parse-a-b.patch \ file://0017-Fix-the-generation-of-alignment-frags-in-code-sectio.patch \ file://0001-ppc-apuinfo-for-spe-parsed-incorrectly.patch \ + file://PR21152.patch \ + file://improve-relocation-overflow-errors.patch \ file://CVE-2017-6965.patch \ file://CVE-2017-6966.patch \ file://CVE-2017-6969.patch \ diff --git a/meta/recipes-devtools/binutils/binutils/PR21152.patch b/meta/recipes-devtools/binutils/binutils/PR21152.patch new file mode 100644 index 0000000000..9bd6dbdb51 --- /dev/null +++ b/meta/recipes-devtools/binutils/binutils/PR21152.patch @@ -0,0 +1,480 @@ +This patch adds support for more relocations in relocatable link. It also +introduces get_lo16_rel_addend method for finding partnering LO16 relocation +because there is a problem with current implementation when using --threads +option. + +Regards, +Vladimir + +ChangeLog - + + PR gold/21152 + * target.h (Sized_target::relocate_special_relocatable): Add + reloc_count parameter. + * arm.cc (Target_arm::relocate_special_relocatable): Likewise. + * target-reloc.h (relocate_relocs): Pass reloc_count to + relocate_special_relocatable. + * mips.cc (Mips_scan_relocatable_relocs::local_section_strategy): + Return RELOC_SPECIAL for more relocations. + (Symbol_visitor_check_symbols::operator()): Check for is_output_pic + rather then checking output_is_position_independent option. + (Target_mips::is_output_pic): New method. + (Mips_relocate_functions::get_lo16_rel_addend): Likewise. + (Target_mips::set_gp): Add case for relocatable link. + (Target_mips::relocate_special_relocatable): Add reloc_count + parameter. Add support for RELA type of relocation sections. + Add support for more relocations. Remove unused code. + +Upstream-Status: Backport +Signed-off-by: Khem Raj + +diff --git a/gold/arm.cc b/gold/arm.cc +index ff472ea..c675065 100644 +--- a/gold/arm.cc ++++ b/gold/arm.cc +@@ -2341,6 +2341,7 @@ class Target_arm : public Sized_target<32, big_endian> + unsigned int sh_type, + const unsigned char* preloc_in, + size_t relnum, ++ size_t reloc_count, + Output_section* output_section, + typename elfcpp::Elf_types<32>::Elf_Off + offset_in_output_section, +@@ -10428,6 +10429,7 @@ Target_arm::relocate_special_relocatable( + unsigned int sh_type, + const unsigned char* preloc_in, + size_t relnum, ++ size_t, + Output_section* output_section, + typename elfcpp::Elf_types<32>::Elf_Off offset_in_output_section, + unsigned char* view, +diff --git a/gold/mips.cc b/gold/mips.cc +index 95bf6db..52edeac 100644 +--- a/gold/mips.cc ++++ b/gold/mips.cc +@@ -2858,12 +2858,45 @@ class Mips_scan_relocatable_relocs : + local_section_strategy(unsigned int r_type, Relobj* object) + { + if (Classify_reloc::sh_type == elfcpp::SHT_RELA) +- return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; ++ { ++ switch (r_type) ++ { ++ case elfcpp::R_MIPS_GPREL32: ++ case elfcpp::R_MIPS_GPREL16: ++ case elfcpp::R_MIPS_LITERAL: ++ case elfcpp::R_MICROMIPS_GPREL16: ++ case elfcpp::R_MICROMIPS_GPREL7_S2: ++ case elfcpp::R_MICROMIPS_LITERAL: ++ case elfcpp::R_MIPS16_GPREL: ++ return Relocatable_relocs::RELOC_SPECIAL; ++ ++ default: ++ return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; ++ } ++ } + else + { + switch (r_type) + { + case elfcpp::R_MIPS_26: ++ case elfcpp::R_MIPS_HI16: ++ case elfcpp::R_MIPS_LO16: ++ case elfcpp::R_MIPS_GOT16: ++ case elfcpp::R_MIPS_GPREL32: ++ case elfcpp::R_MIPS_GPREL16: ++ case elfcpp::R_MIPS_LITERAL: ++ case elfcpp::R_MICROMIPS_26_S1: ++ case elfcpp::R_MICROMIPS_HI16: ++ case elfcpp::R_MICROMIPS_LO16: ++ case elfcpp::R_MICROMIPS_GOT16: ++ case elfcpp::R_MICROMIPS_GPREL16: ++ case elfcpp::R_MICROMIPS_GPREL7_S2: ++ case elfcpp::R_MICROMIPS_LITERAL: ++ case elfcpp::R_MIPS16_26: ++ case elfcpp::R_MIPS16_HI16: ++ case elfcpp::R_MIPS16_LO16: ++ case elfcpp::R_MIPS16_GOT16: ++ case elfcpp::R_MIPS16_GPREL: + return Relocatable_relocs::RELOC_SPECIAL; + + default: +@@ -3048,7 +3081,7 @@ class Symbol_visitor_check_symbols + // stub. + if (parameters->options().relocatable()) + { +- if (!parameters->options().output_is_position_independent()) ++ if (!this->target_->is_output_pic()) + mips_sym->set_pic(); + } + else if (mips_sym->has_nonpic_branches()) +@@ -3411,6 +3444,7 @@ class Target_mips : public Sized_target + unsigned int sh_type, + const unsigned char* preloc_in, + size_t relnum, ++ size_t reloc_count, + Output_section* output_section, + typename elfcpp::Elf_types::Elf_Off + offset_in_output_section, +@@ -3596,6 +3630,11 @@ class Target_mips : public Sized_target + is_output_n64() const + { return size == 64; } + ++ // Whether the output contains position independent code. ++ bool ++ is_output_pic() const ++ { return (this->processor_specific_flags() & elfcpp::EF_MIPS_PIC) != 0; } ++ + // Whether the output uses NEWABI. This is valid only after + // merge_obj_e_flags() is called. + bool +@@ -4294,6 +4333,52 @@ class Mips_relocate_functions : public Relocate_functions + } + + public: ++ // Find partnering LO16 relocation and extract addend from the instruction. ++ // Return true on success or false if the LO16 could not be found. ++ ++ static bool ++ get_lo16_rel_addend(unsigned int sh_type, const unsigned char* prelocs, ++ size_t relnum, size_t reloc_count, ++ unsigned int hi16_r_type, unsigned int hi16_r_sym, ++ unsigned char* view, Mips_address* addend) ++ { ++ gold_assert(sh_type == elfcpp::SHT_REL); ++ ++ typedef typename Mips_reloc_types::Reloc ++ Reltype; ++ const int reloc_size = ++ Mips_classify_reloc::reloc_size; ++ ++ // Start finding lo16 part from the next relocation. ++ prelocs += reloc_size; ++ for (size_t i = relnum + 1; i < reloc_count; ++i, prelocs += reloc_size) ++ { ++ Reltype reloc(prelocs); ++ unsigned int r_sym = Mips_classify_reloc::get_r_sym(&reloc); ++ unsigned int r_type = Mips_classify_reloc:: ++ get_r_type(&reloc); ++ ++ if (hi16_r_sym == r_sym ++ && is_matching_lo16_reloc(hi16_r_type, r_type)) ++ { ++ Mips_address offset = reloc.get_r_offset(); ++ view += offset; ++ ++ mips_reloc_unshuffle(view, r_type, false); ++ Valtype32* wv = reinterpret_cast(view); ++ Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); ++ mips_reloc_shuffle(view, r_type, false); ++ ++ *addend = Bits<16>::sign_extend32(val & 0xffff); ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ + // R_MIPS16_26 is used for the mips16 jal and jalx instructions. + // Most mips16 instructions are 16 bits, but these instructions + // are 32 bits. +@@ -8438,6 +8523,23 @@ Target_mips::set_gp(Layout* layout, Symbol_table* symtab) + 0, false, false)); + this->gp_ = gp; + } ++ ++ if (parameters->options().relocatable()) ++ { ++ // If gp is NULL, set it to the default value. ++ if (gp == NULL) ++ gp = static_cast*>(symtab->define_as_constant( ++ "_gp", NULL, Symbol_table::PREDEFINED, ++ MIPS_GP_OFFSET, 0, ++ elfcpp::STT_OBJECT, ++ elfcpp::STB_GLOBAL, ++ elfcpp::STV_DEFAULT, ++ 0, false, false)); ++ // Don't add _gp to the final symtab, because the value of the _gp symbol ++ // will be stored into .reginfo/.MIPS.options section. ++ gp->set_symtab_index(-1U); ++ this->gp_ = gp; ++ } + } + + // Set the dynamic symbol indexes. INDEX is the index of the first +@@ -8576,7 +8678,6 @@ Target_mips::make_plt_entry(Symbol_table* symtab, + this->plt_->add_entry(gsym, r_type); + } + +- + // Get the .MIPS.stubs section, creating it if necessary. + + template +@@ -10221,35 +10322,48 @@ Target_mips::relocate_special_relocatable( + unsigned int sh_type, + const unsigned char* preloc_in, + size_t relnum, ++ size_t reloc_count, + Output_section* output_section, + typename elfcpp::Elf_types::Elf_Off offset_in_output_section, + unsigned char* view, +- Mips_address view_address, ++ Mips_address, + section_size_type, + unsigned char* preloc_out) + { +- // We can only handle REL type relocation sections. +- gold_assert(sh_type == elfcpp::SHT_REL); +- +- typedef typename Reloc_types::Reloc +- Reltype; +- typedef typename Reloc_types::Reloc_write +- Reltype_write; +- + typedef Mips_relocate_functions Reloc_funcs; +- + const Mips_address invalid_address = static_cast(0) - 1; + + Mips_relobj* object = + Mips_relobj::as_mips_relobj(relinfo->object); + const unsigned int local_count = object->local_symbol_count(); + +- Reltype reloc(preloc_in); +- Reltype_write reloc_write(preloc_out); ++ unsigned int r_sym; ++ unsigned int r_type; ++ Mips_address r_addend; ++ Mips_address offset; + +- elfcpp::Elf_types<32>::Elf_WXword r_info = reloc.get_r_info(); +- const unsigned int r_sym = elfcpp::elf_r_sym(r_info); +- const unsigned int r_type = elfcpp::elf_r_type(r_info); ++ if (sh_type == elfcpp::SHT_RELA) ++ { ++ const Relatype rela(preloc_in); ++ offset = rela.get_r_offset(); ++ r_sym = Mips_classify_reloc:: ++ get_r_sym(&rela); ++ r_type = Mips_classify_reloc:: ++ get_r_type(&rela); ++ r_addend = rela.get_r_addend(); ++ } ++ else if (sh_type == elfcpp::SHT_REL) ++ { ++ const Reltype rel(preloc_in); ++ offset = rel.get_r_offset(); ++ r_sym = Mips_classify_reloc:: ++ get_r_sym(&rel); ++ r_type = Mips_classify_reloc:: ++ get_r_type(&rel); ++ r_addend = 0; ++ } ++ else ++ gold_unreachable(); + + // Get the new symbol index. + // We only use RELOC_SPECIAL strategy in local relocations. +@@ -10270,7 +10384,6 @@ Target_mips::relocate_special_relocatable( + // Get the new offset--the location in the output section where + // this relocation should be applied. + +- Mips_address offset = reloc.get_r_offset(); + Mips_address new_offset; + if (offset_in_output_section != invalid_address) + new_offset = offset + offset_in_output_section; +@@ -10285,19 +10398,6 @@ Target_mips::relocate_special_relocatable( + new_offset = new_sot_offset; + } + +- // In an object file, r_offset is an offset within the section. +- // In an executable or dynamic object, generated by +- // --emit-relocs, r_offset is an absolute address. +- if (!parameters->options().relocatable()) +- { +- new_offset += view_address; +- if (offset_in_output_section != invalid_address) +- new_offset -= offset_in_output_section; +- } +- +- reloc_write.put_r_offset(new_offset); +- reloc_write.put_r_info(elfcpp::elf_r_info<32>(new_symndx, r_type)); +- + // Handle the reloc addend. + // The relocation uses a section symbol in the input file. + // We are adjusting it to use a section symbol in the output +@@ -10306,23 +10406,127 @@ Target_mips::relocate_special_relocatable( + // file to refer to that same address. This adjustment to + // the addend is the same calculation we use for a simple + // absolute relocation for the input section symbol. +- Valtype calculated_value = 0; ++ Valtype x = 0; + const Symbol_value* psymval = object->local_symbol(r_sym); +- ++ bool extract_addend = sh_type == elfcpp::SHT_REL; + unsigned char* paddend = view + offset; + typename Reloc_funcs::Status reloc_status = Reloc_funcs::STATUS_OKAY; ++ ++ Reloc_funcs::mips_reloc_unshuffle(paddend, r_type, false); + switch (r_type) + { + case elfcpp::R_MIPS_26: +- reloc_status = Reloc_funcs::rel26(paddend, object, psymval, +- offset_in_output_section, true, 0, sh_type == elfcpp::SHT_REL, NULL, +- false /*TODO(sasa): cross mode jump*/, r_type, this->jal_to_bal(), +- false, &calculated_value); ++ case elfcpp::R_MICROMIPS_26_S1: ++ case elfcpp::R_MIPS16_26: ++ gold_assert(extract_addend); ++ reloc_status = Reloc_funcs::rel26(paddend, object, psymval, new_offset, ++ true, 0, true, NULL, false, r_type, ++ false, false, &x); ++ break; ++ ++ case elfcpp::R_MIPS_HI16: ++ case elfcpp::R_MIPS_GOT16: ++ case elfcpp::R_MICROMIPS_HI16: ++ case elfcpp::R_MICROMIPS_GOT16: ++ case elfcpp::R_MIPS16_HI16: ++ case elfcpp::R_MIPS16_GOT16: ++ { ++ gold_assert(extract_addend); ++ Valtype32* wv = reinterpret_cast(paddend); ++ Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); ++ Valtype addend_lo; ++ ++ bool found = Reloc_funcs::get_lo16_rel_addend(sh_type, preloc_in, ++ relnum, reloc_count, ++ r_type, r_sym, view, ++ &addend_lo); ++ if (!found) ++ { ++ gold_error(_("%s: Can't find matching LO16 reloc for relocation %u " ++ "against local symbol %u at 0x%lx in section %s"), ++ object->name().c_str(), r_type, r_sym, ++ (unsigned long) offset, ++ object->section_name(relinfo->data_shndx).c_str()); ++ return; ++ } ++ ++ Valtype addend = ((val & 0xffff) << 16) + addend_lo; ++ Valtype value = psymval->value(object, addend); ++ x = ((value + 0x8000) >> 16) & 0xffff; ++ val = Bits<32>::bit_select32(val, x, 0xffff); ++ ++ elfcpp::Swap<32, big_endian>::writeval(wv, val); ++ reloc_status = Reloc_funcs::STATUS_OKAY; ++ break; ++ } ++ ++ case elfcpp::R_MIPS_LO16: ++ case elfcpp::R_MICROMIPS_LO16: ++ case elfcpp::R_MIPS16_LO16: ++ { ++ gold_assert(extract_addend); ++ Valtype32* wv = reinterpret_cast(paddend); ++ Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); ++ Valtype addend = Bits<16>::sign_extend32(val & 0xffff); ++ ++ x = psymval->value(object, addend); ++ val = Bits<32>::bit_select32(val, x, 0xffff); ++ ++ elfcpp::Swap<32, big_endian>::writeval(wv, val); ++ reloc_status = Reloc_funcs::STATUS_OKAY; ++ break; ++ } ++ ++ case elfcpp::R_MIPS_GPREL16: ++ case elfcpp::R_MIPS_LITERAL: ++ case elfcpp::R_MICROMIPS_GPREL16: ++ case elfcpp::R_MICROMIPS_GPREL7_S2: ++ case elfcpp::R_MICROMIPS_LITERAL: ++ case elfcpp::R_MIPS16_GPREL: ++ reloc_status = Reloc_funcs::relgprel(paddend, object, psymval, ++ this->gp_value(), r_addend, ++ extract_addend, true, r_type, ++ !extract_addend, &x); ++ break; ++ ++ case elfcpp::R_MIPS_GPREL32: ++ reloc_status = Reloc_funcs::relgprel32(paddend, object, psymval, ++ this->gp_value(), r_addend, ++ extract_addend, !extract_addend, ++ &x); + break; + + default: + gold_unreachable(); + } ++ Reloc_funcs::mips_reloc_shuffle(paddend, r_type, false); ++ ++ if (sh_type == elfcpp::SHT_RELA) ++ { ++ typedef typename Mips_reloc_types::Reloc_write Relatype_write; ++ Relatype rela(preloc_in); ++ Relatype_write rela_write(preloc_out); ++ ++ rela_write.put_r_offset(new_offset); ++ Mips_classify_reloc:: ++ put_r_info(&rela_write, &rela, new_symndx); ++ Mips_classify_reloc:: ++ put_r_addend(&rela_write, x); ++ } ++ else if (sh_type == elfcpp::SHT_REL) ++ { ++ typedef typename Mips_reloc_types::Reloc_write Reltype_write; ++ Reltype rel(preloc_in); ++ Reltype_write rel_write(preloc_out); ++ ++ rel_write.put_r_offset(new_offset); ++ Mips_classify_reloc:: ++ put_r_info(&rel_write, &rel, new_symndx); ++ } ++ else ++ gold_unreachable(); + + // Report any errors. + switch (reloc_status) +@@ -10330,11 +10534,11 @@ Target_mips::relocate_special_relocatable( + case Reloc_funcs::STATUS_OKAY: + break; + case Reloc_funcs::STATUS_OVERFLOW: +- gold_error_at_location(relinfo, relnum, reloc.get_r_offset(), ++ gold_error_at_location(relinfo, relnum, offset, + _("relocation overflow")); + break; + case Reloc_funcs::STATUS_BAD_RELOC: +- gold_error_at_location(relinfo, relnum, reloc.get_r_offset(), ++ gold_error_at_location(relinfo, relnum, offset, + _("unexpected opcode while processing relocation")); + break; + default: +diff --git a/gold/target-reloc.h b/gold/target-reloc.h +index c8b86c6..536118e 100644 +--- a/gold/target-reloc.h ++++ b/gold/target-reloc.h +@@ -767,7 +767,8 @@ relocate_relocs( + Sized_target* target = + parameters->sized_target(); + target->relocate_special_relocatable(relinfo, Classify_reloc::sh_type, +- prelocs, i, output_section, ++ prelocs, i, reloc_count, ++ output_section, + offset_in_output_section, + view, view_address, + view_size, pwrite); +diff --git a/gold/target.h b/gold/target.h +index 5ca8435..e43623a 100644 +--- a/gold/target.h ++++ b/gold/target.h +@@ -993,6 +993,7 @@ class Sized_target : public Target + unsigned int /* sh_type */, + const unsigned char* /* preloc_in */, + size_t /* relnum */, ++ size_t /* reloc_count */, + Output_section* /* output_section */, + typename elfcpp::Elf_types::Elf_Off diff --git a/meta/recipes-devtools/binutils/binutils/improve-relocation-overflow-errors.patch b/meta/recipes-devtools/binutils/binutils/improve-relocation-overflow-errors.patch new file mode 100644 index 0000000000..dd08d73f8d --- /dev/null +++ b/meta/recipes-devtools/binutils/binutils/improve-relocation-overflow-errors.patch @@ -0,0 +1,74 @@ +This patch improves relocation overflow errors. +Depends on https://sourceware.org/ml/binutils/2017-03/msg00146.html. + +Regards, +Vladimir + +ChangeLog - + + * mips.cc (Target_mips::Relocate::relocate): Improve relocation + overflow error message. + (Target_mips::relocate_special_relocatable): Likewise. + (Mips_relocate_functions::rel26): Don't print relocation overflow + error message. +Upstream-Status: Backport +Signed-off-by: Khem Raj + +diff --git a/gold/mips.cc b/gold/mips.cc +index 10dea9e7..bd9bac0 100644 +--- a/gold/mips.cc ++++ b/gold/mips.cc +@@ -4676,15 +4676,9 @@ class Mips_relocate_functions : public Relocate_functions + } + x = psymval->value(object, x) >> shift; + +- if (!calculate_only && !local && !gsym->is_weak_undefined()) +- { +- if ((x >> 26) != ((address + 4) >> (26 + shift))) +- { +- gold_error(_("relocation truncated to fit: %u against '%s'"), +- r_type, gsym->name()); +- return This::STATUS_OVERFLOW; +- } +- } ++ if (!calculate_only && !local && !gsym->is_weak_undefined() ++ && ((x >> 26) != ((address + 4) >> (26 + shift)))) ++ return This::STATUS_OVERFLOW; + + val = Bits<32>::bit_select32(val, x, 0x03ffffff); + +@@ -10510,7 +10504,9 @@ Target_mips::relocate_special_relocatable( + break; + case Reloc_funcs::STATUS_OVERFLOW: + gold_error_at_location(relinfo, relnum, offset, +- _("relocation overflow")); ++ _("relocation overflow: " ++ "%u against local symbol %u in %s"), ++ r_type, r_sym, object->name().c_str()); + break; + case Reloc_funcs::STATUS_BAD_RELOC: + gold_error_at_location(relinfo, relnum, offset, +@@ -12391,8 +12387,21 @@ Target_mips::Relocate::relocate( + case Reloc_funcs::STATUS_OKAY: + break; + case Reloc_funcs::STATUS_OVERFLOW: +- gold_error_at_location(relinfo, relnum, r_offset, +- _("relocation overflow")); ++ if (gsym == NULL) ++ gold_error_at_location(relinfo, relnum, r_offset, ++ _("relocation overflow: " ++ "%u against local symbol %u in %s"), ++ r_type, r_sym, object->name().c_str()); ++ else if (gsym->is_defined() && gsym->source() == Symbol::FROM_OBJECT) ++ gold_error_at_location(relinfo, relnum, r_offset, ++ _("relocation overflow: " ++ "%u against '%s' defined in %s"), ++ r_type, gsym->demangled_name().c_str(), ++ gsym->object()->name().c_str()); ++ else ++ gold_error_at_location(relinfo, relnum, r_offset, ++ _("relocation overflow: %u against '%s'"), ++ r_type, gsym->demangled_name().c_str()); + break; + case Reloc_funcs::STATUS_BAD_RELOC: + gold_error_at_location(relinfo, relnum, r_offset, -- cgit 1.2.3-korg