From: Alan Modra Date: Wed, 7 Dec 2016 03:45:59 +0000 (+1030) Subject: [GOLD] PowerPC --stub-group-multi X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1c3a5fbe155614a0f87079b953df0d7618e0ab50;p=binutils-gdb.git [GOLD] PowerPC --stub-group-multi Adds a new option, defaulting to off, that allows a group of stubs to serve multiple output sections. Prior to this patch powerpc gold allowed this unconditionally, which is a little unsafe with clever code that discards/reuses sections at runtime. * options.h (--stub-group-multi): New PowerPC option. * powerpc.cc (Stub_control): Add multi_os_ var and param to constructor. Sort start_ var later. Comment State. (Stub_control::can_add_to_stub_group): Heed multi_os_. (Target_powerpc::group_sections): Update. --- diff --git a/gold/ChangeLog b/gold/ChangeLog index 367cb02f0e3..2fcd80ec130 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,11 @@ +2016-12-07 Alan Modra + + * options.h (--stub-group-multi): New PowerPC option. + * powerpc.cc (Stub_control): Add multi_os_ var and param + to constructor. Sort start_ var later. Comment State. + (Stub_control::can_add_to_stub_group): Heed multi_os_. + (Target_powerpc::group_sections): Update. + 2016-12-07 Alan Modra PR gold/20878 diff --git a/gold/options.h b/gold/options.h index 90ccc8058d5..67226673656 100644 --- a/gold/options.h +++ b/gold/options.h @@ -1219,6 +1219,10 @@ class General_options "stubs are always after the group. 1 means use default size"), N_("SIZE")); + DEFINE_bool(stub_group_multi, options::TWO_DASHES, '\0', false, + N_("(PowerpC only) Allow a group of stubs to serve multiple " + "output sections"), NULL); + DEFINE_uint(split_stack_adjust_size, options::TWO_DASHES, '\0', 0x4000, N_("Stack size when -fsplit-stack function calls non-split"), N_("SIZE")); diff --git a/gold/powerpc.cc b/gold/powerpc.cc index f7636183e11..068f5ca602a 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -2441,11 +2441,11 @@ class Stub_control // value of the parameter --stub-group-size. If --stub-group-size // is passed a negative value, we restrict stubs to be always after // the stubbed branches. - Stub_control(int32_t size, bool no_size_errors) - : state_(NO_GROUP), stub_group_size_(abs(size)), - stubs_always_after_branch_(size < 0), - suppress_size_errors_(no_size_errors), group_size_(0), - group_start_addr_(0), owner_(NULL), output_section_(NULL) + Stub_control(int32_t size, bool no_size_errors, bool multi_os) + : stub_group_size_(abs(size)), stubs_always_after_branch_(size < 0), + suppress_size_errors_(no_size_errors), multi_os_(multi_os), + state_(NO_GROUP), group_size_(0), group_start_addr_(0), + owner_(NULL), output_section_(NULL) { } @@ -2475,15 +2475,20 @@ class Stub_control private: typedef enum { + // Initial state. NO_GROUP, + // Adding group sections before the stubs. FINDING_STUB_SECTION, + // Adding group sections after the stubs. HAS_STUB_SECTION } State; - State state_; uint32_t stub_group_size_; bool stubs_always_after_branch_; bool suppress_size_errors_; + // True if a stub group can serve multiple output sections. + bool multi_os_; + State state_; // 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. @@ -2537,7 +2542,19 @@ Stub_control::can_add_to_stub_group(Output_section* o, ? this_size : (long long) end_addr - this->group_start_addr_)); - if (this->state_ == HAS_STUB_SECTION) + if (this->state_ == NO_GROUP) + { + // Only here on very first use of Stub_control + this->owner_ = i; + this->output_section_ = o; + this->state_ = FINDING_STUB_SECTION; + this->group_size_ = group_size; + this->group_start_addr_ = start_addr; + return true; + } + else if (!this->multi_os_ && this->output_section_ != o) + ; + else if (this->state_ == HAS_STUB_SECTION) { // Can we add this section, which is after the stubs, to the // group? @@ -2571,20 +2588,13 @@ Stub_control::can_add_to_stub_group(Output_section* o, return true; } } - else if (this->state_ == NO_GROUP) - { - // Only here on very first use of Stub_control - this->owner_ = i; - this->output_section_ = o; - this->state_ = FINDING_STUB_SECTION; - this->group_size_ = group_size; - this->group_start_addr_ = start_addr; - return true; - } else gold_unreachable(); - gold_debug(DEBUG_TARGET, "nope, didn't fit\n"); + gold_debug(DEBUG_TARGET, + !this->multi_os_ && this->output_section_ != o + ? "nope, new output section\n" + : "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 @@ -2604,7 +2614,8 @@ Target_powerpc::group_sections(Layout* layout, const Task*, bool no_size_errors) { - Stub_control stub_control(this->stub_group_size_, no_size_errors); + Stub_control stub_control(this->stub_group_size_, no_size_errors, + parameters->options().stub_group_multi()); // Group input sections and insert stub table Stub_table_owner* table_owner = NULL;