From edcac0c105556029774320bc8288beb472e999b5 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 21 Dec 2012 06:24:31 +0000 Subject: * layout.cc (Layout::special_ordering_of_input_section): New function. (Layout::layout): If input section requires special ordering, must sort input sections. (Layout::make_output_section): May sort .text input sections. (Layout::is_section_name_prefix_grouped): Remove. * layout.h (class Layout): Declare special_ordering_of_input_section. Don't declare is_section_name_prefix_grouped. * output.cc (Output_section::add_input_section): Revert last change. (Output_section::Input_section_sort::match_file_name): Don't crash if called on output section data. (Output_section::Input_section_sort_compare): Sort based on special ordering. (Output_section::Input_section_sort_section_order_index_compare): Revert last patch. (Output_section::sort_attached_input_sections): Likewise. --- gold/ChangeLog | 27 ++++++++++++++-- gold/layout.cc | 57 +++++++++++++++++++++++++--------- gold/layout.h | 13 +++++--- gold/output.cc | 98 +++++++++++++++------------------------------------------- 4 files changed, 100 insertions(+), 95 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 62ddbc6..ae4f830 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,14 +1,35 @@ +2012-12-20 Ian Lance Taylor + + * layout.cc (Layout::special_ordering_of_input_section): New + function. + (Layout::layout): If input section requires special ordering, must + sort input sections. + (Layout::make_output_section): May sort .text input sections. + (Layout::is_section_name_prefix_grouped): Remove. + * layout.h (class Layout): Declare + special_ordering_of_input_section. Don't declare + is_section_name_prefix_grouped. + * output.cc (Output_section::add_input_section): Revert last + change. + (Output_section::Input_section_sort::match_file_name): Don't crash + if called on output section data. + (Output_section::Input_section_sort_compare): Sort based on + special ordering. + (Output_section::Input_section_sort_section_order_index_compare): + Revert last patch. + (Output_section::sort_attached_input_sections): Likewise. + 2012-12-18 Sriraman Tallam - * layout.cc (Layout::is_section_name_prefix_grouped): New function. + * layout.cc (Layout::is_section_name_prefix_grouped): New function. * layout.h (Layout::is_section_name_prefix_grouped): New function. * output.cc (Output_section::add_input_section): Check if section name contains special prefix. Keep input sections to sort such sections. (Output_section::Input_section_sort_section_order_index_compare ::operator()): Group sections according to prefixes. - * (Output_section::sort_attached_input_sections): Add condition - to Input_section_entry constructor call. + (Output_section::sort_attached_input_sections): Add condition to + Input_section_entry constructor call. * testsuite/Makefile.am (text_section_grouping): New test. * testsuite/Makefile.in: Regenerate. * testsuite/text_section_grouping.cc: New file. diff --git a/gold/layout.cc b/gold/layout.cc index 62b4cad..f7f0e7e 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -1033,6 +1033,33 @@ Layout::init_fixed_output_section(const char* name, return os; } +// Return the index by which an input section should be ordered. This +// is used to sort some .text sections, for compatibility with GNU ld. + +int +Layout::special_ordering_of_input_section(const char* name) +{ + // The GNU linker has some special handling for some sections that + // wind up in the .text section. Sections that start with these + // prefixes must appear first, and must appear in the order listed + // here. + static const char* const text_section_sort[] = + { + ".text.unlikely", + ".text.exit", + ".text.startup", + ".text.hot" + }; + + for (size_t i = 0; + i < sizeof(text_section_sort) / sizeof(text_section_sort[0]); + i++) + if (is_prefix_of(text_section_sort[i], name)) + return i; + + return -1; +} + // Return the output section to use for input section SHNDX, with name // NAME, with header HEADER, from object OBJECT. RELOC_SHNDX is the // index of a relocation section which applies to this section, or 0 @@ -1120,6 +1147,13 @@ Layout::layout(Sized_relobj_file* object, unsigned int shndx, || strcmp(name, ".dtors") == 0)))) os->set_must_sort_attached_input_sections(); + // By default the GNU linker sorts some special text sections ahead + // of others. We are compatible. + if (!this->script_options_->saw_sections_clause() + && !parameters->options().relocatable() + && Layout::special_ordering_of_input_section(name) >= 0) + os->set_must_sort_attached_input_sections(); + // If this is a .ctors or .ctors.* section being mapped to a // .init_array section, or a .dtors or .dtors.* section being mapped // to a .fini_array section, we will need to reverse the words if @@ -1607,6 +1641,15 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, || strcmp(name, ".dtors") == 0)))) os->set_may_sort_attached_input_sections(); + // The GNU linker by default sorts .text.{unlikely,exit,startup,hot} + // sections before other .text sections. We are compatible. We + // need to know that this might happen before we attach any input + // sections. + if (!this->script_options_->saw_sections_clause() + && !parameters->options().relocatable() + && strcmp(name, ".text") == 0) + os->set_may_sort_attached_input_sections(); + // Check for .stab*str sections, as .stab* sections need to link to // them. if (type == elfcpp::SHT_STRTAB @@ -2409,20 +2452,6 @@ Layout::relaxation_loop_body( return off; } -// By default, gold groups input sections with certain prefixes. This -// function returns true if this section name NAME contains such a prefix. - -bool -Layout::is_section_name_prefix_grouped(const char *name) -{ - if (is_prefix_of(".text.unlikely", name) - || is_prefix_of(".text.startup", name) - || is_prefix_of(".text.hot", name)) - return true; - - return false; -} - // Search the list of patterns and find the postion of the given section // name in the output section. If the section name matches a glob // pattern and a non-glob name, then the non-glob position takes diff --git a/gold/layout.h b/gold/layout.h index 71f1aa7..6da9607 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -553,11 +553,14 @@ class Layout void insert_section_segment_map(Const_section_id secn, Unique_segment_info *s); - // By default, gold groups input sections with certain prefixes. This - // function returns true if this section name NAME contains such a prefix. - bool - is_section_name_prefix_grouped(const char *name); - + // Some input sections require special ordering, for compatibility + // with GNU ld. Given the name of an input section, return -1 if it + // does not require special ordering. Otherwise, return the index + // by which it should be ordered compared to other input sections + // that require special ordering. + static int + special_ordering_of_input_section(const char* name); + bool is_section_ordering_specified() { return this->section_ordering_specified_; } diff --git a/gold/output.cc b/gold/output.cc index 39eb1b7..f2321b7 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -2478,19 +2478,6 @@ Output_section::add_input_section(Layout* layout, } } - // The GNU linker groups input sections whose names match .text.unlikely.*. - // This is used to get better code layout. We are compatible. - // Additionally, it could also be beneficial to group .text.hot.*, - // .text.startup.* prefixed input sections. Function - // "is_section_name_prefix_grouped" in layout.cc determines the input - // section prefixes that must be grouped. - if (!have_sections_script - && !parameters->options().relocatable() - && !this->input_section_order_specified() - && !this->must_sort_attached_input_sections() - && layout->is_section_name_prefix_grouped(secname)) - this->set_input_section_order_specified(); - // We need to keep track of this section if we are already keeping // track of sections, or if we are relaxing. Also, if this is a // section which requires sorting, or which may require sorting in @@ -2504,8 +2491,7 @@ Output_section::add_input_section(Layout* layout, || this->must_sort_attached_input_sections() || parameters->options().user_set_Map() || parameters->target().may_relax() - || layout->is_section_ordering_specified() - || this->input_section_order_specified()) + || layout->is_section_ordering_specified()) { Input_section isecn(object, shndx, input_section_size, addralign); /* If section ordering is requested by specifying a ordering file, @@ -3337,7 +3323,11 @@ class Output_section::Input_section_sort_entry // in order to better support gcc, and we need to be compatible. bool match_file_name(const char* file_name) const - { return Layout::match_file_name(this->input_section_.relobj(), file_name); } + { + if (this->input_section_.is_output_section_data()) + return false; + return Layout::match_file_name(this->input_section_.relobj(), file_name); + } // Returns 1 if THIS should appear before S in section order, -1 if S // appears before THIS and 0 if they are not comparable. @@ -3409,6 +3399,19 @@ Output_section::Input_section_sort_compare::operator()( return s1.index() < s2.index(); } + // Some input section names have special ordering requirements. + int o1 = Layout::special_ordering_of_input_section(s1.section_name().c_str()); + int o2 = Layout::special_ordering_of_input_section(s2.section_name().c_str()); + if (o1 != o2) + { + if (o1 < 0) + return false; + else if (o2 < 0) + return true; + else + return o1 < o2; + } + // A section with a priority follows a section without a priority. bool s1_has_priority = s1.has_priority(); bool s2_has_priority = s2.has_priority(); @@ -3498,9 +3501,7 @@ Output_section::Input_section_sort_init_fini_compare::operator()( // Return true if S1 should come before S2. Sections that do not match // any pattern in the section ordering file are placed ahead of the sections -// that match some pattern. This function is also used to group text according -// to their prefix. The following prefixes are recognized: ".text.startup", -// ".text.hot", and ".text.unlikely". +// that match some pattern. bool Output_section::Input_section_sort_section_order_index_compare::operator()( @@ -3510,59 +3511,11 @@ Output_section::Input_section_sort_section_order_index_compare::operator()( unsigned int s1_secn_index = s1.input_section().section_order_index(); unsigned int s2_secn_index = s2.input_section().section_order_index(); - // If section ordering is specified, it takes precedence. - if (s1_secn_index != s2_secn_index) - return s1_secn_index < s2_secn_index; - - // Sort all the sections with no names to the end. - if (!s1.section_has_name() || !s2.section_has_name()) - { - if (s1.section_has_name()) - return true; - if (s2.section_has_name()) - return false; - return s1.index() < s2.index(); - } - - // If it is a text section use the following order: - // .text.unlikely, .text.startup, .text.hot. The prefixes - // must match those in function is_section_name_prefix_grouped - // in layout.cc - const char* section_prefix [] = - { - ".text.unlikely", - ".text.startup", - ".text.hot" - }; - - const unsigned int num_prefixes - = sizeof(section_prefix) / sizeof(const char*); - - unsigned int s1_group_index = num_prefixes; - unsigned int s2_group_index = num_prefixes; - - unsigned int flag_done = 0; - for (unsigned int i = 0; i < num_prefixes && flag_done < 2; i++) - { - if (s1_group_index == num_prefixes - && is_prefix_of(section_prefix[i], s1.section_name().c_str())) - { - s1_group_index = i; - flag_done++; - } - - if (s2_group_index == num_prefixes - && is_prefix_of(section_prefix[i], s2.section_name().c_str())) - { - s2_group_index = i; - flag_done++; - } - } - - if (s1_group_index == s2_group_index) + // Keep input order if section ordering cannot determine order. + if (s1_secn_index == s2_secn_index) return s1.index() < s2.index(); - else - return s1_group_index < s2_group_index; + + return s1_secn_index < s2_secn_index; } // This updates the section order index of input sections according to the @@ -3623,8 +3576,7 @@ Output_section::sort_attached_input_sections() p != this->input_sections_.end(); ++p, ++i) sort_list.push_back(Input_section_sort_entry(*p, i, - (this->must_sort_attached_input_sections() - || this->input_section_order_specified()))); + this->must_sort_attached_input_sections())); // Sort the input sections. if (this->must_sort_attached_input_sections()) -- cgit v1.1