GNU Binutils with patches for OS216
修订版 | 57f6d32deafcfec43bef5e963e12aacc0783a1e4 (tree) |
---|---|
时间 | 2016-08-30 11:50:27 |
作者 | Alan Modra <amodra@gmai...> |
Commiter | Alan Modra |
[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.
@@ -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 | + | |
1 | 12 | 2016-08-26 Han Shen <shenhan@google.com> |
2 | 13 | |
3 | 14 | PR gold/20529 - relaxing loop never ends. |
@@ -2441,7 +2441,7 @@ class Stub_control | ||
2441 | 2441 | : state_(NO_GROUP), stub_group_size_(abs(size)), |
2442 | 2442 | stub14_group_size_(abs(size) >> 10), |
2443 | 2443 | stubs_always_before_branch_(size < 0), |
2444 | - suppress_size_errors_(no_size_errors), | |
2444 | + suppress_size_errors_(no_size_errors), has14_(false), | |
2445 | 2445 | group_end_addr_(0), owner_(NULL), output_section_(NULL) |
2446 | 2446 | { |
2447 | 2447 | } |
@@ -2482,21 +2482,23 @@ class Stub_control | ||
2482 | 2482 | uint32_t stub14_group_size_; |
2483 | 2483 | bool stubs_always_before_branch_; |
2484 | 2484 | bool suppress_size_errors_; |
2485 | + bool has14_; | |
2485 | 2486 | 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. | |
2486 | 2489 | const Output_section::Input_section* owner_; |
2487 | 2490 | Output_section* output_section_; |
2488 | 2491 | }; |
2489 | 2492 | |
2490 | 2493 | // 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. | |
2492 | 2496 | |
2493 | 2497 | bool |
2494 | 2498 | Stub_control::can_add_to_stub_group(Output_section* o, |
2495 | 2499 | const Output_section::Input_section* i, |
2496 | 2500 | bool has14) |
2497 | 2501 | { |
2498 | - uint32_t group_size | |
2499 | - = has14 ? this->stub14_group_size_ : this->stub_group_size_; | |
2500 | 2502 | bool whole_sec = o->order() == ORDER_INIT || o->order() == ORDER_FINI; |
2501 | 2503 | uint64_t this_size; |
2502 | 2504 | uint64_t start_addr = o->address(); |
@@ -2510,46 +2512,81 @@ Stub_control::can_add_to_stub_group(Output_section* o, | ||
2510 | 2512 | start_addr += i->relobj()->output_section_offset(i->shndx()); |
2511 | 2513 | this_size = i->data_size(); |
2512 | 2514 | } |
2515 | + | |
2516 | + uint32_t group_size | |
2517 | + = has14 ? this->stub14_group_size_ : this->stub_group_size_; | |
2513 | 2518 | uint64_t end_addr = start_addr + this_size; |
2514 | - bool toobig = this_size > group_size; | |
2515 | 2519 | |
2516 | - if (toobig && !this->suppress_size_errors_) | |
2520 | + if (this_size > group_size && !this->suppress_size_errors_) | |
2517 | 2521 | gold_warning(_("%s:%s exceeds group size"), |
2518 | 2522 | i->relobj()->name().c_str(), |
2519 | 2523 | i->relobj()->section_name(i->shndx()).c_str()); |
2520 | 2524 | |
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_; | |
2529 | 2527 | |
2530 | - if (this->state_ == NO_GROUP) | |
2528 | + if (this->state_ == HAS_STUB_SECTION) | |
2531 | 2529 | { |
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; | |
2546 | 2534 | } |
2547 | 2535 | else |
2548 | 2536 | { |
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(); | |
2551 | 2580 | } |
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; | |
2553 | 2590 | } |
2554 | 2591 | |
2555 | 2592 | // Look over all the input sections, deciding where to place stubs. |
@@ -2887,7 +2924,7 @@ Target_powerpc<size, big_endian>::do_relax(int pass, | ||
2887 | 2924 | } |
2888 | 2925 | this->stub_tables_.clear(); |
2889 | 2926 | 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"), | |
2891 | 2928 | program_name, this->stub_group_size_); |
2892 | 2929 | this->group_sections(layout, task, true); |
2893 | 2930 | } |