diff options
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 16 | ||||
-rw-r--r-- | gold/layout.cc | 29 | ||||
-rw-r--r-- | gold/output.cc | 49 | ||||
-rw-r--r-- | gold/output.h | 10 |
4 files changed, 95 insertions, 9 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index d6e806d..514310d 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,19 @@ +2010-03-01 Doug Kwan <dougkwan@google.com> + + * layout.cc (Layout::Layout): Force section types of .init_array*, + .preinit_array* and .fini_array* sections. + * output.cc (Output_section::Input_section_sort_entry::has_priority): + Fix check of return value of std::string::find.(). + (Output_section::Input_section_sort_compare::operator()): Remove + comment about .init_array. + (Output_section::Input_section_sort_init_fini_compare::operator()): + New method. + (Output_section::sort_attached_input_sections): Handle .init_array + and .fini_array specially. + * output.h (Output_section::Inut_section_sort_compare): Update + comment. + (Output_section::Input_section_sort_init_fini_compare): New struct. + 2010-02-26 Doug Kwan <dougkwan@google.com> * arm.cc (Target_arm::Relocate::reloc_is_non_pic): Treat diff --git a/gold/layout.cc b/gold/layout.cc index c721ba6..f95813b 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -582,19 +582,40 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx, Output_section* os; + // Sometimes .init_array*, .preinit_array* and .fini_array* do not have + // correct section types. Force them here. + elfcpp::Elf_Word sh_type = shdr.get_sh_type(); + if (sh_type == elfcpp::SHT_PROGBITS) + { + static const char init_array_prefix[] = ".init_array"; + static const char preinit_array_prefix[] = ".preinit_array"; + static const char fini_array_prefix[] = ".fini_array"; + static size_t init_array_prefix_size = sizeof(init_array_prefix) - 1; + static size_t preinit_array_prefix_size = + sizeof(preinit_array_prefix) - 1; + static size_t fini_array_prefix_size = sizeof(fini_array_prefix) - 1; + + if (strncmp(name, init_array_prefix, init_array_prefix_size) == 0) + sh_type = elfcpp::SHT_INIT_ARRAY; + else if (strncmp(name, preinit_array_prefix, preinit_array_prefix_size) + == 0) + sh_type = elfcpp::SHT_PREINIT_ARRAY; + else if (strncmp(name, fini_array_prefix, fini_array_prefix_size) == 0) + sh_type = elfcpp::SHT_FINI_ARRAY; + } + // In a relocatable link a grouped section must not be combined with // any other sections. if (parameters->options().relocatable() && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0) { name = this->namepool_.add(name, true, NULL); - os = this->make_output_section(name, shdr.get_sh_type(), - shdr.get_sh_flags(), false, false, - false, false, false); + os = this->make_output_section(name, sh_type, shdr.get_sh_flags(), false, + false, false, false, false); } else { - os = this->choose_output_section(object, name, shdr.get_sh_type(), + os = this->choose_output_section(object, name, sh_type, shdr.get_sh_flags(), true, false, false, false, false, false); if (os == NULL) diff --git a/gold/output.cc b/gold/output.cc index 1c2533c..d49f08b 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -2695,7 +2695,7 @@ class Output_section::Input_section_sort_entry has_priority() const { gold_assert(this->section_has_name_); - return this->section_name_.find('.', 1); + return this->section_name_.find('.', 1) != std::string::npos; } // Return true if this an input file whose base name matches @@ -2773,8 +2773,6 @@ Output_section::Input_section_sort_compare::operator()( } // A section with a priority follows a section without a priority. - // The GNU linker does this for all but .init_array sections; until - // further notice we'll assume that that is an mistake. bool s1_has_priority = s1.has_priority(); bool s2_has_priority = s2.has_priority(); if (s1_has_priority && !s2_has_priority) @@ -2791,6 +2789,42 @@ Output_section::Input_section_sort_compare::operator()( return s1.index() < s2.index(); } +// Return true if S1 should come before S2 in an .init_array or .fini_array +// output section. + +bool +Output_section::Input_section_sort_init_fini_compare::operator()( + const Output_section::Input_section_sort_entry& s1, + const Output_section::Input_section_sort_entry& s2) const +{ + // We 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(); + } + + // A section without a priority follows a section with a priority. + // This is the reverse of .ctors and .dtors sections. + bool s1_has_priority = s1.has_priority(); + bool s2_has_priority = s2.has_priority(); + if (s1_has_priority && !s2_has_priority) + return true; + if (!s1_has_priority && s2_has_priority) + return false; + + // Otherwise we sort by name. + int compare = s1.section_name().compare(s2.section_name()); + if (compare != 0) + return compare < 0; + + // Otherwise we keep the input order. + return s1.index() < s2.index(); +} + // Sort the input sections attached to an output section. void @@ -2819,7 +2853,14 @@ Output_section::sort_attached_input_sections() sort_list.push_back(Input_section_sort_entry(*p, i)); // Sort the input sections. - std::sort(sort_list.begin(), sort_list.end(), Input_section_sort_compare()); + if (this->type() == elfcpp::SHT_PREINIT_ARRAY + || this->type() == elfcpp::SHT_INIT_ARRAY + || this->type() == elfcpp::SHT_FINI_ARRAY) + std::sort(sort_list.begin(), sort_list.end(), + Input_section_sort_init_fini_compare()); + else + std::sort(sort_list.begin(), sort_list.end(), + Input_section_sort_compare()); // Copy the sorted input sections back to our list. this->input_sections_.clear(); diff --git a/gold/output.h b/gold/output.h index 9008bdd..a63f07c 100644 --- a/gold/output.h +++ b/gold/output.h @@ -3378,7 +3378,7 @@ class Output_section : public Output_data // This class is used to sort the input sections. class Input_section_sort_entry; - // This is the sort comparison function. + // This is the sort comparison function for ctors and dtors. struct Input_section_sort_compare { bool @@ -3386,6 +3386,14 @@ class Output_section : public Output_data const Input_section_sort_entry&) const; }; + // This is the sort comparison function for .init_array and .fini_array. + struct Input_section_sort_init_fini_compare + { + bool + operator()(const Input_section_sort_entry&, + const Input_section_sort_entry&) const; + }; + // Fill data. This is used to fill in data between input sections. // It is also used for data statements (BYTE, WORD, etc.) in linker // scripts. When we have to keep track of the input sections, we |