public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Sriraman Tallam <tmsriram@google.com>
To: Ian Lance Taylor <iant@google.com>
Cc: Cary Coutant <ccoutant@google.com>, binutils <binutils@sourceware.org>
Subject: Re: [patch] Gold linker patch to provide plugin support for mapping some text sections to an unique ELF segment.
Date: Thu, 23 Aug 2012 04:14:00 -0000	[thread overview]
Message-ID: <CAAs8HmwCE61Mex95HWC0+ji1=QrziV7dwpAO0BZZpx0QOY8QhA@mail.gmail.com> (raw)
In-Reply-To: <CAKOQZ8w=jWq4=OCc=eXEF=5mYyN89rPUj=B=URcT+aLpCoZKMg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 8972 bytes --]

Hi Ian,

    I have made all the changes and attached the patch.

Thanks,
-Sri.

On Wed, Aug 22, 2012 at 10:59 AM, Ian Lance Taylor <iant@google.com> wrote:
> On Thu, Aug 9, 2012 at 2:32 PM, Sriraman Tallam <tmsriram@google.com> wrote:
>>
>>         * gold.cc (queue_middle_tasks): Call layout again when unique
>>         segments for sections is desired.
>>         * layout.cc (Layout::Layout): Initialize new members.
>>         (Layout::layout): Make output section for mapping to a unique segment.
>>         (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::get_section_segment_map): 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.
>>
>>
>>         * 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.
>
>> +      if (it != this->section_segment_map_.end())
>> +     {
>> +       // We know the name of the output section, directly call
>> +       // get_output_section here by-passing choose_output_section.
>> +       elfcpp::Elf_Xword flags = shdr.get_sh_flags();
>
> Please invert this conditional, so the common and shorter case appears.  That is
>   if (it == this->section_segment_map_.end())
>     os = this->choose_output_section(...);
>   else
>     {
>       ...
>     }
>
>> +       // We know the name of the output section, directly call
>> +       // get_output_section here by-passing choose_output_section.
>> +       elfcpp::Elf_Xword flags = shdr.get_sh_flags();
>> +       // Some flags in the input section should not be automatically
>> +       // copied to the output section.
>> +       flags &= ~ (elfcpp::SHF_INFO_LINK
>> +                   | elfcpp::SHF_GROUP
>> +                   | elfcpp::SHF_MERGE
>> +                   | elfcpp::SHF_STRINGS);
>> +
>> +       // We only clear the SHF_LINK_ORDER flag in for
>> +       // a non-relocatable link.
>> +       if (!parameters->options().relocatable())
>> +         flags &= ~elfcpp::SHF_LINK_ORDER;
>
> This code is too finicky to have two copies.  Please refactor into a
> common function one way or another.
>
>> +       os_name = this->namepool_.add_with_length(os_name, strlen(os_name),
>> +                                                 true, &name_key);
>
> Don't call add_with_length(x, strlen(x), ...).  Just call add().
>
>> +      // If this segment is marked unique, skip.
>
> This comment adds nothing to the code.
>
>> +       if (os->segment_alignment())
>
> os->segment_alignment is not a bool: write os->segment_alignment() != 0.
>
>> +  typedef struct
>> +  {
>> +    // Identifier for the Segment.  ELF Segments dont have names.
>> +    const char* name;
>> +    // Segment flags.
>> +    uint64_t flags;
>> +    uint64_t align;
>> +  } Unique_segment_info;
>
> This is C++, not C.  Don't write typedef struct { } S.  Just write struct S { }.
>
> The align field should have a comment.  The flags field comment should
> say something like "Additional segment flags."
>
>> +  Section_segment_map&
>> +  get_section_segment_map()
>> +  { return this->section_segment_map_; }
>
> gold doesn't use non-const references as function parameter or return
> types.  This should be a pointer.
>
>> +       gold_assert (sd != NULL);
>
> Remove space before left parenthesis.
>
> Thanks for the cleanups here.
>
>> +  const unsigned char* pnamesu = (is_two_pass)
>>                                ? gc_sd->section_names_data
>>                                : sd->section_names->data();
>
> It's not new in this patch, but the parenthesization here is wrong.
> It should be
>    ... = (is_two_pass
>            ? ...
>            : ...);
>
> The ? and : should be lined up under the start of the condition (i.e.,
> under the 'i').
>
> L +  gold_assert(!(is_two_pass) || reloc_sections.empty());
>
> No need to parenthesize is_two_pass.
>
>> +  uint64_t extra_segment_flags() const
>> +  { return extra_segment_flags_; }
>> +
>> +  void
>> +  set_extra_segment_flags(uint64_t flags)
>> +  { extra_segment_flags_ = flags; }
>> +
>> +  uint64_t segment_alignment() const
>> +  { return segment_alignment_; }
>> +
>> +  void
>> +  set_segment_alignment(uint64_t align)
>> +  { segment_alignment_ = align; }
>
> This functions are all missing "this->".
>
>> +  bool
>> +  is_unique_segment() const
>> +  { return is_unique_segment_; }
>> +
>> +  // Mark segment as unique, happens when linker plugins request that
>> +  // certain input sections be mapped to unique segments.
>> +  void
>> +  set_is_unique_segment()
>> +  { this->is_unique_segment_ = true; }
>
> Missing this-> here too.
>
>> +  Layout* layout = parameters->options().plugins()->layout();
>> +  gold_assert (layout != NULL);
>
> Somewhere here you should ensure that the plugin called the
> LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS entry point.
>
>> +  Layout::Unique_segment_info* s = static_cast<Layout::Unique_segment_info*>
>> +      (malloc(sizeof(Layout::Unique_segment_info)));
>
> This is C++.  You mean
>   Layout::Unique_segment_info* s = new Unique_segment_info;
>
>> +      section_segment_map[secn_id] = s;
>
> Rather than have Layout return a pointer to its private data member, I
> would prefer to see a Layout method that saves this value.  And that
> Layout method should assert unique_segment_for_sections_specified_.
>
>> +check_DATA += plugin_final_layout.stdout plugin_final_layout.readelf.stdout
>
> Stick to a single '.' per fliename.
> plugin_final_layout_readelf.stdout is fine here.
>
>> With readelf -l, an ELF Section to Segment mapping is printed as :
>
> readelf can be a bit unpredictable: I recommend using the -W option as well.
>
>> +/* The linker's interface for specifying that a subset of sections is
>> +   to be mapped to a unique segment.  This should be invoked before
>> +   unique_segment_for_sections, preferably in the claim_file handler.  */
>
> This is a "must", not a "should".  How about something along the lines
> of "If the plugin wants to call unique_segment_for_sections, it must
> call this function from a claim_file handler or when it is first
> loaded."
>
> Sorry for the slow review.
>
> Ian

[-- Attachment #2: segment_patch.txt --]
[-- Type: text/plain, Size: 42294 bytes --]




	* 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.

	* 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.

Index: gold/gold.cc
===================================================================
RCS file: /cvs/src/src/gold/gold.cc,v
retrieving revision 1.100
diff -u -u -p -r1.100 gold.cc
--- gold/gold.cc	16 Jul 2012 19:00:18 -0000	1.100
+++ gold/gold.cc	23 Aug 2012 02:32:29 -0000
@@ -530,11 +530,13 @@ queue_middle_tasks(const General_options
 
   // Call Object::layout for the second time to determine the
   // output_sections for all referenced input sections.  When
-  // --gc-sections or --icf is turned on, Object::layout is
-  // called twice.  It is called the first time when the
-  // symbols are added.
+  // --gc-sections or --icf is turned on, or when certain input
+  // sections have to be mapped to unique segments, Object::layout
+  // is called twice.  It is called the first time when symbols
+  // are added.
   if (parameters->options().gc_sections()
-      || parameters->options().icf_enabled())
+      || parameters->options().icf_enabled()
+      || layout->is_unique_segment_for_sections_specified())
     {
       for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
 	   p != input_objects->relobj_end();
Index: gold/layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.235
diff -u -u -p -r1.235 layout.cc
--- gold/layout.cc	22 Aug 2012 18:26:32 -0000	1.235
+++ gold/layout.cc	23 Aug 2012 02:32:29 -0000
@@ -408,12 +408,14 @@ Layout::Layout(int number_of_input_files
     resized_signatures_(false),
     have_stabstr_section_(false),
     section_ordering_specified_(false),
+    unique_segment_for_sections_specified_(false),
     incremental_inputs_(NULL),
     record_output_section_data_from_script_(false),
     script_output_section_data_list_(),
     segment_states_(NULL),
     relaxation_debug_check_(NULL),
     section_order_map_(),
+    section_segment_map_(),
     input_section_position_(),
     input_section_glob_(),
     incremental_base_(NULL),
@@ -824,6 +826,27 @@ Layout::keep_input_section(const Relobj*
   return name != NULL && keep;
 }
 
+// Clear the input section flags that should not be copied to the
+// output section.
+
+elfcpp::Elf_Xword
+Layout::get_output_section_flags(elfcpp::Elf_Xword input_section_flags)
+{
+  // Some flags in the input section should not be automatically
+  // copied to the output section.
+  input_section_flags &= ~ (elfcpp::SHF_INFO_LINK
+			    | elfcpp::SHF_GROUP
+			    | elfcpp::SHF_MERGE
+			    | elfcpp::SHF_STRINGS);
+
+  // We only clear the SHF_LINK_ORDER flag in for
+  // a non-relocatable link.
+  if (!parameters->options().relocatable())
+    input_section_flags &= ~elfcpp::SHF_LINK_ORDER;
+
+  return input_section_flags;
+}
+
 // Pick the output section to use for section NAME, in input file
 // RELOBJ, with type TYPE and flags FLAGS.  RELOBJ may be NULL for a
 // linker created section.  IS_INPUT_SECTION is true if we are
@@ -842,17 +865,7 @@ Layout::choose_output_section(const Relo
   // sections to segments.
   gold_assert(!is_input_section || !this->sections_are_attached_);
 
-  // Some flags in the input section should not be automatically
-  // copied to the output section.
-  flags &= ~ (elfcpp::SHF_INFO_LINK
-	      | elfcpp::SHF_GROUP
-	      | elfcpp::SHF_MERGE
-	      | elfcpp::SHF_STRINGS);
-
-  // We only clear the SHF_LINK_ORDER flag in for
-  // a non-relocatable link.
-  if (!parameters->options().relocatable())
-    flags &= ~elfcpp::SHF_LINK_ORDER;
+  flags = this->get_output_section_flags (flags);
 
   if (this->script_options_->saw_sections_clause())
     {
@@ -1054,9 +1067,37 @@ Layout::layout(Sized_relobj_file<size, b
     }
   else
     {
-      os = this->choose_output_section(object, name, sh_type,
-				       shdr.get_sh_flags(), true,
-				       ORDER_INVALID, false);
+      // Plugins can choose to place one or more subsets of sections in
+      // unique segments and this is done by mapping these section subsets
+      // to unique output sections.  Check if this section needs to be
+      // remapped to a unique output section.
+      Section_segment_map::iterator it
+	  = this->section_segment_map_.find(Const_section_id(object, shndx));
+      if (it == this->section_segment_map_.end())
+	{
+          os = this->choose_output_section(object, name, sh_type,
+					   shdr.get_sh_flags(), true,
+					   ORDER_INVALID, false);
+	}
+      else
+	{
+	  // We know the name of the output section, directly call
+	  // get_output_section here by-passing choose_output_section.
+	  elfcpp::Elf_Xword flags
+	    = this->get_output_section_flags(shdr.get_sh_flags());
+
+	  const char* os_name = it->second->name;
+	  Stringpool::Key name_key;
+	  os_name = this->namepool_.add(os_name, true, &name_key);
+	  os = this->get_output_section(os_name, name_key, sh_type, flags,
+					ORDER_INVALID, false);
+	  if (!os->is_unique_segment())
+	    {
+	      os->set_is_unique_segment();
+	      os->set_extra_segment_flags(it->second->flags);
+	      os->set_segment_alignment(it->second->align);
+	    }
+	}
       if (os == NULL)
 	return NULL;
     }
@@ -1116,6 +1157,15 @@ Layout::layout(Sized_relobj_file<size, b
   return os;
 }
 
+// Maps section SECN to SEGMENT s.
+void
+Layout::insert_section_segment_map(Const_section_id secn,
+				   Unique_segment_info *s)
+{
+  gold_assert(this->unique_segment_for_sections_specified_); 
+  this->section_segment_map_[secn] = s;
+}
+
 // Handle a relocation section when doing a relocatable link.
 
 template<int size, bool big_endian>
@@ -1718,6 +1768,10 @@ Layout::attach_allocated_section_to_segm
 
   elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
 
+  // If this output section's segment has extra flags that need to be set,
+  // coming from a linker plugin, do that.
+  seg_flags |= os->extra_segment_flags();
+
   // Check for --section-start.
   uint64_t addr;
   bool is_address_set = parameters->options().section_start(os->name(), &addr);
@@ -1734,8 +1788,13 @@ Layout::attach_allocated_section_to_segm
        p != this->segment_list_.end();
        ++p)
     {
+      // No need to go through the loop if a unique segment is needed.
+      if (os->is_unique_segment())
+        break;
       if ((*p)->type() != elfcpp::PT_LOAD)
 	continue;
+      if ((*p)->is_unique_segment())
+	continue;
       if (!parameters->options().omagic()
 	  && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
 	continue;
@@ -1768,7 +1827,8 @@ Layout::attach_allocated_section_to_segm
       break;
     }
 
-  if (p == this->segment_list_.end())
+  if (p == this->segment_list_.end()
+      || os->is_unique_segment())
     {
       Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
 						       seg_flags);
@@ -1777,6 +1837,14 @@ Layout::attach_allocated_section_to_segm
       oseg->add_output_section_to_load(this, os, seg_flags);
       if (is_address_set)
 	oseg->set_addresses(addr, addr);
+      // Check if segment should be marked unique.  For segments marked
+      // unique by linker plugins, set the new alignment if specified.
+      if (os->is_unique_segment())
+	{
+	  oseg->set_is_unique_segment();
+	  if (os->segment_alignment() != 0)
+	    oseg->set_minimum_p_align(os->segment_alignment());
+	}
     }
 
   // If we see a loadable SHT_NOTE section, we create a PT_NOTE
@@ -3121,9 +3189,11 @@ Layout::segment_precedes(const Output_se
 
   // We shouldn't get here--we shouldn't create segments which we
   // can't distinguish.  Unless of course we are using a weird linker
-  // script or overlapping --section-start options.
+  // script or overlapping --section-start options.  We could also get
+  // here if plugins want unique segments for subsets of sections.
   gold_assert(this->script_options_->saw_phdrs_clause()
-	      || parameters->options().any_section_start());
+	      || parameters->options().any_section_start()
+	      || this->is_unique_segment_for_sections_specified());
   return false;
 }
 
Index: gold/layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.104
diff -u -u -p -r1.104 layout.h
--- gold/layout.h	14 Aug 2012 08:31:56 -0000	1.104
+++ gold/layout.h	23 Aug 2012 02:32:30 -0000
@@ -528,6 +528,30 @@ class Layout
   get_section_order_map()
   { return &this->section_order_map_; }
 
+  // Struct to store segment info when mapping some input sections to
+  // unique segments using linker plugins.  Mapping an input section to
+  // a unique segment is done by first placing such input sections in
+  // unique output sections and then mapping the output section to a
+  // unique segment.  NAME is the name of the output section.  FLAGS
+  // and ALIGN are the extra flags and alignment of the segment.
+  struct Unique_segment_info
+  {
+    // Identifier for the Segment.  ELF Segments dont have names.
+    const char* name;
+    // Additional Segment flags.
+    uint64_t flags;
+    // Segment alignment.
+    uint64_t align;
+  };
+
+  // Mapping from input section to segment.
+  typedef std::map<Const_section_id, Unique_segment_info*>
+  Section_segment_map;
+
+  // Maps section SECN to SEGMENT s.
+  void
+  insert_section_segment_map(Const_section_id secn, Unique_segment_info *s);
+  
   bool
   is_section_ordering_specified()
   { return this->section_ordering_specified_; }
@@ -536,6 +560,14 @@ class Layout
   set_section_ordering_specified()
   { this->section_ordering_specified_ = true; }
 
+  bool
+  is_unique_segment_for_sections_specified() const
+  { return this->unique_segment_for_sections_specified_; }
+
+  void
+  set_unique_segment_for_sections_specified()
+  { this->unique_segment_for_sections_specified_ = true; }
+
   // For incremental updates, allocate a block of memory from the
   // free list.  Find a block starting at or after MINOFF.
   off_t
@@ -1070,6 +1102,11 @@ class Layout
 		     elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
 		     Output_section_order order, bool is_relro);
 
+  // Clear the input section flags that should not be copied to the
+  // output section.
+  elfcpp::Elf_Xword
+  get_output_section_flags (elfcpp::Elf_Xword input_section_flags);
+
   // Choose the output section for NAME in RELOBJ.
   Output_section*
   choose_output_section(const Relobj* relobj, const char* name,
@@ -1336,6 +1373,9 @@ class Layout
   // True if the input sections in the output sections should be sorted
   // as specified in a section ordering file.
   bool section_ordering_specified_;
+  // True if some input sections need to be mapped to a unique segment,
+  // after being mapped to a unique Output_section.
+  bool unique_segment_for_sections_specified_;
   // In incremental build, holds information check the inputs and build the
   // .gnu_incremental_inputs section.
   Incremental_inputs* incremental_inputs_;
@@ -1350,6 +1390,11 @@ class Layout
   // Plugins specify section_ordering using this map.  This is set in
   // update_section_order in plugin.cc
   std::map<Section_id, unsigned int> section_order_map_;
+  // This maps an input section to a unique segment. This is done by first
+  // placing such input sections in unique output sections and then mapping
+  // the output section to a unique segment.  Unique_segment_info stores
+  // any additional flags and alignment of the new segment.
+  Section_segment_map section_segment_map_;
   // Hash a pattern to its position in the section ordering file.
   Unordered_map<std::string, unsigned int> input_section_position_;
   // Vector of glob only patterns in the section_ordering file.
Index: gold/object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.157
diff -u -u -p -r1.157 object.cc
--- gold/object.cc	14 Aug 2012 08:31:56 -0000	1.157
+++ gold/object.cc	23 Aug 2012 02:32:30 -0000
@@ -1221,15 +1221,19 @@ Sized_relobj_file<size, big_endian>::lay
 // 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_
 					       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()));
 
-  bool is_gc_or_icf = (parameters->options().gc_sections()
-		       || parameters->options().icf_enabled());
+  /* 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());
+
+  /* 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_
       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_
   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_
   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_
   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_
   // 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_
 
       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_
 	    }
 	}
 
-      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_
 	  && 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_
 	  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_
 	      }
 	}
 
-      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_
       // 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_
       // 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_
 	}
     }
 
-  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_
   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_
     }
 
   // 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_
 
   // 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_
 			       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;
Index: gold/output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.168
diff -u -u -p -r1.168 output.cc
--- gold/output.cc	11 Aug 2012 04:41:28 -0000	1.168
+++ gold/output.cc	23 Aug 2012 02:32:30 -0000
@@ -2257,7 +2257,10 @@ Output_section::Output_section(const cha
     always_keeps_input_sections_(false),
     has_fixed_layout_(false),
     is_patch_space_allowed_(false),
+    is_unique_segment_(false),
     tls_offset_(0),
+    extra_segment_flags_(0),
+    segment_alignment_(0),
     checkpoint_(NULL),
     lookup_maps_(new Output_section_lookup_maps),
     free_list_(),
@@ -3991,7 +3994,8 @@ Output_segment::Output_segment(elfcpp::E
     flags_(flags),
     is_max_align_known_(false),
     are_addresses_set_(false),
-    is_large_data_segment_(false)
+    is_large_data_segment_(false),
+    is_unique_segment_(false)
 {
   // The ELF ABI specifies that a PT_TLS segment always has PF_R as
   // the flags.
Index: gold/output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.136
diff -u -u -p -r1.136 output.h
--- gold/output.h	11 Aug 2012 04:41:28 -0000	1.136
+++ gold/output.h	23 Aug 2012 02:32:31 -0000
@@ -3265,6 +3265,29 @@ class Output_section : public Output_dat
   requires_postprocessing() const
   { return this->requires_postprocessing_; }
 
+  bool
+  is_unique_segment() const
+  { return this->is_unique_segment_; }
+
+  void
+  set_is_unique_segment()
+  { this->is_unique_segment_ = true; }
+
+  uint64_t extra_segment_flags() const
+  { return this->extra_segment_flags_; }
+
+  void
+  set_extra_segment_flags(uint64_t flags)
+  { this->extra_segment_flags_ = flags; }
+
+  uint64_t segment_alignment() const
+  { return this->segment_alignment_; }
+
+  void
+  set_segment_alignment(uint64_t align)
+  { this->segment_alignment_ = align; }
+  
+
   // If a section requires postprocessing, return the buffer to use.
   unsigned char*
   postprocessing_buffer() const
@@ -4216,9 +4239,17 @@ class Output_section : public Output_dat
   bool has_fixed_layout_ : 1;
   // True if we can add patch space to this section.
   bool is_patch_space_allowed_ : 1;
+  // True if this output section goes into a unique segment.
+  bool is_unique_segment_ : 1;
   // For SHT_TLS sections, the offset of this section relative to the base
   // of the TLS segment.
   uint64_t tls_offset_;
+  // Additional segment flags, specified via linker plugin, when mapping some
+  // input sections to unique segments.
+  uint64_t extra_segment_flags_; 
+  // Segment alignment specified via linker plugin, when mapping some
+  // input sections to unique segments.
+  uint64_t segment_alignment_;
   // Saved checkpoint.
   Checkpoint_output_section* checkpoint_;
   // Fast lookup maps for merged and relaxed input sections.
@@ -4294,6 +4325,16 @@ class Output_segment
   set_is_large_data_segment()
   { this->is_large_data_segment_ = true; }
 
+  bool
+  is_unique_segment() const
+  { return this->is_unique_segment_; }
+
+  // Mark segment as unique, happens when linker plugins request that
+  // certain input sections be mapped to unique segments.
+  void
+  set_is_unique_segment()
+  { this->is_unique_segment_ = true; }
+
   // Return the maximum alignment of the Output_data.
   uint64_t
   maximum_alignment();
@@ -4504,6 +4545,8 @@ class Output_segment
   bool are_addresses_set_ : 1;
   // Whether this segment holds large data sections.
   bool is_large_data_segment_ : 1;
+  // Whether this was marked as a unique segment via a linker plugin.
+  bool is_unique_segment_ : 1;
 };
 
 // This class represents the output file.
Index: gold/plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.54
diff -u -u -p -r1.54 plugin.cc
--- gold/plugin.cc	12 Jun 2012 22:52:41 -0000	1.54
+++ gold/plugin.cc	23 Aug 2012 02:32:31 -0000
@@ -115,6 +115,15 @@ update_section_order(const struct ld_plu
 static enum ld_plugin_status
 allow_section_ordering();
 
+static enum ld_plugin_status
+allow_unique_segment_for_sections();
+
+static enum ld_plugin_status
+unique_segment_for_sections(const char* segment_name,
+			    uint64_t flags,
+			    uint64_t align,
+			    const struct ld_plugin_section *section_list,
+			    unsigned int num_sections);
 };
 
 #endif // ENABLE_PLUGINS
@@ -159,7 +168,7 @@ Plugin::load()
   sscanf(ver, "%d.%d", &major, &minor);
 
   // Allocate and populate a transfer vector.
-  const int tv_fixed_size = 24;
+  const int tv_fixed_size = 26;
 
   int tv_size = this->args_.size() + tv_fixed_size;
   ld_plugin_tv* tv = new ld_plugin_tv[tv_size];
@@ -273,6 +282,15 @@ Plugin::load()
   tv[i].tv_u.tv_allow_section_ordering = allow_section_ordering;
 
   ++i;
+  tv[i].tv_tag = LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS;
+  tv[i].tv_u.tv_allow_unique_segment_for_sections
+    = allow_unique_segment_for_sections;
+
+  ++i;
+  tv[i].tv_tag = LDPT_UNIQUE_SEGMENT_FOR_SECTIONS;
+  tv[i].tv_u.tv_unique_segment_for_sections = unique_segment_for_sections;
+
+  ++i;
   tv[i].tv_tag = LDPT_NULL;
   tv[i].tv_u.tv_val = 0;
 
@@ -1685,6 +1703,64 @@ allow_section_ordering()
   return LDPS_OK;
 }
 
+// Let the linker know that a subset of sections could be mapped
+// to a unique segment.
+
+static enum ld_plugin_status
+allow_unique_segment_for_sections()
+{
+  gold_assert(parameters->options().has_plugins());
+  Layout* layout = parameters->options().plugins()->layout();
+  layout->set_unique_segment_for_sections_specified();
+  return LDPS_OK;
+}
+
+// This function should map the list of sections specified in the
+// SECTION_LIST to a unique segment.  ELF segments do not have names
+// and the NAME is used to identify Output Section which should contain
+// the list of sections.  This Output Section will then be mapped to
+// a unique segment.  FLAGS is used to specify if any additional segment
+// flags need to be set.  For instance, a specific segment flag can be
+// set to identify this segment.  Unsetting segment flags is not possible.
+// ALIGN specifies the alignment of the segment.
+
+static enum ld_plugin_status
+unique_segment_for_sections(const char* segment_name,
+			    uint64_t flags,
+			    uint64_t align,
+			    const struct ld_plugin_section* section_list,
+			    unsigned int num_sections)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (num_sections == 0)
+    return LDPS_OK;
+
+  if (section_list == NULL)
+    return LDPS_ERR;
+
+  Layout* layout = parameters->options().plugins()->layout();
+  gold_assert (layout != NULL);
+
+  Layout::Unique_segment_info* s = new Layout::Unique_segment_info;
+  s->name = segment_name;
+  s->flags = flags;
+  s->align = align;
+
+  for (unsigned int i = 0; i < num_sections; ++i)
+    {
+      Object* obj = parameters->options().plugins()->get_elf_object(
+          section_list[i].handle);
+      if (obj == NULL)
+	return LDPS_BAD_HANDLE;
+      unsigned int shndx = section_list[i].shndx;
+      Const_section_id secn_id(obj, shndx);
+      layout->insert_section_segment_map(secn_id, s);
+    }
+
+  return LDPS_OK;
+}
+
 #endif // ENABLE_PLUGINS
 
 // Allocate a Pluginobj object of the appropriate size and endianness.
Index: gold/testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.195
diff -u -u -p -r1.195 Makefile.am
--- gold/testsuite/Makefile.am	14 Aug 2012 08:31:57 -0000	1.195
+++ gold/testsuite/Makefile.am	23 Aug 2012 02:32:31 -0000
@@ -1529,13 +1529,15 @@ unused.c:
 	@cp /dev/null $@
 
 check_SCRIPTS += plugin_final_layout.sh
-check_DATA += plugin_final_layout.stdout
+check_DATA += plugin_final_layout.stdout plugin_final_layout_readelf.stdout
 plugin_final_layout.o: plugin_final_layout.cc
 	$(CXXCOMPILE) -O0 -c -ffunction-sections  -fdata-sections -g -o $@ $<
 plugin_final_layout: plugin_final_layout.o plugin_section_order.so gcctestdir/ld
 	$(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_order.so" plugin_final_layout.o
 plugin_final_layout.stdout: plugin_final_layout
 	$(TEST_NM) -n plugin_final_layout > plugin_final_layout.stdout
+plugin_final_layout_readelf.stdout: plugin_final_layout
+	$(TEST_READELF) -Wl plugin_final_layout > plugin_final_layout_readelf.stdout
 
 plugin_section_order.so: plugin_section_order.o
 	$(LINK) -Bgcctestdir/ -shared plugin_section_order.o
Index: gold/testsuite/Makefile.in
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.in,v
retrieving revision 1.205
diff -u -u -p -r1.205 Makefile.in
--- gold/testsuite/Makefile.in	14 Aug 2012 08:31:57 -0000	1.205
+++ gold/testsuite/Makefile.in	23 Aug 2012 02:32:32 -0000
@@ -329,7 +329,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__E
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	plugin_test_7.err \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	plugin_test_7.syms \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	plugin_test_9.err \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	plugin_final_layout.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	plugin_final_layout.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	plugin_final_layout.readelf.stdout
 # Make a copy of two_file_test_1.o, which does not define the symbol _Z4t16av.
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_36 =  \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	plugin_test_1.err \
@@ -4875,6 +4876,8 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	$(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_order.so" plugin_final_layout.o
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.stdout: plugin_final_layout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	$(TEST_NM) -n plugin_final_layout > plugin_final_layout.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.readelf.stdout: plugin_final_layout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	$(TEST_READELF) -Wl plugin_final_layout > plugin_final_layout_readelf.stdout
 
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_order.so: plugin_section_order.o
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@	$(LINK) -Bgcctestdir/ -shared plugin_section_order.o
Index: gold/testsuite/plugin_final_layout.sh
===================================================================
RCS file: /cvs/src/src/gold/testsuite/plugin_final_layout.sh,v
retrieving revision 1.1
diff -u -u -p -r1.1 plugin_final_layout.sh
--- gold/testsuite/plugin_final_layout.sh	29 Sep 2011 23:45:57 -0000	1.1
+++ gold/testsuite/plugin_final_layout.sh	23 Aug 2012 02:32:32 -0000
@@ -56,5 +56,35 @@ END {
     }" $1
 }
 
+# With readelf -l, an ELF Section to Segment mapping is printed as :
+##############################################
+#  Section to Segment mapping:
+#  Segment Sections...
+#  ...
+#     0x     .text.plugin_created_unique
+#  ...
+##############################################
+# Check of .text.plugin_created_unique is the only section in the segment.
+check_unique_segment()
+{
+    awk "
+BEGIN { saw_section = 0; saw_unique = 0; }
+/$2/ { saw_section = 1; }
+/[ ]*0[0-9][ ]*$2[ ]*\$/ { saw_unique = 1; }
+END {
+      if (!saw_section)
+	{
+	  printf \"Section $2 not seen in output\\n\";
+	  exit 1;
+	}
+      else if (!saw_unique)
+	{
+	  printf \"Unique segment not seen for: $2\\n\";
+	  exit 1;
+	}
+    }" $1
+}
+
 check plugin_final_layout.stdout "_Z3foov" "_Z3barv"
 check plugin_final_layout.stdout "_Z3barv" "_Z3bazv"
+check_unique_segment plugin_final_layout_readelf.stdout ".text.plugin_created_unique"
Index: gold/testsuite/plugin_section_order.c
===================================================================
RCS file: /cvs/src/src/gold/testsuite/plugin_section_order.c,v
retrieving revision 1.1
diff -u -u -p -r1.1 plugin_section_order.c
--- gold/testsuite/plugin_section_order.c	29 Sep 2011 23:45:57 -0000	1.1
+++ gold/testsuite/plugin_section_order.c	23 Aug 2012 02:32:32 -0000
@@ -36,6 +36,9 @@ static ld_plugin_get_input_section_name 
 static ld_plugin_get_input_section_contents get_input_section_contents = NULL;
 static ld_plugin_update_section_order update_section_order = NULL;
 static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
+static ld_plugin_allow_unique_segment_for_sections 
+    allow_unique_segment_for_sections = NULL;
+static ld_plugin_unique_segment_for_sections unique_segment_for_sections = NULL;
 
 enum ld_plugin_status onload(struct ld_plugin_tv *tv);
 enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
@@ -52,11 +55,13 @@ onload(struct ld_plugin_tv *tv)
       switch (entry->tv_tag)
         {
         case LDPT_REGISTER_CLAIM_FILE_HOOK:
-          assert((*entry->tv_u.tv_register_claim_file) (claim_file_hook) == LDPS_OK);
+          assert((*entry->tv_u.tv_register_claim_file) (claim_file_hook)
+		 == LDPS_OK);
           break;
 	case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
-          assert((*entry->tv_u.tv_register_all_symbols_read) (all_symbols_read_hook)
-		  == LDPS_OK);
+          assert((*entry->tv_u.tv_register_all_symbols_read)
+		     (all_symbols_read_hook)
+		 == LDPS_OK);
           break;
         case LDPT_GET_INPUT_SECTION_COUNT:
           get_input_section_count = *entry->tv_u.tv_get_input_section_count;
@@ -68,7 +73,8 @@ onload(struct ld_plugin_tv *tv)
           get_input_section_name = *entry->tv_u.tv_get_input_section_name;
           break;
         case LDPT_GET_INPUT_SECTION_CONTENTS:
-          get_input_section_contents = *entry->tv_u.tv_get_input_section_contents;
+          get_input_section_contents
+	      = *entry->tv_u.tv_get_input_section_contents;
           break;
 	case LDPT_UPDATE_SECTION_ORDER:
 	  update_section_order = *entry->tv_u.tv_update_section_order;
@@ -76,6 +82,13 @@ onload(struct ld_plugin_tv *tv)
 	case LDPT_ALLOW_SECTION_ORDERING:
 	  allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
 	  break;
+	case LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS:
+	  allow_unique_segment_for_sections
+	      = *entry->tv_u.tv_allow_unique_segment_for_sections;
+	case LDPT_UNIQUE_SEGMENT_FOR_SECTIONS:
+	  unique_segment_for_sections
+	      = *entry->tv_u.tv_unique_segment_for_sections;
+	  break;
         default:
           break;
         }
@@ -86,7 +99,9 @@ onload(struct ld_plugin_tv *tv)
       || get_input_section_name == NULL
       || get_input_section_contents == NULL
       || update_section_order == NULL
-      || allow_section_ordering == NULL)
+      || allow_section_ordering == NULL
+      || allow_unique_segment_for_sections == NULL
+      || unique_segment_for_sections == NULL)
     {
       fprintf(stderr, "Some interfaces are missing\n");
       return LDPS_ERR;
@@ -117,6 +132,9 @@ claim_file_hook(const struct ld_plugin_i
     {
       /* Inform the linker to prepare for section reordering.  */
       (*allow_section_ordering)();
+      /* Inform the linker to prepare to map some sections to unique
+	 segments.  */
+      (*allow_unique_segment_for_sections)(); 
       is_ordering_specified = 1;
     }
 
@@ -160,8 +178,11 @@ enum ld_plugin_status
 all_symbols_read_hook(void)
 {
   if (num_entries == 3)
-    update_section_order(section_list, num_entries);
+    { 
+      update_section_order(section_list, num_entries);
+      unique_segment_for_sections (".text.plugin_created_unique", 0, 0x1000,
+				   section_list, num_entries);
+    }
 
   return LDPS_OK;
 }
Index: include/plugin-api.h
===================================================================
RCS file: /cvs/src/src/include/plugin-api.h,v
retrieving revision 1.19
diff -u -u -p -r1.19 plugin-api.h
--- include/plugin-api.h	12 Jun 2012 22:50:44 -0000	1.19
+++ include/plugin-api.h	23 Aug 2012 02:32:32 -0000
@@ -318,6 +318,32 @@ typedef
 enum ld_plugin_status
 (*ld_plugin_allow_section_ordering) (void);
 
+/* The linker's interface for specifying that a subset of sections is
+   to be mapped to a unique segment.  If the plugin wants to call
+   unique_segment_for_sections, it must call this function from a
+   claim_file_handler or when it is first loaded.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_allow_unique_segment_for_sections) (void);
+
+/* The linker's interface for specifying that a specific set of sections
+   must be mapped to a unique segment.  ELF segments do not have names
+   and the NAME is used as an identifier only.   FLAGS is used to specify
+   if any additional segment flags need to be set.  For instance, a
+   specific segment flag can be set to identify this segment.  Unsetting
+   segment flags that would be set by default is not possible.  The
+   parameter SEGMENT_ALIGNMENT when non-zero will override the default.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_unique_segment_for_sections) (
+    const char* segment_name,
+    uint64_t segment_flags,
+    uint64_t segment_alignment,
+    const struct ld_plugin_section * section_list,
+    unsigned int num_sections);
+
 enum ld_plugin_level
 {
   LDPL_INFO,
@@ -355,7 +381,9 @@ enum ld_plugin_tag
   LDPT_GET_INPUT_SECTION_CONTENTS,
   LDPT_UPDATE_SECTION_ORDER,
   LDPT_ALLOW_SECTION_ORDERING,
-  LDPT_GET_SYMBOLS_V2
+  LDPT_GET_SYMBOLS_V2,
+  LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS,
+  LDPT_UNIQUE_SEGMENT_FOR_SECTIONS
 };
 
 /* The plugin transfer vector.  */
@@ -385,6 +413,8 @@ struct ld_plugin_tv
     ld_plugin_get_input_section_contents tv_get_input_section_contents;
     ld_plugin_update_section_order tv_update_section_order;
     ld_plugin_allow_section_ordering tv_allow_section_ordering;
+    ld_plugin_allow_unique_segment_for_sections tv_allow_unique_segment_for_sections; 
+    ld_plugin_unique_segment_for_sections tv_unique_segment_for_sections;
   } tv_u;
 };
 

  reply	other threads:[~2012-08-23  3:12 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-21  0:28 Sriraman Tallam
2012-07-31 17:21 ` Sriraman Tallam
2012-08-03  6:44   ` Cary Coutant
2012-08-10  0:56     ` Sriraman Tallam
2012-08-22 21:41       ` Ian Lance Taylor
2012-08-23  4:14         ` Sriraman Tallam [this message]
2012-08-24 17:41           ` Ian Lance Taylor
2012-08-24 17:44           ` Cary Coutant
2012-08-24 19:01             ` Sriraman Tallam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAAs8HmwCE61Mex95HWC0+ji1=QrziV7dwpAO0BZZpx0QOY8QhA@mail.gmail.com' \
    --to=tmsriram@google.com \
    --cc=binutils@sourceware.org \
    --cc=ccoutant@google.com \
    --cc=iant@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).