From: Sriraman Tallam Date: Tue, 1 Jun 2010 23:37:58 +0000 (+0000) Subject: * gold.h (is_wildcard_string): New function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6e9ba2ca9c85e1d04123b87af1d57d57a5e6e82a;p=binutils-gdb.git * gold.h (is_wildcard_string): New function. * layout.cc (Layout::layout): Pass this pointer to add_input_section. (Layout::layout_eh_frame): Ditto. (Layout::find_section_order_index): New method. (Layout::read_layout_from_file): New method. * layout.h (Layout::find_section_order_index): New method. (Layout::read_layout_from_file): New method. (Layout::input_section_position_): New private member. (Layout::input_section_glob_): New private member. * main.cc (main): Call read_layout_from_file here. * options.h (--section-ordering-file): New option. * output.cc (Output_section::input_section_order_specified_): New member. (Output_section::Output_section): Initialize new member. (Output_section::add_input_section): Add new parameter. Keep input sections when --section-ordering-file is used. (Output_section::set_final_data_size): Sort input sections when section ordering file is specified. (Output_section::Input_section_sort_entry): Add new parameter. Check sorting type. (Output_section::Input_section_sort_entry::compare_section_ordering): New method. (Output_section::Input_section_sort_compare::operator()): Change to consider section_order_index. (Output_section::Input_section_sort_init_fini_compare::operator()): Change to consider section_order_index. (Output_section::Input_section_sort_section_order_index_compare ::operator()): New method. (Output_section::sort_attached_input_sections): Change to sort according to section order when specified. (Output_section::add_input_section<32, true>): Add new parameter. (Output_section::add_input_section<64, true>): Add new parameter. (Output_section::add_input_section<32, false>): Add new parameter. (Output_section::add_input_section<64, false>): Add new parameter. * output.h (Output_section::add_input_section): Add new parameter. (Output_section::input_section_order_specified): New method. (Output_section::set_input_section_order_specified): New method. (Input_section::Input_section): Initialize section_order_index_. (Input_section::section_order_index): New method. (Input_section::set_section_order_index): New method. (Input_section::section_order_index_): New member. (Input_section::Input_section_sort_section_order_index_compare): New struct. (Output_section::input_section_order_specified_): New member. * script-sections.cc (is_wildcard_string): Delete and move modified method to gold.h. (Output_section_element_input::Output_section_element_input): Modify call to is_wildcard_string. (Output_section_element_input::Input_section_pattern ::Input_section_pattern): Ditto. (Output_section_element_input::Output_section_element_input): Ditto. * testsuite/Makefile.am (final_layout): New test case. * testsuite/Makefile.in: Regenerate. * testsuite/final_layout.cc: New file. * testsuite/final_layout.sh: New file. --- diff --git a/gold/ChangeLog b/gold/ChangeLog index 2b4e94b9168..95e683f4152 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,62 @@ +2010-06-01 Sriraman Tallam + + * gold.h (is_wildcard_string): New function. + * layout.cc (Layout::layout): Pass this pointer to add_input_section. + (Layout::layout_eh_frame): Ditto. + (Layout::find_section_order_index): New method. + (Layout::read_layout_from_file): New method. + * layout.h (Layout::find_section_order_index): New method. + (Layout::read_layout_from_file): New method. + (Layout::input_section_position_): New private member. + (Layout::input_section_glob_): New private member. + * main.cc (main): Call read_layout_from_file here. + * options.h (--section-ordering-file): New option. + * output.cc (Output_section::input_section_order_specified_): New + member. + (Output_section::Output_section): Initialize new member. + (Output_section::add_input_section): Add new parameter. + Keep input sections when --section-ordering-file is used. + (Output_section::set_final_data_size): Sort input sections when + section ordering file is specified. + (Output_section::Input_section_sort_entry): Add new parameter. + Check sorting type. + (Output_section::Input_section_sort_entry::compare_section_ordering): + New method. + (Output_section::Input_section_sort_compare::operator()): Change to + consider section_order_index. + (Output_section::Input_section_sort_init_fini_compare::operator()): + Change to consider section_order_index. + (Output_section::Input_section_sort_section_order_index_compare + ::operator()): New method. + (Output_section::sort_attached_input_sections): Change to sort + according to section order when specified. + (Output_section::add_input_section<32, true>): Add new parameter. + (Output_section::add_input_section<64, true>): Add new parameter. + (Output_section::add_input_section<32, false>): Add new parameter. + (Output_section::add_input_section<64, false>): Add new parameter. + * output.h (Output_section::add_input_section): Add new parameter. + (Output_section::input_section_order_specified): New + method. + (Output_section::set_input_section_order_specified): New method. + (Input_section::Input_section): Initialize section_order_index_. + (Input_section::section_order_index): New method. + (Input_section::set_section_order_index): New method. + (Input_section::section_order_index_): New member. + (Input_section::Input_section_sort_section_order_index_compare): New + struct. + (Output_section::input_section_order_specified_): New member. + * script-sections.cc (is_wildcard_string): Delete and move modified + method to gold.h. + (Output_section_element_input::Output_section_element_input): Modify + call to is_wildcard_string. + (Output_section_element_input::Input_section_pattern + ::Input_section_pattern): Ditto. + (Output_section_element_input::Output_section_element_input): Ditto. + * testsuite/Makefile.am (final_layout): New test case. + * testsuite/Makefile.in: Regenerate. + * testsuite/final_layout.cc: New file. + * testsuite/final_layout.sh: New file. + 2010-06-01 Rafael Espindola * plugin.cc (Plugin::load): Pass the output name to the plugin. diff --git a/gold/gold.h b/gold/gold.h index 04b69115099..90f1f7d1f4e 100644 --- a/gold/gold.h +++ b/gold/gold.h @@ -401,6 +401,15 @@ string_hash(const Char_type* s) return h; } +// Return whether STRING contains a wildcard character. This is used +// to speed up matching. + +inline bool +is_wildcard_string(const char* s) +{ + return strpbrk(s, "?*[") != NULL; +} + } // End namespace gold. #endif // !defined(GOLD_GOLD_H) diff --git a/gold/layout.cc b/gold/layout.cc index 36cfa8bd744..a39b1157b08 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -26,8 +26,10 @@ #include #include #include +#include #include #include +#include #include #include "libiberty.h" #include "md5.h" @@ -668,7 +670,7 @@ Layout::layout(Sized_relobj* object, unsigned int shndx, // FIXME: Handle SHF_LINK_ORDER somewhere. - *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx, + *off = os->add_input_section(this, object, shndx, name, shdr, reloc_shndx, this->script_options_->saw_sections_clause()); this->have_added_input_section_ = true; @@ -886,7 +888,7 @@ Layout::layout_eh_frame(Sized_relobj* object, // We couldn't handle this .eh_frame section for some reason. // Add it as a normal section. bool saw_sections_clause = this->script_options_->saw_sections_clause(); - *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx, + *off = os->add_input_section(this, object, shndx, name, shdr, reloc_shndx, saw_sections_clause); this->have_added_input_section_ = true; } @@ -1642,6 +1644,72 @@ Layout::relaxation_loop_body( return off; } +// 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 +// precedence. Return 0 if no match is found. + +unsigned int +Layout::find_section_order_index(const std::string& section_name) +{ + Unordered_map::iterator map_it; + map_it = this->input_section_position_.find(section_name); + if (map_it != this->input_section_position_.end()) + return map_it->second; + + // Absolute match failed. Linear search the glob patterns. + std::vector::iterator it; + for (it = this->input_section_glob_.begin(); + it != this->input_section_glob_.end(); + ++it) + { + if (fnmatch((*it).c_str(), section_name.c_str(), FNM_NOESCAPE) == 0) + { + map_it = this->input_section_position_.find(*it); + gold_assert(map_it != this->input_section_position_.end()); + return map_it->second; + } + } + return 0; +} + +// Read the sequence of input sections from the file specified with +// --section-ordering-file. + +void +Layout::read_layout_from_file() +{ + const char* filename = parameters->options().section_ordering_file(); + std::ifstream in; + std::string line; + + in.open(filename); + if (!in) + gold_fatal(_("unable to open --section-ordering-file file %s: %s"), + filename, strerror(errno)); + + std::getline(in, line); // this chops off the trailing \n, if any + unsigned int position = 1; + + while (in) + { + if (!line.empty() && line[line.length() - 1] == '\r') // Windows + line.resize(line.length() - 1); + // Ignore comments, beginning with '#' + if (line[0] == '#') + { + std::getline(in, line); + continue; + } + this->input_section_position_[line] = position; + // Store all glob patterns in a vector. + if (is_wildcard_string(line.c_str())) + this->input_section_glob_.push_back(line); + position++; + std::getline(in, line); + } +} + // Finalize the layout. When this is called, we have created all the // output sections and all the output segments which are based on // input sections. We have several things to do, and we have to do diff --git a/gold/layout.h b/gold/layout.h index 912be31e154..55ad7a6a3a5 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -308,6 +308,12 @@ class Layout const char* name, const elfcpp::Shdr& shdr, unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset); + unsigned int + find_section_order_index(const std::string&); + + void + read_layout_from_file(); + // Layout an input reloc section when doing a relocatable link. The // section is RELOC_SHNDX in OBJECT, with data in SHDR. // DATA_SECTION is the reloc section to which it refers. RR is the @@ -1037,6 +1043,10 @@ class Layout Segment_states* segment_states_; // A relaxation debug checker. We only create one when in debugging mode. Relaxation_debug_check* relaxation_debug_check_; + // Hash a pattern to its position in the section ordering file. + Unordered_map input_section_position_; + // Vector of glob only patterns in the section_ordering file. + std::vector input_section_glob_; }; // This task handles writing out data in output sections which is not diff --git a/gold/main.cc b/gold/main.cc index e3df9c08484..631f1ac2d2c 100644 --- a/gold/main.cc +++ b/gold/main.cc @@ -234,6 +234,9 @@ main(int argc, char** argv) layout.incremental_inputs()->report_inputs(command_line.inputs()); } + if (parameters->options().section_ordering_file()) + layout.read_layout_from_file(); + // Get the search path from the -L options. Dirsearch search_path; search_path.initialize(&workqueue, &command_line.options().library_path()); diff --git a/gold/options.h b/gold/options.h index 1e328a8dbec..cf1c15375fb 100644 --- a/gold/options.h +++ b/gold/options.h @@ -892,6 +892,10 @@ class General_options N_("Add DIR to link time shared library search path"), N_("DIR")); + DEFINE_string(section_ordering_file, options::TWO_DASHES, '\0', NULL, + N_("Layout sections in the order specified."), + N_("FILENAME")); + DEFINE_special(section_start, options::TWO_DASHES, '\0', N_("Set address of section"), N_("SECTION=ADDRESS")); diff --git a/gold/output.cc b/gold/output.cc index 752a1d37a04..3cfcf1ebeb4 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1933,6 +1933,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, found_in_sections_clause_(false), has_load_address_(false), info_uses_section_index_(false), + input_section_order_specified_(false), may_sort_attached_input_sections_(false), must_sort_attached_input_sections_(false), attached_input_sections_are_sorted_(false), @@ -1994,7 +1995,8 @@ Output_section::set_entsize(uint64_t v) template off_t -Output_section::add_input_section(Sized_relobj* object, +Output_section::add_input_section(Layout* layout, + Sized_relobj* object, unsigned int shndx, const char* secname, const elfcpp::Shdr& shdr, @@ -2090,16 +2092,30 @@ Output_section::add_input_section(Sized_relobj* object, // 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 - // the future, we keep track of the sections. + // the future, we keep track of the sections. If the + // --section-ordering-file option is used to specify the order of + // sections, we need to keep track of sections. if (have_sections_script || !this->input_sections_.empty() || this->may_sort_attached_input_sections() || this->must_sort_attached_input_sections() || parameters->options().user_set_Map() - || parameters->target().may_relax()) - this->input_sections_.push_back(Input_section(object, shndx, - shdr.get_sh_size(), - addralign)); + || parameters->target().may_relax() + || parameters->options().section_ordering_file()) + { + Input_section isecn(object, shndx, shdr.get_sh_size(), addralign); + if (parameters->options().section_ordering_file()) + { + unsigned int section_order_index = + layout->find_section_order_index(std::string(secname)); + if (section_order_index != 0) + { + isecn.set_section_order_index(section_order_index); + this->set_input_section_order_specified(); + } + } + this->input_sections_.push_back(isecn); + } return aligned_offset_in_section; } @@ -2623,7 +2639,8 @@ Output_section::set_final_data_size() return; } - if (this->must_sort_attached_input_sections()) + if (this->must_sort_attached_input_sections() + || this->input_section_order_specified()) this->sort_attached_input_sections(); uint64_t address = this->address(); @@ -2700,12 +2717,14 @@ class Output_section::Input_section_sort_entry { } Input_section_sort_entry(const Input_section& input_section, - unsigned int index) + unsigned int index, + bool must_sort_attached_input_sections) : input_section_(input_section), index_(index), section_has_name_(input_section.is_input_section() || input_section.is_relaxed_input_section()) { - if (this->section_has_name_) + if (this->section_has_name_ + && must_sort_attached_input_sections) { // This is only called single-threaded from Layout::finalize, // so it is OK to lock. Unfortunately we have no way to pass @@ -2782,6 +2801,22 @@ class Output_section::Input_section_sort_entry return memcmp(base_name + base_len - 2, ".o", 2) == 0; } + // Returns 0 if sections are not comparable. Returns 1 if THIS is the + // first section in order, returns -1 for S. + int + compare_section_ordering(const Input_section_sort_entry& s) const + { + gold_assert(this->index_ != -1U); + if (this->input_section_.section_order_index() == 0 + || s.input_section().section_order_index() == 0) + return 0; + if (this->input_section_.section_order_index() + < s.input_section().section_order_index()) + return 1; + else + return -1; + } + private: // The Input_section we are sorting. Input_section input_section_; @@ -2843,6 +2878,12 @@ Output_section::Input_section_sort_compare::operator()( if (!s1_has_priority && s2_has_priority) return true; + // Check if a section order exists for these sections through a section + // ordering file. If sequence_num is 0, an order does not exist. + int sequence_num = s1.compare_section_ordering(s2); + if (sequence_num != 0) + return sequence_num == 1; + // Otherwise we sort by name. int compare = s1.section_name().compare(s2.section_name()); if (compare != 0) @@ -2879,6 +2920,12 @@ Output_section::Input_section_sort_init_fini_compare::operator()( if (!s1_has_priority && s2_has_priority) return false; + // Check if a section order exists for these sections through a section + // ordering file. If sequence_num is 0, an order does not exist. + int sequence_num = s1.compare_section_ordering(s2); + if (sequence_num != 0) + return sequence_num == 1; + // Otherwise we sort by name. int compare = s1.section_name().compare(s2.section_name()); if (compare != 0) @@ -2888,6 +2935,22 @@ Output_section::Input_section_sort_init_fini_compare::operator()( return s1.index() < s2.index(); } +// Return true if S1 should come before S2. +bool +Output_section::Input_section_sort_section_order_index_compare::operator()( + const Output_section::Input_section_sort_entry& s1, + const Output_section::Input_section_sort_entry& s2) const +{ + // Check if a section order exists for these sections through a section + // ordering file. If sequence_num is 0, an order does not exist. + int sequence_num = s1.compare_section_ordering(s2); + if (sequence_num != 0) + return sequence_num == 1; + + // Otherwise we keep the input order. + return s1.index() < s2.index(); +} + // Sort the input sections attached to an output section. void @@ -2913,17 +2976,27 @@ Output_section::sort_attached_input_sections() for (Input_section_list::iterator p = this->input_sections_.begin(); p != this->input_sections_.end(); ++p, ++i) - sort_list.push_back(Input_section_sort_entry(*p, i)); + sort_list.push_back(Input_section_sort_entry(*p, i, + this->must_sort_attached_input_sections())); // Sort the input sections. - 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()); + if (this->must_sort_attached_input_sections()) + { + 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()); + } else - std::sort(sort_list.begin(), sort_list.end(), - Input_section_sort_compare()); + { + gold_assert(parameters->options().section_ordering_file()); + std::sort(sort_list.begin(), sort_list.end(), + Input_section_sort_section_order_index_compare()); + } // Copy the sorted input sections back to our list. this->input_sections_.clear(); @@ -2931,6 +3004,7 @@ Output_section::sort_attached_input_sections() p != sort_list.end(); ++p) this->input_sections_.push_back(p->input_section()); + sort_list.clear(); // Remember that we sorted the input sections, since we might get // called again. @@ -4466,6 +4540,7 @@ Output_file::close() template off_t Output_section::add_input_section<32, false>( + Layout* layout, Sized_relobj<32, false>* object, unsigned int shndx, const char* secname, @@ -4478,6 +4553,7 @@ Output_section::add_input_section<32, false>( template off_t Output_section::add_input_section<32, true>( + Layout* layout, Sized_relobj<32, true>* object, unsigned int shndx, const char* secname, @@ -4490,6 +4566,7 @@ Output_section::add_input_section<32, true>( template off_t Output_section::add_input_section<64, false>( + Layout* layout, Sized_relobj<64, false>* object, unsigned int shndx, const char* secname, @@ -4502,6 +4579,7 @@ Output_section::add_input_section<64, false>( template off_t Output_section::add_input_section<64, true>( + Layout* layout, Sized_relobj<64, true>* object, unsigned int shndx, const char* secname, diff --git a/gold/output.h b/gold/output.h index eb5d83671cc..1a0a8da42c4 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2515,8 +2515,8 @@ class Output_section : public Output_data // within the output section. template off_t - add_input_section(Sized_relobj* object, unsigned int shndx, - const char *name, + add_input_section(Layout* layout, Sized_relobj* object, + unsigned int shndx, const char *name, const elfcpp::Shdr& shdr, unsigned int reloc_shndx, bool have_sections_script); @@ -2736,6 +2736,18 @@ class Output_section : public Output_data set_may_sort_attached_input_sections() { this->may_sort_attached_input_sections_ = true; } + // Returns true if input sections must be sorted according to the + // order in which their name appear in the --section-ordering-file. + bool + input_section_order_specified() + { return this->input_section_order_specified_; } + + // Record that input sections must be sorted as some of their names + // match the patterns specified through --section-ordering-file. + void + set_input_section_order_specified() + { this->input_section_order_specified_ = true; } + // Return whether the input sections attached to this output section // require sorting. This is used to handle constructor priorities // compatibly with GNU ld. @@ -2972,7 +2984,8 @@ class Output_section : public Output_data Input_section(Relobj* object, unsigned int shndx, off_t data_size, uint64_t addralign) : shndx_(shndx), - p2align_(ffsll(static_cast(addralign))) + p2align_(ffsll(static_cast(addralign))), + section_order_index_(0) { gold_assert(shndx != OUTPUT_SECTION_CODE && shndx != MERGE_DATA_SECTION_CODE @@ -2984,7 +2997,8 @@ class Output_section : public Output_data // For a non-merge output section. Input_section(Output_section_data* posd) - : shndx_(OUTPUT_SECTION_CODE), p2align_(0) + : shndx_(OUTPUT_SECTION_CODE), p2align_(0), + section_order_index_(0) { this->u1_.data_size = 0; this->u2_.posd = posd; @@ -2995,7 +3009,8 @@ class Output_section : public Output_data : shndx_(is_string ? MERGE_STRING_SECTION_CODE : MERGE_DATA_SECTION_CODE), - p2align_(0) + p2align_(0), + section_order_index_(0) { this->u1_.entsize = entsize; this->u2_.posd = posd; @@ -3003,12 +3018,25 @@ class Output_section : public Output_data // For a relaxed input section. Input_section(Output_relaxed_input_section *psection) - : shndx_(RELAXED_INPUT_SECTION_CODE), p2align_(0) + : shndx_(RELAXED_INPUT_SECTION_CODE), p2align_(0), + section_order_index_(0) { this->u1_.data_size = 0; this->u2_.poris = psection; } + unsigned int + section_order_index() const + { + return this->section_order_index_; + } + + void + set_section_order_index(unsigned int number) + { + this->section_order_index_ = number; + } + // The required alignment. uint64_t addralign() const @@ -3234,6 +3262,9 @@ class Output_section : public Output_data // For RELAXED_INPUT_SECTION_CODE, the data. Output_relaxed_input_section* poris; } u2_; + // The line number of the pattern it matches in the --section-ordering-file + // file. It is 0 if does not match any pattern. + unsigned int section_order_index_; }; // Store the list of input sections for this Output_section into the @@ -3540,6 +3571,15 @@ class Output_section : public Output_data const Input_section_sort_entry&) const; }; + // This is the sort comparison function when a section order is specified + // from an input file. + struct Input_section_sort_section_order_index_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 @@ -3707,6 +3747,9 @@ class Output_section : public Output_data // section, false if it means the symbol index of the corresponding // section symbol. bool info_uses_section_index_ : 1; + // True if input sections attached to this output section have to be + // sorted according to a specified order. + bool input_section_order_specified_ : 1; // True if the input sections attached to this output section may // need sorting. bool may_sort_attached_input_sections_ : 1; diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 3266115a9e7..2988d106f21 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -983,15 +983,6 @@ class Output_section_element_fill : public Output_section_element Expression* val_; }; -// Return whether STRING contains a wildcard character. This is used -// to speed up matching. - -static inline bool -is_wildcard_string(const std::string& s) -{ - return strpbrk(s.c_str(), "?*[") != NULL; -} - // An input section specification in an output section class Output_section_element_input : public Output_section_element @@ -1035,7 +1026,7 @@ class Output_section_element_input : public Output_section_element Input_section_pattern(const char* patterna, size_t patternlena, Sort_wildcard sorta) : pattern(patterna, patternlena), - pattern_is_wildcard(is_wildcard_string(this->pattern)), + pattern_is_wildcard(is_wildcard_string(this->pattern.c_str())), sort(sorta) { } }; @@ -1102,7 +1093,7 @@ Output_section_element_input::Output_section_element_input( if (spec->file.name.length != 1 || spec->file.name.value[0] != '*') this->filename_pattern_.assign(spec->file.name.value, spec->file.name.length); - this->filename_is_wildcard_ = is_wildcard_string(this->filename_pattern_); + this->filename_is_wildcard_ = is_wildcard_string(this->filename_pattern_.c_str()); if (spec->input_sections.exclude != NULL) { @@ -1111,7 +1102,7 @@ Output_section_element_input::Output_section_element_input( p != spec->input_sections.exclude->end(); ++p) { - bool is_wildcard = is_wildcard_string(*p); + bool is_wildcard = is_wildcard_string((*p).c_str()); this->filename_exclusions_.push_back(std::make_pair(*p, is_wildcard)); } diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index afb704d1554..67d03335f13 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -193,6 +193,18 @@ icf_safe_so_test_1.stdout: icf_safe_so_test icf_safe_so_test_2.stdout: icf_safe_so_test $(TEST_READELF) -h icf_safe_so_test > icf_safe_so_test_2.stdout +check_SCRIPTS += final_layout.sh +check_DATA += final_layout.stdout +MOSTLYCLEANFILES += final_layout +final_layout.o: final_layout.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -fdata-sections -g -o $@ $< +final_layout_sequence.txt: + (echo "*_Z3barv*" && echo ".text._Z3bazv" && echo "*_Z3foov*" && echo "*global_varb*" && echo "*global_vara*" && echo "*global_varc*") > final_layout_sequence.txt +final_layout: final_layout.o final_layout_sequence.txt gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt final_layout.o +final_layout.stdout: final_layout + $(TEST_NM) final_layout > final_layout.stdout + check_PROGRAMS += icf_virtual_function_folding_test MOSTLYCLEANFILES += icf_virtual_function_folding_test icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 4470580f116..efc3bcd7ff8 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -62,6 +62,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.sh weak_plt.sh \ @@ -94,6 +95,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test_2.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_1.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_2.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \ @@ -118,6 +120,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test icf_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test icf_safe_so_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_virtual_function_folding_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test \ @@ -2609,6 +2612,14 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_safe_so_test > icf_safe_so_test_1.stdout @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_so_test_2.stdout: icf_safe_so_test @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -h icf_safe_so_test > icf_safe_so_test_2.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout.o: final_layout.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fdata-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout_sequence.txt: +@GCC_TRUE@@NATIVE_LINKER_TRUE@ (echo "*_Z3barv*" && echo ".text._Z3bazv" && echo "*_Z3foov*" && echo "*global_varb*" && echo "*global_vara*" && echo "*global_varc*") > final_layout_sequence.txt +@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout: final_layout.o final_layout_sequence.txt gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt final_layout.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout.stdout: final_layout +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) final_layout > final_layout.stdout @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIE -g -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test: icf_virtual_function_folding_test.o gcctestdir/ld diff --git a/gold/testsuite/final_layout.cc b/gold/testsuite/final_layout.cc new file mode 100644 index 00000000000..f5338859935 --- /dev/null +++ b/gold/testsuite/final_layout.cc @@ -0,0 +1,48 @@ +// final_layout.cc -- a test case for gold + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Sriraman Tallam . + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if --section-ordering-file orders +// the .text and .data sections correctly as specified. + +int global_vara; +int global_varb; +int global_varc; + +int foo() +{ + return 1; +} + +int bar() +{ + return 1; +} + +int baz() +{ + return 1; +} + +int main() +{ + return 1; +} diff --git a/gold/testsuite/final_layout.sh b/gold/testsuite/final_layout.sh new file mode 100755 index 00000000000..ed7ad78b9e3 --- /dev/null +++ b/gold/testsuite/final_layout.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +# final_layout.sh -- test --final-layout + +# Copyright 2010 Free Software Foundation, Inc. +# Written by Sriraman Tallam . + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if --section-ordering-file works as +# intended. File final_layout.cc is in this test. + +check() +{ + func_addr_1=$((16#`grep $2 $1 | awk '{print $1}'`)) + func_addr_2=$((16#`grep $3 $1 | awk '{print $1}'`)) + if [ $func_addr_1 -gt $func_addr_2 ] + then + echo "final layout of" $2 "and" $3 "is not right." + exit 1 + fi +} + +check final_layout.stdout "_Z3barv" "_Z3bazv" +check final_layout.stdout "_Z3bazv" "_Z3foov" +check final_layout.stdout "global_varb" "global_vara" +check final_layout.stdout "global_vara" "global_varc"