This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Patch to do reorder text and data sections according to a user specified sequence.


On 05/21/2010 06:41 PM, Sriraman Tallam wrote:
Hi Taras,

Did you get a chance to test the timings with the new patch ?
I've only tested it briefly on Friday. I'm having some problems with the new patch. It ranges from working perfectly to occasionally taking longer than the previous one and/or crashing. I'll let you know more once I have more time to play with it

Taras
Thanks,
-Sri.

On Thu, May 13, 2010 at 5:58 PM, Sriraman Tallam<tmsriram@google.com> wrote:
Hi Ian and Taras,

     Sorry for taking this long to get back. I have modified the patch
to address Taras' timing issue. Basically, I split patterns specified
into glob and non-glob by just looking for wild-card characters in the
pattern. Non-glob look-ups are through a hash table and fast. Glob
patterns are be searched linearly. So, if you specify non-glob symbol
names in the section ordering file, the link should be faster than
before.

     Further, I have prioritized non-glob patters over glob patterns.
Let me explain with an example :

If object main.o has sections .text._foov, .text._barv, and
.text._zapv and the seection ordering file is :
===============================
*bar*
.text.*
.text._barv
===============================

Then, .text._barv will be the last section in .text even though it
matches the first glob pattern.


The changes are :


        * 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::is_before_in_sequence):
        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.

Please let me know what you think.

Thanks,
-Sri.



On Tue, Mar 2, 2010 at 7:43 PM, Sriraman Tallam<tmsriram@google.com> wrote:
Hi Ian,

    I finally got around to making the changes you specified. Please
take a look when you get a chance.

        * layout.cc (Layout::read_layout_from_file): New method.
        (Layout::layout): Pass this pointer to add_input_section.
        (Layout::layout_eh_frame): Ditto.
        * layout.h (Layout::read_layout_from_file): New method.
        (Layout::input_section_order): New method.
        (Layout::input_section_order_): 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::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::section_order_index_): New
        member.
        (Output_section::Input_section_sort_entry::section_order_index): 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.h (Output_section::input_section_order_specified): New
        method.
        (Output_section::set_input_section_order_specified): New method.
        (Input_section::glob_pattern_number): New method.
        (Input_section::set_glob_pattern_number): New method.
        (Input_section::glob_pattern_number_): New member.
        (Input_section::Input_section_sort_section_order_index_compare): New
        struct.
        (Output_section::input_section_order_specified_): New member.
        * testsuite/Makefile.am (final_layout): New test case.
        * testsuite/Makefile.in: Regenerate.
        * testsuite/final_layout.cc: New file.
        * testsuite/final_layout.sh: New file


Thanks, -Sriraman.


On Thu, Feb 11, 2010 at 9:29 PM, Ian Lance Taylor<iant@google.com> wrote:
Sriraman Tallam<tmsriram@google.com> writes:

    I have attached a patch to reorder text and data sections in the
linker according to a user specified sequence. I have added a new
option --final-layout to do this. Currently, this could be done using
linker scripts but this patch makes it really easy to do this. Let me
explain using a simple example.

test.cc

void foo()
{ }

void bar()
{ }

int main()
{
   return 0;
}

$ g++ -ffunction-sections test.cc
$ nm -n a.out
...
000000000040038c T _Z3foov
0000000000400392 T _Z3barv
....

foo is laid to be before bar. Now, I can change this order as follows.

$ (echo "_Z3barv"&&  echo "_Z3foov")>  sequence.txt
$ g++ -ffunction-sections test.cc -Wl,--final-layout,sequence.txt
$ nm -n a.out
...
0000000000400658 T _Z3barv
000000000040065e T _Z3foov
...

The order is changed.

This can be done for text or data sections.

As I understand it, in linker terms, you are sorting the sections by suffixes. When two input sections are in the same output section, and both input sections have suffixes which appear in the file, then the input sections are sorted in the order in which the suffixes appear in the file.

I think it would be more natural to sort the input sections by name
rather than by suffix.  Since you don't want to fuss with writing
".text." all the time, suppose we say that we sort the input sections
by name, and we match the input section names using glob patterns.  We
already use glob patterns in linker scripts, so that is not a big
stretch.

Just a few comments on the rest of the patch.



+// Read the sequence of input sections from the file specified with
+// --final-layout.
+
+bool
+Layout::read_layout_from_file()
+{
+ const char* filename = parameters->options().final_layout();
+ char *buf = NULL;
+ size_t len = 0;
+ FILE* fp = fopen(filename, "r");
+
+ if (fp == NULL)
+ {
+ gold_error(_("Error opening layout file : %s\n"), filename);
+ gold_exit(false);
+ }
+
+ while (getline(&buf,&len, fp) != -1)
+ {
+ buf[strlen(buf) - 1] = 0;
+ this->input_section_order_.push_back(std::string(buf));
+ }
+
+ if (buf != NULL)
+ free(buf);
+
+ fclose(fp);
+ return true;
+}
The getline function is insufficient portable for use in gold.  Search
for std::getline in options.cc for an alternate approach you can use.
Emulate the error message style you see there too--no capital letter,
name the file, no space before colon, no \n.  And if you really want
to exit on failure, call gold_fatal.


+// If --final-layout option is used, reorder the input sections in
+// .text, .data, .bss and .rodata according to the specified sequence.
+
+void
+Layout::section_reorder()
+{
+ this->read_layout_from_file();
+
+ for (Section_list::iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ {
+ if (strcmp(".text", (*p)->name()) == 0
+ || strcmp(".data", (*p)->name()) == 0
+ || strcmp(".bss", (*p)->name()) == 0
+ || strcmp(".rodata", (*p)->name()) == 0)
+ (*p)->reorder_layout(this);
+ }
+}
Why restrict this to those output sections?  Why not sort input
sections in any output section?


+ DEFINE_string(final_layout, options::TWO_DASHES, '\0', NULL,
+ N_("Layout functions and data in the order specified."),
+ N_("FILENAME"));
I'm not sure I care for --final-layout as the option name.  Perhaps
--section-ordering-file?  Perhaps somebody else has a better idea.


+ // the future, we keep track of the sections. If the --final-layout
+ // 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().final_layout())
+ {
+ Input_section isecn(object, shndx, shdr.get_sh_size(), addralign);
+ isecn.set_section_name(secname);
+ this->input_sections_.push_back(isecn);
+ }
Don't save the string here, that's just going to bloat memory usage.
Instead, when you read the file, give each line a number.  Then match
the section name which you have here against the list of patterns.  If
you find a match, store the number in the Input_section structure.
Also, if you find a match, set a flag in the output section.  Then
sort the sections, by number, in a function called from
set_final_data_size.

You will see that there is already some section ordering in that
function, which is used to implement constructor/destructor priority
ordering.  I guess the priority ordering should take precedence.
Maybe.

Ian



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]