From 16164a6b00372ebc0360f6aa71337e5613278817 Mon Sep 17 00:00:00 2001 From: Sriraman Tallam Date: Fri, 24 Aug 2012 18:35:35 +0000 Subject: Patch adds support to allow plugins to map selected subset of sections to unique segments. 2012-08-24 Sriraman Tallam * gold.cc (queue_middle_tasks): Call layout again when unique segments for sections is desired. * layout.cc (Layout::Layout): Initialize new members. (Layout::get_output_section_flags): New function. (Layout::choose_output_section): Call get_output_section_flags. (Layout::layout): Make output section for mapping to a unique segment. (Layout::insert_section_segment_map): New function. (Layout::attach_allocated_section_to_segment): Make unique segment for output sections marked so. (Layout::segment_precedes): Check for unique segments when sorting. * layout.h (Layout::Unique_segment_info): New struct. (Layout::Section_segment_map): New typedef. (Layout::insert_section_segment_map): New function. (Layout::get_output_section_flags): New function. (Layout::is_unique_segment_for_sections_specified): New function. (Layout::set_unique_segment_for_sections_specified): New function. (Layout::unique_segment_for_sections_specified_): New member. (Layout::section_segment_map_): New member. * object.cc (Sized_relobj_file::do_layout): Rename is_gc_pass_one to is_pass_one. Rename is_gc_pass_two to is_pass_two. Rename is_gc_or_icf to is_two_pass. Check for which pass based on whether symbols data is present. Make it two pass when unique segments for sections is desired. * output.cc (Output_section::Output_section): Initialize new members. * output.h (Output_section::is_unique_segment): New function. (Output_section::set_is_unique_segment): New function. (Output_section::is_unique_segment_): New member. (Output_section::extra_segment_flags): New function. (Output_section::set_extra_segment_flags): New function. (Output_section::extra_segment_flags_): New member. (Output_section::segment_alignment): New function. (Output_section::set_segment_alignment): New function. (Output_section::segment_alignment_): New member. (Output_segment::Output_segment): Initialize is_unique_segment_. (Output_segment::is_unique_segment): New function. (Output_segment::set_is_unique_segment): New function. (Output_segment::is_unique_segment_): New member. * plugin.cc (allow_unique_segment_for_sections): New function. (unique_segment_for_sections): New function. (Plugin::load): Add new functions to transfer vector. * Makefile.am (plugin_final_layout.readelf.stdout): Add readelf output. * Makefile.in: Regenerate. * testsuite/plugin_final_layout.sh: Check if unique segment functionality works. * testsuite/plugin_section_order.c (onload): Check if new interfaces are available. (allow_unique_segment_for_sections): New global. (unique_segment_for_sections): New global. (claim_file_hook): Call allow_unique_segment_for_sections. (all_symbols_read_hook): Call unique_segment_for_sections. 2012-08-24 Sriraman Tallam * plugin-api.h (ld_plugin_allow_unique_segment_for_sections): New interface. (ld_plugin_unique_segment_for_sections): New interface. (LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS): New enum val. (LDPT_UNIQUE_SEGMENT_FOR_SECTIONS): New enum val. (tv_allow_unique_segment_for_sections): New member. (tv_unique_segment_for_sections): New member. --- gold/object.cc | 110 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 46 deletions(-) (limited to 'gold/object.cc') diff --git a/gold/object.cc b/gold/object.cc index 417ccfc7c4..6c0c187726 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -1221,15 +1221,19 @@ Sized_relobj_file::layout_eh_frame_section( // whether they should be included in the link. If they should, we // pass them to the Layout object, which will return an output section // and an offset. -// During garbage collection (--gc-sections) and identical code folding -// (--icf), this function is called twice. When it is called the first -// time, it is for setting up some sections as roots to a work-list for -// --gc-sections and to do comdat processing. Actual layout happens the -// second time around after all the relevant sections have been determined. -// The first time, is_worklist_ready or is_icf_ready is false. It is then -// set to true after the garbage collection worklist or identical code -// folding is processed and the relevant sections to be kept are -// determined. Then, this function is called again to layout the sections. +// This function is called twice sometimes, two passes, when mapping +// of input sections to output sections must be delayed. +// This is true for the following : +// * Garbage collection (--gc-sections): Some input sections will be +// discarded and hence the assignment must wait until the second pass. +// In the first pass, it is for setting up some sections as roots to +// a work-list for --gc-sections and to do comdat processing. +// * Identical Code Folding (--icf=): Some input sections +// will be folded and hence the assignment must wait. +// * Using plugins to map some sections to unique segments: Mapping +// some sections to unique segments requires mapping them to unique +// output sections too. This can be done via plugins now and this +// information is not available in the first pass. template void @@ -1238,26 +1242,44 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, Read_symbols_data* sd) { const unsigned int shnum = this->shnum(); - bool is_gc_pass_one = ((parameters->options().gc_sections() - && !symtab->gc()->is_worklist_ready()) - || (parameters->options().icf_enabled() - && !symtab->icf()->is_icf_ready())); - bool is_gc_pass_two = ((parameters->options().gc_sections() - && symtab->gc()->is_worklist_ready()) - || (parameters->options().icf_enabled() - && symtab->icf()->is_icf_ready())); + /* Should this function be called twice? */ + bool is_two_pass = (parameters->options().gc_sections() + || parameters->options().icf_enabled() + || layout->is_unique_segment_for_sections_specified()); - bool is_gc_or_icf = (parameters->options().gc_sections() - || parameters->options().icf_enabled()); + /* Only one of is_pass_one and is_pass_two is true. Both are false when + a two-pass approach is not needed. */ + bool is_pass_one = false; + bool is_pass_two = false; - // Both is_gc_pass_one and is_gc_pass_two should not be true. - gold_assert(!(is_gc_pass_one && is_gc_pass_two)); + Symbols_data* gc_sd = NULL; + /* Check if do_layout needs to be two-pass. If so, find out which pass + should happen. In the first pass, the data in sd is saved to be used + later in the second pass. */ + if (is_two_pass) + { + gc_sd = this->get_symbols_data(); + if (gc_sd == NULL) + { + gold_assert(sd != NULL); + is_pass_one = true; + } + else + { + if (parameters->options().gc_sections()) + gold_assert(symtab->gc()->is_worklist_ready()); + if (parameters->options().icf_enabled()) + gold_assert(symtab->icf()->is_icf_ready()); + is_pass_two = true; + } + } + if (shnum == 0) return; - Symbols_data* gc_sd = NULL; - if (is_gc_pass_one) + + if (is_pass_one) { // During garbage collection save the symbols data to use it when // re-entering this function. @@ -1265,10 +1287,6 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, this->copy_symbols_data(gc_sd, sd, This::shdr_size * shnum); this->set_symbols_data(gc_sd); } - else if (is_gc_pass_two) - { - gc_sd = this->get_symbols_data(); - } const unsigned char* section_headers_data = NULL; section_size_type section_names_size; @@ -1277,7 +1295,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, const unsigned char* symbol_names_data = NULL; section_size_type symbol_names_size; - if (is_gc_or_icf) + if (is_two_pass) { section_headers_data = gc_sd->section_headers_data; section_names_size = gc_sd->section_names_size; @@ -1303,9 +1321,9 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, const unsigned char* pshdrs; // Get the section names. - const unsigned char* pnamesu = (is_gc_or_icf) - ? gc_sd->section_names_data - : sd->section_names->data(); + const unsigned char* pnamesu = (is_two_pass + ? gc_sd->section_names_data + : sd->section_names->data()); const char* pnames = reinterpret_cast(pnamesu); @@ -1355,7 +1373,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, Output_sections& out_sections(this->output_sections()); std::vector
& out_section_offsets(this->section_offsets()); - if (!is_gc_pass_two) + if (!is_pass_two) { out_sections.resize(shnum); out_section_offsets.resize(shnum); @@ -1365,7 +1383,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, // do here. if (this->input_file()->just_symbols()) { - if (!is_gc_pass_two) + if (!is_pass_two) { delete sd->section_headers; sd->section_headers = NULL; @@ -1417,7 +1435,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, const char* name = pnames + shdr.get_sh_name(); - if (!is_gc_pass_two) + if (!is_pass_two) { if (this->handle_gnu_warning_section(name, i, symtab)) { @@ -1491,7 +1509,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, } } - if (is_gc_pass_one && parameters->options().gc_sections()) + if (is_pass_one && parameters->options().gc_sections()) { if (this->is_section_name_included(name) || layout->keep_input_section (this, name) @@ -1537,7 +1555,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, && strcmp(name, ".eh_frame") == 0 && this->check_eh_frame_flags(&shdr)) { - if (is_gc_pass_one) + if (is_pass_one) { out_sections[i] = reinterpret_cast(1); out_section_offsets[i] = invalid_address; @@ -1552,7 +1570,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, continue; } - if (is_gc_pass_two && parameters->options().gc_sections()) + if (is_pass_two && parameters->options().gc_sections()) { // This is executed during the second pass of garbage // collection. do_layout has been called before and some @@ -1577,7 +1595,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, } } - if (is_gc_pass_two && parameters->options().icf_enabled()) + if (is_pass_two && parameters->options().icf_enabled()) { if (out_sections[i] == NULL) { @@ -1611,7 +1629,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, // should_defer_layout should be false. if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC)) { - gold_assert(!is_gc_pass_two); + gold_assert(!is_pass_two); this->deferred_layout_.push_back(Deferred_layout(i, name, pshdrs, reloc_shndx[i], @@ -1626,11 +1644,11 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, // During gc_pass_two if a section that was previously deferred is // found, do not layout the section as layout_deferred_sections will // do it later from gold.cc. - if (is_gc_pass_two + if (is_pass_two && (out_sections[i] == reinterpret_cast(2))) continue; - if (is_gc_pass_one) + if (is_pass_one) { // This is during garbage collection. The out_sections are // assigned in the second call to this function. @@ -1661,7 +1679,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, } } - if (!is_gc_pass_two) + if (!is_pass_two) layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this); // When doing a relocatable link handle the reloc sections at the @@ -1670,7 +1688,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, if (emit_relocs) this->size_relocatable_relocs(); - gold_assert(!(is_gc_or_icf) || reloc_sections.empty()); + gold_assert(!is_two_pass || reloc_sections.empty()); for (std::vector::const_iterator p = reloc_sections.begin(); p != reloc_sections.end(); @@ -1717,7 +1735,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, } // Handle the .eh_frame sections at the end. - gold_assert(!is_gc_pass_one || eh_frame_sections.empty()); + gold_assert(!is_pass_one || eh_frame_sections.empty()); for (std::vector::const_iterator p = eh_frame_sections.begin(); p != eh_frame_sections.end(); ++p) @@ -1740,7 +1758,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, // When building a .gdb_index section, scan the .debug_info and // .debug_types sections. - gold_assert(!is_gc_pass_one + gold_assert(!is_pass_one || (debug_info_sections.empty() && debug_types_sections.empty())); for (std::vector::const_iterator p = debug_info_sections.begin(); @@ -1761,7 +1779,7 @@ Sized_relobj_file::do_layout(Symbol_table* symtab, i, reloc_shndx[i], reloc_type[i]); } - if (is_gc_pass_two) + if (is_pass_two) { delete[] gc_sd->section_headers_data; delete[] gc_sd->section_names_data; -- cgit v1.2.3