Index: layout.cc =================================================================== RCS file: /cvs/src/src/gold/layout.cc,v retrieving revision 1.241 diff -u -p -r1.241 layout.cc --- layout.cc 19 Dec 2012 02:55:15 -0000 1.241 +++ layout.cc 21 Dec 2012 06:20:28 -0000 @@ -1033,6 +1033,33 @@ Layout::init_fixed_output_section(const 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_fileset_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* || 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 Index: layout.h =================================================================== RCS file: /cvs/src/src/gold/layout.h,v retrieving revision 1.107 diff -u -p -r1.107 layout.h --- layout.h 19 Dec 2012 02:55:15 -0000 1.107 +++ layout.h 21 Dec 2012 06:20:28 -0000 @@ -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_; } Index: output.cc =================================================================== RCS file: /cvs/src/src/gold/output.cc,v retrieving revision 1.178 diff -u -p -r1.178 output.cc --- output.cc 19 Dec 2012 02:55:15 -0000 1.178 +++ output.cc 21 Dec 2012 06:20:29 -0000 @@ -2478,19 +2478,6 @@ Output_section::add_input_section(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 || 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 // 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_compa 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_ // 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_secti 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_sect 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())