You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1717 lines
64 KiB
1717 lines
64 KiB
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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<int L, int U> |
|
-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<int L> |
|
+class Rvalue_bit_select_impl<L, 63> |
|
+{ |
|
+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<int L, int U> |
|
uint64_t |
|
-rvalue_bit_select<0, 0>(uint64_t x) { return x; } |
|
+rvalue_bit_select(uint64_t x) |
|
+{ |
|
+ return Rvalue_bit_select_impl<L, U>::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<bool big_endian> |
|
@@ -6639,6 +6672,80 @@ Arm_relobj<big_endian>::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<Valtype*>(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<Valtype*>(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<big_endian> |
|
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<big_endian>::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<big_endian>::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<big_endian>::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<big_endian>::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<big_endian>::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<big_endian>::Classify_reloc:: |
|
unsigned int r_type, |
|
Relobj* object) |
|
{ |
|
- r_type = get_real_reloc_type(r_type); |
|
+ Target_arm<big_endian>* arm_target = |
|
+ Target_arm<big_endian>::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<big_endian>::do_dynsym_value( |
|
// |
|
template<bool big_endian> |
|
unsigned int |
|
-Target_arm<big_endian>::get_real_reloc_type(unsigned int r_type) |
|
+Target_arm<big_endian>::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<big_endian>::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<unsigned int>* num_tracked_relocs, |
|
std::vector<unsigned int>* kept_section_id, |
|
const std::vector<Section_id>& id_section, |
|
+ const std::vector<uint64_t>& section_addraligns, |
|
std::vector<bool>* is_secn_or_group_unique, |
|
std::vector<std::string>* 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<unsigned int> num_tracked_relocs; |
|
+ std::vector<uint64_t> section_addraligns; |
|
std::vector<bool> is_secn_or_group_unique; |
|
std::vector<std::string> 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<int>(ORDER_MAX); ++i) |
|
{ |
|
if (i == static_cast<int>(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<size, big_endian>::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<size, big_endian>::do_rel |
|
Stub_table<size, big_endian>* stub_table |
|
= static_cast<Stub_table<size, big_endian>*>( |
|
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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size>::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<size>::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<size>::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 ')' |
|
diff -rup binutils.orig/gold/testsuite/pr18689.sh binutils-2.27/gold/testsuite/pr18689.sh |
|
--- binutils.orig/gold/testsuite/pr18689.sh 2017-01-17 10:17:46.062813402 +0000 |
|
+++ gold/testsuite/pr18689.sh 2017-01-17 10:30:51.583556117 +0000 |
|
@@ -23,6 +23,6 @@ |
|
|
|
set -e |
|
|
|
-egrep -q "..debug_mac[ro|info][ ]+*" pr18689.stdout |
|
+egrep -q "..debug_str[ ]+*" pr18689.stdout |
|
|
|
exit 0
|
|
|