• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修订版57f6d32deafcfec43bef5e963e12aacc0783a1e4 (tree)
时间2016-08-30 11:50:27
作者Alan Modra <amodra@gmai...>
CommiterAlan Modra

Log Message

[GOLD] correct grouping of stubs

This patch rewrites the rather obscure can_add_to_stub_group, fixing
a problem with the handling of sections containing conditional
external branches. When a section group contains any such section,
the group size needs to be limited to a much smaller size than groups
with only non-conditional external branches.

PR 20523
* powerpc.cc (class Stub_control): Add has14_. Comment owner_.
(Stub_control::can_add_to_stub_group): Correct grouping of
sections containing 14-bit external branches. When returning
false, set state_ to reflect the fact that we have one section
for the next group. Rewrite most of function for clarity.
Add and expand comments.
(Target_powerpc::do_relax): Print stub group size retry in hex.

更改概述

差异

--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,14 @@
1+2016-08-30 Alan Modra <amodra@gmail.com>
2+
3+ PR 20523
4+ * powerpc.cc (class Stub_control): Add has14_. Comment owner_.
5+ (Stub_control::can_add_to_stub_group): Correct grouping of
6+ sections containing 14-bit external branches. When returning
7+ false, set state_ to reflect the fact that we have one section
8+ for the next group. Rewrite most of function for clarity.
9+ Add and expand comments.
10+ (Target_powerpc::do_relax): Print stub group size retry in hex.
11+
112 2016-08-26 Han Shen <shenhan@google.com>
213
314 PR gold/20529 - relaxing loop never ends.
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -2441,7 +2441,7 @@ class Stub_control
24412441 : state_(NO_GROUP), stub_group_size_(abs(size)),
24422442 stub14_group_size_(abs(size) >> 10),
24432443 stubs_always_before_branch_(size < 0),
2444- suppress_size_errors_(no_size_errors),
2444+ suppress_size_errors_(no_size_errors), has14_(false),
24452445 group_end_addr_(0), owner_(NULL), output_section_(NULL)
24462446 {
24472447 }
@@ -2482,21 +2482,23 @@ class Stub_control
24822482 uint32_t stub14_group_size_;
24832483 bool stubs_always_before_branch_;
24842484 bool suppress_size_errors_;
2485+ bool has14_;
24852486 uint64_t group_end_addr_;
2487+ // owner_ and output_section_ specify the section to which stubs are
2488+ // attached. The stubs are placed at the end of this section.
24862489 const Output_section::Input_section* owner_;
24872490 Output_section* output_section_;
24882491 };
24892492
24902493 // Return true iff input section can be handled by current stub
2491-// group.
2494+// group. Sections are presented to this function in reverse order,
2495+// so the first section is the tail of the group.
24922496
24932497 bool
24942498 Stub_control::can_add_to_stub_group(Output_section* o,
24952499 const Output_section::Input_section* i,
24962500 bool has14)
24972501 {
2498- uint32_t group_size
2499- = has14 ? this->stub14_group_size_ : this->stub_group_size_;
25002502 bool whole_sec = o->order() == ORDER_INIT || o->order() == ORDER_FINI;
25012503 uint64_t this_size;
25022504 uint64_t start_addr = o->address();
@@ -2510,46 +2512,81 @@ Stub_control::can_add_to_stub_group(Output_section* o,
25102512 start_addr += i->relobj()->output_section_offset(i->shndx());
25112513 this_size = i->data_size();
25122514 }
2515+
2516+ uint32_t group_size
2517+ = has14 ? this->stub14_group_size_ : this->stub_group_size_;
25132518 uint64_t end_addr = start_addr + this_size;
2514- bool toobig = this_size > group_size;
25152519
2516- if (toobig && !this->suppress_size_errors_)
2520+ if (this_size > group_size && !this->suppress_size_errors_)
25172521 gold_warning(_("%s:%s exceeds group size"),
25182522 i->relobj()->name().c_str(),
25192523 i->relobj()->section_name(i->shndx()).c_str());
25202524
2521- if (this->state_ != HAS_STUB_SECTION
2522- && (!whole_sec || this->output_section_ != o)
2523- && (this->state_ == NO_GROUP
2524- || this->group_end_addr_ - end_addr < group_size))
2525- {
2526- this->owner_ = i;
2527- this->output_section_ = o;
2528- }
2525+ this->has14_ = this->has14_ || has14;
2526+ group_size = this->has14_ ? this->stub14_group_size_ : this->stub_group_size_;
25292527
2530- if (this->state_ == NO_GROUP)
2528+ if (this->state_ == HAS_STUB_SECTION)
25312529 {
2532- this->state_ = FINDING_STUB_SECTION;
2533- this->group_end_addr_ = end_addr;
2534- }
2535- else if (this->group_end_addr_ - start_addr < group_size)
2536- ;
2537- // Adding this section would make the group larger than GROUP_SIZE.
2538- else if (this->state_ == FINDING_STUB_SECTION
2539- && !this->stubs_always_before_branch_
2540- && !toobig)
2541- {
2542- // But wait, there's more! Input sections up to GROUP_SIZE
2543- // bytes before the stub table can be handled by it too.
2544- this->state_ = HAS_STUB_SECTION;
2545- this->group_end_addr_ = end_addr;
2530+ // Can we add this section, which is before the stubs, to the
2531+ // group?
2532+ if (this->group_end_addr_ - start_addr <= group_size)
2533+ return true;
25462534 }
25472535 else
25482536 {
2549- this->state_ = NO_GROUP;
2550- return false;
2537+ // Stubs are added at the end of "owner_".
2538+ // The current section can always be the stub owner, except when
2539+ // whole_sec is true and the current section isn't the last of
2540+ // the pasted sections. (This restriction for the whole_sec
2541+ // case is just to simplify the corner case mentioned in
2542+ // group_sections.)
2543+ // Note that "owner_" itself is not necessarily part of the
2544+ // group of sections served by these stubs!
2545+ if (!whole_sec || this->output_section_ != o)
2546+ {
2547+ this->owner_ = i;
2548+ this->output_section_ = o;
2549+ }
2550+
2551+ if (this->state_ == FINDING_STUB_SECTION)
2552+ {
2553+ if (this->group_end_addr_ - start_addr <= group_size)
2554+ return true;
2555+ // The group after the stubs has reached maximum size.
2556+ // Now see about adding sections before the stubs to the
2557+ // group. If the current section has a 14-bit branch and
2558+ // the group after the stubs exceeds stub14_group_size_
2559+ // (because they didn't have 14-bit branches), don't add
2560+ // sections before the stubs: The size of stubs for such a
2561+ // large group may exceed the reach of a 14-bit branch.
2562+ if (!this->stubs_always_before_branch_
2563+ && this_size <= group_size
2564+ && this->group_end_addr_ - end_addr <= group_size)
2565+ {
2566+ this->state_ = HAS_STUB_SECTION;
2567+ this->group_end_addr_ = end_addr;
2568+ return true;
2569+ }
2570+ }
2571+ else if (this->state_ == NO_GROUP)
2572+ {
2573+ // Only here on very first use of Stub_control
2574+ this->state_ = FINDING_STUB_SECTION;
2575+ this->group_end_addr_ = end_addr;
2576+ return true;
2577+ }
2578+ else
2579+ gold_unreachable();
25512580 }
2552- return true;
2581+
2582+ // The section fails to fit in the current group. Set up a few
2583+ // things for the next group. owner_ and output_section_ will be
2584+ // set later after we've retrieved those values for the current
2585+ // group.
2586+ this->state_ = FINDING_STUB_SECTION;
2587+ this->has14_ = has14;
2588+ this->group_end_addr_ = end_addr;
2589+ return false;
25532590 }
25542591
25552592 // Look over all the input sections, deciding where to place stubs.
@@ -2887,7 +2924,7 @@ Target_powerpc<size, big_endian>::do_relax(int pass,
28872924 }
28882925 this->stub_tables_.clear();
28892926 this->stub_group_size_ = this->stub_group_size_ / 4 * 3;
2890- gold_info(_("%s: stub group size is too large; retrying with %d"),
2927+ gold_info(_("%s: stub group size is too large; retrying with %#x"),
28912928 program_name, this->stub_group_size_);
28922929 this->group_sections(layout, task, true);
28932930 }