diff options
author | Han Shen <shenhan@google.com> | 2016-08-26 15:50:15 -0700 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2017-02-22 09:40:07 +1030 |
commit | cd54b50e7b5ac662ca52d636c01dfaa506cdb07b (patch) | |
tree | 5dfdafc3d3599bcf304f253a0faf5563331faaac | |
parent | 8e1e2483a2240693d68c4e696ebfe6402b294834 (diff) | |
download | gdb-cd54b50e7b5ac662ca52d636c01dfaa506cdb07b.zip gdb-cd54b50e7b5ac662ca52d636c01dfaa506cdb07b.tar.gz gdb-cd54b50e7b5ac662ca52d636c01dfaa506cdb07b.tar.bz2 |
PR gold/20529 - relaxing loop never ends.
* powerpc.cc (Stub_table::min_size_threshold_): New member to
limit size.
(Stub_table::set_min_size_threshold): New member function.
(Stub_table::set_address_and_size): Add code to only allow size
increase.
(Target_powerpc::do_relax): Add code to record last size.
-rw-r--r-- | gold/ChangeLog | 12 | ||||
-rw-r--r-- | gold/powerpc.cc | 27 |
2 files changed, 36 insertions, 3 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index f5005ef..e551591 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,15 @@ +2017-02-22 Alan Modra <amodra@gmail.com> + + Apply from master + 2016-08-26 Han Shen <shenhan@google.com> + PR gold/20529 - relaxing loop never ends. + * powerpc.cc (Stub_table::min_size_threshold_): New member to + limit size. + (Stub_table::set_min_size_threshold): New member function. + (Stub_table::set_address_and_size): Add code to only allow size + increase. + (Target_powerpc::do_relax): Add code to record last size. + 2016-09-26 Cary Coutant <ccoutant@gmail.com> PR gold/20238 diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 60530ba..c269ae0 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -2982,7 +2982,13 @@ Target_powerpc<size, big_endian>::do_relax(int pass, 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 +3640,8 @@ class Stub_table : public Output_relaxed_input_section 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 +3732,11 @@ class Stub_table : public Output_relaxed_input_section 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 +3762,9 @@ class Stub_table : public Output_relaxed_input_section 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 +4029,13 @@ class Stub_table : public Output_relaxed_input_section 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 |