summaryrefslogtreecommitdiff
path: root/gold/object.cc
diff options
context:
space:
mode:
authorSriraman Tallam <tmsriram@google.com>2012-08-24 18:35:35 +0000
committerSriraman Tallam <tmsriram@google.com>2012-08-24 18:35:35 +0000
commit16164a6b00372ebc0360f6aa71337e5613278817 (patch)
tree503893149fa2b29775eafe985a0a537cf7433132 /gold/object.cc
parent92a289b3800274d15d440cea98c0df067da4c2ec (diff)
Patch adds support to allow plugins to map selected subset of sections to unique
segments. 2012-08-24 Sriraman Tallam <tmsriram@google.com> * 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<size, big_endian>::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 <tmsriram@google.com> * 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.
Diffstat (limited to 'gold/object.cc')
-rw-r--r--gold/object.cc110
1 files changed, 64 insertions, 46 deletions
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<size, big_endian>::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=<safe,all>): 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<int size, bool big_endian>
void
@@ -1238,26 +1242,44 @@ Sized_relobj_file<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<const char*>(pnamesu);
@@ -1355,7 +1373,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
Output_sections& out_sections(this->output_sections());
std::vector<Address>& 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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<Output_section*>(1);
out_section_offsets[i] = invalid_address;
@@ -1552,7 +1570,7 @@ Sized_relobj_file<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<Output_section*>(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<size, big_endian>::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<size, big_endian>::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<unsigned int>::const_iterator p = reloc_sections.begin();
p != reloc_sections.end();
@@ -1717,7 +1735,7 @@ Sized_relobj_file<size, big_endian>::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<unsigned int>::const_iterator p = eh_frame_sections.begin();
p != eh_frame_sections.end();
++p)
@@ -1740,7 +1758,7 @@ Sized_relobj_file<size, big_endian>::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<unsigned int>::const_iterator p
= debug_info_sections.begin();
@@ -1761,7 +1779,7 @@ Sized_relobj_file<size, big_endian>::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;