Plugin interfaces to do Pettis Hansen style code layout in the gold linker.

Sriraman Tallam tmsriram@google.com
Wed Jul 13 14:45:00 GMT 2011


Hi Ian,

   I made all the changes you mentioned. I removed the
inspect_unclaimed_object hooks and allowed the functionality to happen
in claim_file hook, so one handle. Please look at readsyms.cc in
particular as that has the biggest change to allow this to happen.

Thanks,
-Sri.


  	* archive.cc (Archive::get_elf_object_for_member): Add extra parameter
	to claim_file call.
	* layout.cc (Layout::Layout): Initialize section_ordering_specified_,
	input_section_position_, and input_section_glob_.
	(read_layout_from_file): Call function section_ordering_specified.
	* layout.h (is_section_ordering_specified): New function.
	(section_ordering_specified): New function.
	(section_ordering_specified_): New boolean member.
	* main.cc(main): Call load_plugins after layout object is defined.
	* output.cc (Output_section::add_input_section): Use
	function section_ordering_specified to check if section ordering is
	needed.
	* output.cc (Output_section::add_relaxed_input_section): Use
	function section_ordering_specified to check if section ordering is
	needed.
	(Output_section::update_section_layout): New function.
	(Output_section::sort_attached_input_sections): Check if input section
	must be reordered.
	* output.h (Output_section::update_section_layout): New function.
	* plugin.cc (get_section_count): New function.
	(get_section_type): New function.
	(get_section_name): New function.
	(get_section_contents): New function.
	(update_section_order): New function.
	(allow_section_ordering): New function.	
	(Plugin::load): Add the new interfaces to the transfer vector.
	(Plugin_manager::load_plugins): New parameter.
	(Plugin_manager::all_symbols_read): New parameter.
	(Plugin_manager::claim_file): New parameter. Save the elf object for
	unclaimed objects.
	(Plugin_manager::get_elf_object): New function.
	* plugin.h (input_objects): New function
	(Plugin__manager::load_plugins): New parameter.
	(Plugin_manager::claim_file): New parameter.
	(Plugin_manager::get_elf_object): New function.
	(Plugin_manager::in_claim_file_handler): New function.
	(Plugin_manager::in_claim_file_handler_): New member.
	(layout): New function.
	* readsyms.cc (Read_symbols::do_read_symbols): Call the claim_file
	handler with an extra parameter. Make the elf object before calling
	claim_file handler.
	* testsuite/plugin_test.c (get_section_count): New function pointer.
	(get_section_type): New function pointer.
	(get_section_name): New function pointer.
	(get_section_contents): New function pointer.
	(update_section_order): New function pointer.
	(allow_section_ordering): New function pointer.
	(onload): Check if the new interfaces exist.

	* plugin-api.h
	(ld_plugin_section): New struct.
	(ld_plugin_get_section_count): New typedef.
	(ld_plugin_get_section_type): New typedef.
	(ld_plugin_get_section_name): New typedef.
	(ld_plugin_get_section_contents): New typedef.
	(ld_plugin_update_section_order): New typedef.
	(ld_plugin_allow_section_ordering): New typedef.
	(LDPT_GET_SECTION_COUNT): New enum value.
	(LDPT_GET_SECTION_TYPE): New enum value.
	(LDPT_GET_SECTION_NAME): New enum value.
	(LDPT_GET_SECTION_CONTENTS): New enum value.
	(LDPT_UPDATE_SECTION_ORDER): New enum value.
	(LDPT_ALLOW_SECTION_ORDERING): New enum value.
	(tv_get_section_count): New struct members.
	(tv_get_section_type): New struct members.
	(tv_get_section_name): New struct members.
	(tv_get_section_contents): New struct members.
	(tv_update_section_order): New struct members.
	(tv_allow_section_ordering): New struct members.

On Tue, Jul 5, 2011 at 2:29 PM, Ian Lance Taylor <iant@google.com> wrote:
> Sriraman Tallam <tmsriram@google.com> writes:
>
>> * layout.cc (Layout::Layout): Initialize section_ordering_specified_,
>> input_section_position_, and input_section_glob_.
>> (read_layout_from_file): Call function section_ordering_specified.
>> * layout.h (is_section_ordering_specified): New function.
>> (section_ordering_specified): New function.
>> (section_ordering_specified_): New boolean member.
>> * main.cc(main): Call load_plugins after layout object is defined.
>> * output.cc (Output_section::add_input_section): Use
>> function section_ordering_specified to check if section ordering is
>> needed.
>> * output.cc (Output_section::add_relaxed_input_section): Use
>> function section_ordering_specified to check if section ordering is
>> needed.
>> (Output_section::update_section_layout): New function.
>> (Output_section::sort_attached_input_sections): Check if input section
>> must be reordered.
>> * output.h (Output_section::update_section_layout): New function.
>> * plugin.cc (register_inspect_unclaimed_object): New function.
>> (get_section_count): New function.
>> (get_section_type): New function.
>> (get_section_name): New function.
>> (get_section_contents): New function.
>> (update_section_order): New function.
>> (allow_section_ordering): New function.
>> (Plugin::inspect_unclaimed_object): New function.
>> (Plugin_manager::inspect_unclaimed_object): New function.
>> (Plugin_manager::get_unclaimed_object): New function.
>> (Plugin::load): Add the new interfaces to the transfer vector.
>> (Plugin_manager::load_plugins): New parameter.
>> (Plugin_manager::all_symbols_read): New parameter.
>> * plugin.h (input_objects): New function
>> (Plugin::inspect_unclaimed_object): New function.
>> (Plugin::set_inspect_unclaimed_object_handler): New function.
>> (Plugin__manager::load_plugins): New parameter.
>> (Plugin_manager::inspect_unclaimed_object): New function.
>> (Plugin_manager::get_unclaimed_object): New function.
>> (Plugin_manager::in_inspect_unclaimed_object_handler): New function.
>> (Plugin_manager::set_inspect_unclaimed_object_handler): New function.
>> (Plugin_manager::unclaimed_object): New function.
>> (Plugin_manager::Unclaimed_object_list): New typedef.
>> (Plugin_manager::unclaimed_objects_): New member.
>> (Plugin_manager::in_inspect_unclaimed_object_handler_): New member.
>> (layout): New function.
>> * readsyms.cc (Read_symbols::do_read_symbols): Call the plugin handler.
>> * testsuite/plugin_test.c (register_inspect_unclaimed_object_hook):
>> New function pointer.
>> (get_section_count): New function pointer.
>> (get_section_type): New function pointer.
>> (get_section_name): New function pointer.
>> (get_section_contents): New function pointer.
>> (update_section_order): New function pointer.
>> (allow_section_ordering): New function pointer.
>> (inspect_unclaimed_object_hook): New function.
>> (onload): Check if the new interfaces exist.
>> * plugin-api.h
>> (unclaimed_obkect_handle): New typedef.
>> (ld_plugin_section): New struct.
>> (ld_plugin_inspect_unclaimed_object_handler): New typedef.
>> (ld_plugin_register_inspect_unclaimed_object): New typedef.
>> (ld_plugin_get_section_count): New typedef.
>> (ld_plugin_get_section_type): New typedef.
>> (ld_plugin_get_section_name): New typedef.
>> (ld_plugin_get_section_contents): New typedef.
>> (ld_plugin_update_section_order): New typedef.
>> (ld_plugin_allow_section_ordering): New typedef.
>> (LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK): New enum value.
>> (LDPT_GET_SECTION_COUNT): New enum value.
>> (LDPT_GET_SECTION_TYPE): New enum value.
>> (LDPT_GET_SECTION_NAME): New enum value.
>> (LDPT_GET_SECTION_CONTENTS): New enum value.
>> (LDPT_UPDATE_SECTION_ORDER): New enum value.
>> (LDPT_ALLOW_SECTION_ORDERING): New enum value.
>> (tv_get_section_count): New struct members.
>> (tv_get_section_type): New struct members.
>> (tv_get_section_name): New struct members.
>> (tv_get_section_contents): New struct members.
>> (tv_update_section_order): New struct members.
>> (tv_allow_section_ordering): New struct members.
>
>
>> +static enum ld_plugin_status
>> +get_input_section_contents(const struct ld_plugin_section section,
>> +                           const unsigned char** section_contents,
>> +                        unsigned int* len);
>
> Let's change the len parameter from "unsigned int*" to "size_t*".
>
>
>> +// This updates the section order index of input sections according to the
>> +// the order specified in the mapping from Section id to order index.
>> +
>> +void
>> +Output_section::update_section_layout(
>> +  const Section_layout_order& order_map)
>> +{
>> +  for (Input_section_list::iterator p = this->input_sections_.begin();
>> +       p != this->input_sections_.end();
>> +       ++p)
>> +    {
>> +      if ((*p).is_input_section()
>> +       || (*p).is_relaxed_input_section())
>> +        {
>> +       Object* obj = ((*p).is_input_section()
>> +                      ? (*p).relobj()
>> +                      : (*p).relaxed_input_section()->relobj());
>> +       unsigned int shndx = (*p).shndx();
>> +       Section_layout_order::const_iterator it
>> +         = order_map.find(Section_id(obj, shndx));
>> +       if (it == order_map.end())
>> +         continue;
>> +       unsigned int section_order_index = it->second;
>> +       if (section_order_index != 0)
>> +            {
>> +              (*p).set_section_order_index(section_order_index);
>> +              this->set_input_section_order_specified();
>> +         }
>> +        }
>> +    }
>> +}
>
> Please write "p->" instead of "(*p).".
>
>
>> +// Specify the ordering of sections in the final layout. The sections are
>> +// specified as (handle,shndx) pairs in the two arrays in the order in
>> +// which they should appear in the final layout.
>> +
>> +static enum ld_plugin_status
>> +update_section_order(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;
>> +
>> +  std::map<Section_id, unsigned int> order_map;
>> +
>> +  for (unsigned int i = 0; i < num_sections; ++i)
>> +    {
>> +      Object* obj = parameters->options().plugins()->get_unclaimed_object(
>> +        section_list[i].handle);
>> +      unsigned int shndx = section_list[i].shndx;
>> +      Section_id secn_id(obj, shndx);
>> +      order_map[secn_id] = i + 1;
>> +    }
>> +
>> +  Layout* layout = parameters->options().plugins()->layout();
>> +  gold_assert (layout != NULL);
>> +
>> +  for (Layout::Section_list::const_iterator p = layout->section_list().begin();
>> +       p != layout->section_list().end();
>> +       ++p)
>> +    (*p)->update_section_layout(order_map);
>> +
>> +  return LDPS_OK;
>> +}
>
> You need to check the return value of get_unclaimed_object, and return
> LDPS_ERR if it returns NULL.
>
>
>> +      // Allow the plugins to inspect the unclaimed object now.
>> +      if (parameters->options().has_plugins())
>> +        parameters->options().plugins()->inspect_unclaimed_object(obj);
>
> Can you remind me of why we need both inspect_unclaimed_object and
> claim_file?  To me it seems that it might be logical to let claim_file
> call get_section_count and so forth, and even update_section_order, and
> then simply set *claimed to 0 if it doesn't want to claim the file.
>
>
>> +/* The linker's interface for retrieving the name of specific section in
>> +   an object. This interface should only be invoked in the
>> +   inspect_unclaimed_object handler.  This function sets *SECTION_NAME_PTR
>> +   to a null-terminated buffer allocated by malloc.  The plugin must free
>> +   *SECTION_NAME_PTR.  */
>
> s/of specific section/of a specific section/
>
>
>> +/* The linker's interface for retrieving the contents of a specific section
>> +   in an object.  This interface should only be invoked in the
>> +   inspect_unclaimed_object handler.  This function sets *SECTION_CONTENTS to
>> +   point to a buffer that is valid  until inspect_unclaimed_object handler
>> +   returns.  It sets *LEN to the size of the buffer.  */
>
> There seems to be an extra space after "valid".
>
>
> The only important point in the above is whether we can eliminate
> inspect_unclaimed_object.
>
> Ian
>
-------------- next part --------------
Index: include/plugin-api.h
===================================================================
RCS file: /cvs/src/src/include/plugin-api.h,v
retrieving revision 1.14
diff -u -u -p -r1.14 plugin-api.h
--- include/plugin-api.h	23 Mar 2011 14:09:48 -0000	1.14
+++ include/plugin-api.h	13 Jul 2011 01:32:36 -0000
@@ -93,6 +93,14 @@ struct ld_plugin_symbol
   int resolution;
 };
 
+/* An object's section.  */
+
+struct ld_plugin_section
+{
+  const void* handle;
+  unsigned int shndx;
+};
+
 /* Whether the symbol is a definition, reference, or common, weak or not.  */
 
 enum ld_plugin_symbol_kind
@@ -244,6 +252,66 @@ typedef
 enum ld_plugin_status
 (*ld_plugin_message) (int level, const char *format, ...);
 
+/* The linker's interface for retrieving the number of sections in an object.
+   The handle is obtained in the claim_file handler.  This interface should
+   only be invoked in the claim_file handler.   This function sets *COUNT to
+   the number of sections in the object.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_input_section_count) (const void* handle, unsigned int *count);
+
+/* The linker's interface for retrieving the section type of a specific
+   section in an object.  This interface should only be invoked in the
+   claim_file handler.  This function sets *TYPE to an ELF SHT_xxx value.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_input_section_type) (const struct ld_plugin_section section,
+                                     unsigned int *type);
+
+/* The linker's interface for retrieving the name of a specific section in
+   an object. This interface should only be invoked in the claim_file handler.
+   This function sets *SECTION_NAME_PTR to a null-terminated buffer allocated
+   by malloc.  The plugin must free *SECTION_NAME_PTR.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_input_section_name) (const struct ld_plugin_section section,
+                                     char **section_name_ptr);
+
+/* The linker's interface for retrieving the contents of a specific section
+   in an object.  This interface should only be invoked in the claim_file
+   handler.  This function sets *SECTION_CONTENTS to point to a buffer that is
+   valid until inspect_unclaimed_object handler returns.  It sets *LEN to the
+   size of the buffer.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_input_section_contents) (const struct ld_plugin_section section,
+                                         const unsigned char **section_contents,
+                                         size_t* len);
+
+/* The linker's interface for specifying the desired order of sections.
+   The sections should be specifed using the array SECTION_LIST in the
+   order in which they should appear in the final layout.  NUM_SECTIONS
+   specifies the number of entries in each array.  This should be invoked
+   in the all_symbols_read handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_update_section_order) (const struct ld_plugin_section *section_list,
+				   unsigned int num_sections);
+
+/* The linker's interface for specifying that reordering of sections is
+   desired so that the linker can prepare for it.  This should be invoked
+   before update_section_order, preferably in the inspect_unclaimed_object
+   handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_allow_section_ordering) (void);
+
 enum ld_plugin_level
 {
   LDPL_INFO,
@@ -274,7 +342,13 @@ enum ld_plugin_tag
   LDPT_OUTPUT_NAME,
   LDPT_SET_EXTRA_LIBRARY_PATH,
   LDPT_GNU_LD_VERSION,
-  LDPT_GET_VIEW
+  LDPT_GET_VIEW,
+  LDPT_GET_INPUT_SECTION_COUNT,
+  LDPT_GET_INPUT_SECTION_TYPE,
+  LDPT_GET_INPUT_SECTION_NAME,
+  LDPT_GET_INPUT_SECTION_CONTENTS,
+  LDPT_UPDATE_SECTION_ORDER,
+  LDPT_ALLOW_SECTION_ORDERING
 };
 
 /* The plugin transfer vector.  */
@@ -298,6 +372,12 @@ struct ld_plugin_tv
     ld_plugin_release_input_file tv_release_input_file;
     ld_plugin_add_input_library tv_add_input_library;
     ld_plugin_set_extra_library_path tv_set_extra_library_path;
+    ld_plugin_get_input_section_count tv_get_input_section_count;
+    ld_plugin_get_input_section_type tv_get_input_section_type;
+    ld_plugin_get_input_section_name tv_get_input_section_name;
+    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;
   } tv_u;
 };
Index: gold/archive.cc
===================================================================
RCS file: /cvs/src/src/gold/archive.cc,v
retrieving revision 1.69
diff -u -u -p -r1.69 archive.cc
--- gold/archive.cc	2 Jun 2011 20:13:23 -0000	1.69
+++ gold/archive.cc	13 Jul 2011 01:32:37 -0000
@@ -653,7 +653,8 @@ Archive::get_elf_object_for_member(off_t
     {
       Object* obj = parameters->options().plugins()->claim_file(input_file,
                                                                 memoff,
-                                                                memsize);
+                                                                memsize,
+								NULL);
       if (obj != NULL)
         {
           // The input file was claimed by a plugin, and its symbols
Index: gold/layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.215
diff -u -u -p -r1.215 layout.cc
--- gold/layout.cc	11 Jul 2011 16:19:50 -0000	1.215
+++ gold/layout.cc	13 Jul 2011 01:32:37 -0000
@@ -399,11 +399,14 @@ Layout::Layout(int number_of_input_files
     any_postprocessing_sections_(false),
     resized_signatures_(false),
     have_stabstr_section_(false),
+    section_ordering_specified_(false),
     incremental_inputs_(NULL),
     record_output_section_data_from_script_(false),
     script_output_section_data_list_(),
     segment_states_(NULL),
     relaxation_debug_check_(NULL),
+    input_section_position_(),
+    input_section_glob_(),
     incremental_base_(NULL),
     free_list_()
 {
@@ -2209,7 +2212,7 @@ Layout::find_section_order_index(const s
 }
 
 // Read the sequence of input sections from the file specified with
-// --section-ordering-file.
+// option --section-ordering-file.
 
 void
 Layout::read_layout_from_file()
@@ -2225,6 +2228,7 @@ Layout::read_layout_from_file()
 
   std::getline(in, line);   // this chops off the trailing \n, if any
   unsigned int position = 1;
+  this->set_section_ordering_specified();
 
   while (in)
     {
Index: gold/layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.97
diff -u -u -p -r1.97 layout.h
--- gold/layout.h	1 Jul 2011 22:05:01 -0000	1.97
+++ gold/layout.h	13 Jul 2011 01:32:37 -0000
@@ -492,6 +492,14 @@ class Layout
 	 const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
 	 unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
 
+  bool
+  is_section_ordering_specified()
+  { return this->section_ordering_specified_; }
+
+  void
+  set_section_ordering_specified()
+  { this->section_ordering_specified_ = true; }
+
   // For incremental updates, allocate a block of memory from the
   // free list.  Find a block starting at or after MINOFF.
   off_t
@@ -501,6 +509,8 @@ class Layout
   unsigned int
   find_section_order_index(const std::string&);
 
+  // Read the sequence of input sections from the file specified with
+  // linker option --section-ordering-file.
   void
   read_layout_from_file();
 
@@ -1262,6 +1272,9 @@ class Layout
   bool resized_signatures_;
   // Whether we have created a .stab*str output section.
   bool have_stabstr_section_;
+  // True if the input sections in the output sections should be sorted
+  // as specified in a section ordering file.
+  bool section_ordering_specified_;
   // In incremental build, holds information check the inputs and build the
   // .gnu_incremental_inputs section.
   Incremental_inputs* incremental_inputs_;
Index: gold/main.cc
===================================================================
RCS file: /cvs/src/src/gold/main.cc,v
retrieving revision 1.44
diff -u -u -p -r1.44 main.cc
--- gold/main.cc	8 Jun 2011 04:43:28 -0000	1.44
+++ gold/main.cc	13 Jul 2011 01:32:37 -0000
@@ -195,10 +195,6 @@ main(int argc, char** argv)
   if (parameters->options().relocatable())
     command_line.script_options().version_script_info()->clear();
 
-  // Load plugin libraries.
-  if (command_line.options().has_plugins())
-    command_line.options().plugins()->load_plugins();
-
   // The work queue.
   Workqueue workqueue(command_line.options());
 
@@ -234,6 +230,10 @@ main(int argc, char** argv)
   if (parameters->options().section_ordering_file())
     layout.read_layout_from_file();
 
+  // Load plugin libraries.
+  if (command_line.options().has_plugins())
+    command_line.options().plugins()->load_plugins(&layout);
+
   // Get the search path from the -L options.
   Dirsearch search_path;
   search_path.initialize(&workqueue, &command_line.options().library_path());
Index: gold/output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.155
diff -u -u -p -r1.155 output.cc
--- gold/output.cc	8 Jul 2011 22:48:08 -0000	1.155
+++ gold/output.cc	13 Jul 2011 01:32:38 -0000
@@ -2296,7 +2296,7 @@ Output_section::add_input_section(Layout
       && (sh_flags & elfcpp::SHF_EXECINSTR) != 0
       && parameters->target().has_code_fill()
       && (parameters->target().may_relax()
-          || parameters->options().section_ordering_file()))
+          || layout->is_section_ordering_specified()))
     {
       gold_assert(this->fills_.empty());
       this->generate_code_fills_at_write_ = true;
@@ -2335,10 +2335,10 @@ Output_section::add_input_section(Layout
       || this->must_sort_attached_input_sections()
       || parameters->options().user_set_Map()
       || parameters->target().may_relax()
-      || parameters->options().section_ordering_file())
+      || layout->is_section_ordering_specified())
     {
       Input_section isecn(object, shndx, input_section_size, addralign);
-      if (parameters->options().section_ordering_file())
+      if (layout->is_section_ordering_specified())
         {
           unsigned int section_order_index =
             layout->find_section_order_index(std::string(secname));
@@ -2421,7 +2421,7 @@ Output_section::add_relaxed_input_sectio
 
   // If the --section-ordering-file option is used to specify the order of
   // sections, we need to keep track of sections.
-  if (parameters->options().section_ordering_file())
+  if (layout->is_section_ordering_specified())
     {
       unsigned int section_order_index =
         layout->find_section_order_index(name);
@@ -3339,6 +3339,38 @@ Output_section::Input_section_sort_secti
   return s1_secn_index < s2_secn_index;
 }
 
+// This updates the section order index of input sections according to the
+// the order specified in the mapping from Section id to order index.
+
+void
+Output_section::update_section_layout(
+  const Section_layout_order& order_map)
+{
+  for (Input_section_list::iterator p = this->input_sections_.begin();
+       p != this->input_sections_.end();
+       ++p)
+    {
+      if (p->is_input_section()
+	  || p->is_relaxed_input_section())
+        {
+	  Object* obj = (p->is_input_section()
+			 ? p->relobj()
+		         : p->relaxed_input_section()->relobj());
+	  unsigned int shndx = p->shndx();
+	  Section_layout_order::const_iterator it
+	    = order_map.find(Section_id(obj, shndx));
+	  if (it == order_map.end())
+	    continue;
+	  unsigned int section_order_index = it->second;
+	  if (section_order_index != 0)
+            {
+              p->set_section_order_index(section_order_index);
+              this->set_input_section_order_specified();
+	    }
+        }
+    }
+}
+
 // Sort the input sections attached to an output section.
 
 void
@@ -3381,7 +3413,7 @@ Output_section::sort_attached_input_sect
     }
   else
     {
-      gold_assert(parameters->options().section_ordering_file());
+      gold_assert(this->input_section_order_specified());
       std::sort(sort_list.begin(), sort_list.end(),
 	        Input_section_sort_section_order_index_compare());
     }
Index: gold/output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.126
diff -u -u -p -r1.126 output.h
--- gold/output.h	6 Jul 2011 21:19:32 -0000	1.126
+++ gold/output.h	13 Jul 2011 01:32:38 -0000
@@ -2665,6 +2665,11 @@ class Output_section : public Output_dat
   flags() const
   { return this->flags_; }
 
+  typedef std::map<Section_id, unsigned int> Section_layout_order;
+
+  void
+  update_section_layout(const Section_layout_order& order_map);
+
   // Update the output section flags based on input section flags.
   void
   update_flags_for_input_section(elfcpp::Elf_Xword flags);
Index: gold/plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.47
diff -u -u -p -r1.47 plugin.cc
--- gold/plugin.cc	25 May 2011 00:17:47 -0000	1.47
+++ gold/plugin.cc	13 Jul 2011 01:32:38 -0000
@@ -89,6 +89,29 @@ set_extra_library_path(const char *path)
 static enum ld_plugin_status
 message(int level, const char *format, ...);
 
+static enum ld_plugin_status
+get_input_section_count(const void* handle, unsigned int* count);
+
+static enum ld_plugin_status
+get_input_section_type(const struct ld_plugin_section section,
+                       unsigned int* type);
+
+static enum ld_plugin_status
+get_input_section_name(const struct ld_plugin_section section,
+                       char** section_name_ptr);
+
+static enum ld_plugin_status
+get_input_section_contents(const struct ld_plugin_section section,
+                           const unsigned char** section_contents,
+		           size_t* len);
+
+static enum ld_plugin_status
+update_section_order(const struct ld_plugin_section *section_list,
+		     unsigned int num_sections);
+
+static enum ld_plugin_status
+allow_section_ordering();
+
 };
 
 #endif // ENABLE_PLUGINS
@@ -133,7 +156,8 @@ Plugin::load()
   sscanf(ver, "%d.%d", &major, &minor);
 
   // Allocate and populate a transfer vector.
-  const int tv_fixed_size = 17;
+  const int tv_fixed_size = 23;
+
   int tv_size = this->args_.size() + tv_fixed_size;
   ld_plugin_tv* tv = new ld_plugin_tv[tv_size];
 
@@ -216,6 +240,30 @@ Plugin::load()
   tv[i].tv_u.tv_set_extra_library_path = set_extra_library_path;
 
   ++i;
+  tv[i].tv_tag = LDPT_GET_INPUT_SECTION_COUNT;
+  tv[i].tv_u.tv_get_input_section_count = get_input_section_count;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_INPUT_SECTION_TYPE;
+  tv[i].tv_u.tv_get_input_section_type = get_input_section_type;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_INPUT_SECTION_NAME;
+  tv[i].tv_u.tv_get_input_section_name = get_input_section_name;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_INPUT_SECTION_CONTENTS;
+  tv[i].tv_u.tv_get_input_section_contents = get_input_section_contents;
+
+  ++i;
+  tv[i].tv_tag = LDPT_UPDATE_SECTION_ORDER;
+  tv[i].tv_u.tv_update_section_order = update_section_order;
+
+  ++i;
+  tv[i].tv_tag = LDPT_ALLOW_SECTION_ORDERING;
+  tv[i].tv_u.tv_allow_section_ordering = allow_section_ordering;
+
+  ++i;
   tv[i].tv_tag = LDPT_NULL;
   tv[i].tv_u.tv_val = 0;
 
@@ -326,8 +374,9 @@ Plugin_manager::~Plugin_manager()
 // Load all plugin libraries.
 
 void
-Plugin_manager::load_plugins()
+Plugin_manager::load_plugins(Layout* layout)
 {
+  this->layout_ = layout;
   for (this->current_ = this->plugins_.begin();
        this->current_ != this->plugins_.end();
        ++this->current_)
@@ -338,7 +387,7 @@ Plugin_manager::load_plugins()
 
 Pluginobj*
 Plugin_manager::claim_file(Input_file* input_file, off_t offset,
-                           off_t filesize)
+                           off_t filesize, Object* elf_object)
 {
   if (this->in_replacement_phase_)
     return NULL;
@@ -350,6 +399,9 @@ Plugin_manager::claim_file(Input_file* i
   this->plugin_input_file_.offset = offset;
   this->plugin_input_file_.filesize = filesize;
   this->plugin_input_file_.handle = reinterpret_cast<void*>(handle);
+  if (elf_object != NULL)
+    this->objects_.push_back(elf_object);
+  this->in_claim_file_handler_ = true;
 
   for (this->current_ = this->plugins_.begin();
        this->current_ != this->plugins_.end();
@@ -358,9 +410,11 @@ Plugin_manager::claim_file(Input_file* i
       if ((*this->current_)->claim_file(&this->plugin_input_file_))
         {
 	  this->any_claimed_ = true;
+	  this->in_claim_file_handler_ = false;
 
-          if (this->objects_.size() > handle)
-            return this->objects_[handle];
+          if (this->objects_.size() > handle
+              && this->objects_[handle]->pluginobj() != NULL)
+            return this->objects_[handle]->pluginobj();
 
           // If the plugin claimed the file but did not call the
           // add_symbols callback, we need to create the Pluginobj now.
@@ -369,6 +423,7 @@ Plugin_manager::claim_file(Input_file* i
         }
     }
 
+  this->in_claim_file_handler_ = false;
   return NULL;
 }
 
@@ -402,7 +457,7 @@ Plugin_manager::save_input_group(Input_g
 void
 Plugin_manager::all_symbols_read(Workqueue* workqueue, Task* task,
                                  Input_objects* input_objects,
-	                         Symbol_table* symtab, Layout* layout,
+	                         Symbol_table* symtab,
 	                         Dirsearch* dirpath, Mapfile* mapfile,
 	                         Task_token** last_blocker)
 {
@@ -411,7 +466,6 @@ Plugin_manager::all_symbols_read(Workque
   this->task_ = task;
   this->input_objects_ = input_objects;
   this->symtab_ = symtab;
-  this->layout_ = layout;
   this->dirpath_ = dirpath;
   this->mapfile_ = mapfile;
   this->this_blocker_ = NULL;
@@ -599,12 +653,20 @@ Pluginobj*
 Plugin_manager::make_plugin_object(unsigned int handle)
 {
   // Make sure we aren't asked to make an object for the same handle twice.
-  if (this->objects_.size() != handle)
+  if (this->objects_.size() != handle
+      && this->objects_[handle]->pluginobj() != NULL)
     return NULL;
 
   Pluginobj* obj = make_sized_plugin_object(this->input_file_,
                                             this->plugin_input_file_.offset,
                                             this->plugin_input_file_.filesize);
+
+
+  // If the elf object for this file was pushed into the objects_ vector, delete
+  // it to make room for the Pluginobj as this file is claimed.
+  if (this->objects_.size() != handle)
+    this->objects_.pop_back();
+
   this->objects_.push_back(obj);
   return obj;
 }
@@ -616,7 +678,7 @@ ld_plugin_status
 Plugin_manager::get_input_file(unsigned int handle,
                                struct ld_plugin_input_file* file)
 {
-  Pluginobj* obj = this->object(handle);
+  Pluginobj* obj = this->object(handle)->pluginobj();
   if (obj == NULL)
     return LDPS_BAD_HANDLE;
 
@@ -634,7 +696,7 @@ Plugin_manager::get_input_file(unsigned 
 ld_plugin_status
 Plugin_manager::release_input_file(unsigned int handle)
 {
-  Pluginobj* obj = this->object(handle);
+  Pluginobj* obj = this->object(handle)->pluginobj();
   if (obj == NULL)
     return LDPS_BAD_HANDLE;
 
@@ -642,6 +704,23 @@ Plugin_manager::release_input_file(unsig
   return LDPS_OK;
 }
 
+// Get the elf object corresponding to the handle. Return NULL if we
+// found a Pluginobj instead.
+
+Object*
+Plugin_manager::get_elf_object(const void* handle)
+{
+  Object* obj = parameters->options().plugins()->object(
+      static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
+
+  // The object should not be a Pluginobj.
+  if (obj == NULL
+      || obj->pluginobj() != NULL)
+    return NULL;
+
+  return obj;
+}
+
 ld_plugin_status
 Plugin_manager::get_view(unsigned int handle, const void **viewp)
 {
@@ -659,7 +738,7 @@ Plugin_manager::get_view(unsigned int ha
   else
     {
       // An already claimed file.
-      Pluginobj* obj = this->object(handle);
+      Pluginobj* obj = this->object(handle)->pluginobj();
       if (obj == NULL)
         return LDPS_BAD_HANDLE;
       offset = obj->offset();
@@ -1226,7 +1305,6 @@ Plugin_hook::run(Workqueue* workqueue)
                                              this,
                                              this->input_objects_,
                                              this->symtab_,
-                                             this->layout_,
                                              this->dirpath_,
                                              this->mapfile_,
                                              &this->this_blocker_);
@@ -1321,7 +1399,7 @@ get_symbols(const void* handle, int nsym
 {
   gold_assert(parameters->options().has_plugins());
   Pluginobj* obj = parameters->options().plugins()->object(
-      static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
+    static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)))->pluginobj();
   if (obj == NULL)
     return LDPS_ERR;
   return obj->get_symbol_resolution_info(nsyms, syms);
@@ -1384,6 +1462,160 @@ message(int level, const char* format, .
   return LDPS_OK;
 }
 
+// Get the section count of the object corresponding to the handle.  This
+// plugin interface can only be called in the claim_file handler of the plugin.
+
+static enum ld_plugin_status
+get_input_section_count(const void* handle, unsigned int* count)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_claim_file_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_elf_object(handle);
+
+  if (obj == NULL)
+    return LDPS_ERR;
+
+  *count = obj->shnum();
+  return LDPS_OK;
+}
+
+// Get the type of the specified section in the object corresponding
+// to the handle.  This plugin interface can only be called in the
+// claim_file handler of the plugin.
+
+static enum ld_plugin_status
+get_input_section_type(const struct ld_plugin_section section,
+                       unsigned int* type)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_claim_file_handler())
+    return LDPS_ERR;
+
+  Object* obj
+    = parameters->options().plugins()->get_elf_object(section.handle); 
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  *type = obj->section_type(section.shndx);
+  return LDPS_OK;
+}
+
+// Get the name of the specified section in the object corresponding
+// to the handle.  This plugin interface can only be called in the
+// claim_file handler of the plugin.
+
+static enum ld_plugin_status
+get_input_section_name(const struct ld_plugin_section section,
+                       char** section_name_ptr)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_claim_file_handler())
+    return LDPS_ERR;
+
+  Object* obj
+    = parameters->options().plugins()->get_elf_object(section.handle); 
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  // Check if the object is locked before getting the section name.
+  gold_assert(obj->is_locked());
+
+  const std::string section_name = obj->section_name(section.shndx);
+  const char* section_name_c_ptr = section_name.c_str();
+  *section_name_ptr
+    = static_cast<char*>(malloc(strlen(section_name_c_ptr) + 1));
+  strcpy(*section_name_ptr, section_name_c_ptr);
+  return LDPS_OK;
+}
+
+// Get the contents of the specified section in the object corresponding
+// to the handle.  This plugin interface can only be called in the
+// claim_file handler of the plugin.
+
+static enum ld_plugin_status
+get_input_section_contents(const struct ld_plugin_section section,
+			   const unsigned char** section_contents_ptr,
+			   size_t* len)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_claim_file_handler())
+    return LDPS_ERR;
+
+  Object* obj
+    = parameters->options().plugins()->get_elf_object(section.handle); 
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  // Check if the object is locked before getting the section contents.
+  gold_assert(obj->is_locked());
+
+  section_size_type plen;
+  *section_contents_ptr
+      = obj->section_contents(section.shndx, &plen, false);
+  *len = plen;
+  return LDPS_OK;
+}
+
+// Specify the ordering of sections in the final layout. The sections are
+// specified as (handle,shndx) pairs in the two arrays in the order in
+// which they should appear in the final layout.
+
+static enum ld_plugin_status
+update_section_order(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;
+
+  std::map<Section_id, unsigned int> order_map;
+
+  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;
+      Section_id secn_id(obj, shndx);
+      order_map[secn_id] = i + 1;
+    }
+
+  Layout* layout = parameters->options().plugins()->layout();
+  gold_assert (layout != NULL);
+
+  for (Layout::Section_list::const_iterator p = layout->section_list().begin();
+       p != layout->section_list().end();
+       ++p)
+    (*p)->update_section_layout(order_map);
+
+  return LDPS_OK;
+}
+
+// Let the linker know that the sections could be reordered.
+
+static enum ld_plugin_status
+allow_section_ordering()
+{
+  gold_assert(parameters->options().has_plugins());
+  Layout* layout = parameters->options().plugins()->layout();
+  layout->set_section_ordering_specified();
+  return LDPS_OK;
+}
+
 #endif // ENABLE_PLUGINS
 
 // Allocate a Pluginobj object of the appropriate size and endianness.
Index: gold/plugin.h
===================================================================
RCS file: /cvs/src/src/gold/plugin.h,v
retrieving revision 1.19
diff -u -u -p -r1.19 plugin.h
--- gold/plugin.h	12 Apr 2011 00:44:48 -0000	1.19
+++ gold/plugin.h	13 Jul 2011 01:32:38 -0000
@@ -131,6 +131,7 @@ class Plugin_manager
     : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
       plugin_input_file_(), rescannable_(), undefined_symbols_(),
       any_claimed_(false), in_replacement_phase_(false), any_added_(false),
+      in_claim_file_handler_(false),
       options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
       symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
       this_blocker_(NULL), extra_search_path_()
@@ -153,11 +154,22 @@ class Plugin_manager
 
   // Load all plugin libraries.
   void
-  load_plugins();
+  load_plugins(Layout* layout);
 
   // Call the plugin claim-file handlers in turn to see if any claim the file.
   Pluginobj*
-  claim_file(Input_file* input_file, off_t offset, off_t filesize);
+  claim_file(Input_file* input_file, off_t offset, off_t filesize,
+             Object* elf_object);
+
+  // Get the object associated with the handle and check if it is an elf object.
+  // If it is not a Pluginobj, it is an elf object.
+  Object*
+  get_elf_object(const void* handle);
+
+  // True if the claim_file handler of the plugins is being called.
+  bool
+  in_claim_file_handler()
+  { return in_claim_file_handler_; }
 
   // Let the plugin manager save an archive for later rescanning.
   // This takes ownership of the Archive pointer.
@@ -173,7 +185,7 @@ class Plugin_manager
   void
   all_symbols_read(Workqueue* workqueue, Task* task,
                    Input_objects* input_objects, Symbol_table* symtab,
-                   Layout* layout, Dirsearch* dirpath, Mapfile* mapfile,
+                   Dirsearch* dirpath, Mapfile* mapfile,
                    Task_token** last_blocker);
 
   // Tell the plugin manager that we've a new undefined symbol which
@@ -219,7 +231,7 @@ class Plugin_manager
   make_plugin_object(unsigned int handle);
 
   // Return the Pluginobj associated with the given HANDLE.
-  Pluginobj*
+  Object*
   object(unsigned int handle) const
   {
     if (handle >= this->objects_.size())
@@ -265,6 +277,14 @@ class Plugin_manager
   in_replacement_phase() const
   { return this->in_replacement_phase_; }
 
+  Input_objects*
+  input_objects() const
+  { return this->input_objects_; }
+
+  Layout*
+  layout()
+  { return this->layout_; }
+
  private:
   Plugin_manager(const Plugin_manager&);
   Plugin_manager& operator=(const Plugin_manager&);
@@ -293,7 +313,7 @@ class Plugin_manager
   };
 
   typedef std::list<Plugin*> Plugin_list;
-  typedef std::vector<Pluginobj*> Object_list;
+  typedef std::vector<Object*> Object_list;
   typedef std::vector<Relobj*> Deferred_layout_list;
   typedef std::vector<Rescannable> Rescannable_list;
   typedef std::vector<Symbol*> Undefined_symbol_list;
@@ -340,6 +360,9 @@ class Plugin_manager
   // Whether any input files or libraries were added by a plugin.
   bool any_added_;
 
+  // Set to true when the claim_file handler of a plugin is called.
+  bool in_claim_file_handler_;
+
   const General_options& options_;
   Workqueue* workqueue_;
   Task* task_;
Index: gold/readsyms.cc
===================================================================
RCS file: /cvs/src/src/gold/readsyms.cc,v
retrieving revision 1.50
diff -u -u -p -r1.50 readsyms.cc
--- gold/readsyms.cc	6 Jul 2011 22:07:59 -0000	1.50
+++ gold/readsyms.cc	13 Jul 2011 01:32:38 -0000
@@ -320,12 +320,33 @@ Read_symbols::do_read_symbols(Workqueue*
 	}
     }
 
+  Object* elf_obj = NULL;
+  bool unconfigured;
+  bool* punconfigured = NULL;
+  if (is_elf)
+    {
+      // This is an ELF object.
+
+      unconfigured = false;
+      punconfigured = (input_file->will_search_for()
+		       ? &unconfigured
+		       : NULL);
+      elf_obj = make_elf_object(input_file->filename(),
+				input_file, 0, ehdr, read_size,
+				punconfigured);
+    }
+
   if (parameters->options().has_plugins())
     {
       Pluginobj* obj = parameters->options().plugins()->claim_file(input_file,
-                                                                   0, filesize);
+                                                                   0, filesize,
+								   elf_obj);
       if (obj != NULL)
         {
+	  // Delete the elf_obj, this file has been claimed.
+	  if (elf_obj != NULL)
+	    delete elf_obj;
+
           // The input file was claimed by a plugin, and its symbols
           // have been provided by the plugin.
 
@@ -359,14 +380,7 @@ Read_symbols::do_read_symbols(Workqueue*
     {
       // This is an ELF object.
 
-      bool unconfigured = false;
-      bool* punconfigured = (input_file->will_search_for()
-			     ? &unconfigured
-			     : NULL);
-      Object* obj = make_elf_object(input_file->filename(),
-				    input_file, 0, ehdr, read_size,
-				    punconfigured);
-      if (obj == NULL)
+      if (elf_obj == NULL)
 	{
 	  if (unconfigured)
 	    {
@@ -382,7 +396,7 @@ Read_symbols::do_read_symbols(Workqueue*
 	}
 
       Read_symbols_data* sd = new Read_symbols_data;
-      obj->read_symbols(sd);
+      elf_obj->read_symbols(sd);
 
       // Opening the file locked it, so now we need to unlock it.  We
       // need to unlock it before queuing the Add_symbols task,
@@ -397,7 +411,7 @@ Read_symbols::do_read_symbols(Workqueue*
       if (this->member_ != NULL)
         {
           this->member_->sd_ = sd;
-          this->member_->obj_ = obj;
+          this->member_->obj_ = elf_obj;
           this->member_->arg_serial_ =
               this->input_argument_->file().arg_serial();
           return true;
@@ -412,7 +426,7 @@ Read_symbols::do_read_symbols(Workqueue*
 					    this->dirindex_,
 					    this->mapfile_,
 					    this->input_argument_,
-					    obj,
+					    elf_obj,
 					    NULL,
 					    sd,
 					    this->this_blocker_,
Index: gold/testsuite/plugin_test.c
===================================================================
RCS file: /cvs/src/src/gold/testsuite/plugin_test.c,v
retrieving revision 1.4
diff -u -u -p -r1.4 plugin_test.c
--- gold/testsuite/plugin_test.c	9 Nov 2009 16:11:34 -0000	1.4
+++ gold/testsuite/plugin_test.c	13 Jul 2011 01:32:38 -0000
@@ -60,6 +60,12 @@ static ld_plugin_add_input_file add_inpu
 static ld_plugin_message message = NULL;
 static ld_plugin_get_input_file get_input_file = NULL;
 static ld_plugin_release_input_file release_input_file = NULL;
+static ld_plugin_get_input_section_count get_input_section_count = NULL;
+static ld_plugin_get_input_section_type get_input_section_type = NULL;
+static ld_plugin_get_input_section_name get_input_section_name = NULL;
+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;
 
 #define MAXOPTS 10
 
@@ -126,6 +132,24 @@ onload(struct ld_plugin_tv *tv)
         case LDPT_RELEASE_INPUT_FILE:
           release_input_file = entry->tv_u.tv_release_input_file;
           break;
+        case LDPT_GET_INPUT_SECTION_COUNT:
+          get_input_section_count = *entry->tv_u.tv_get_input_section_count;
+          break;
+        case LDPT_GET_INPUT_SECTION_TYPE:
+          get_input_section_type = *entry->tv_u.tv_get_input_section_type;
+          break;
+        case LDPT_GET_INPUT_SECTION_NAME:
+          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;
+          break;
+	case LDPT_UPDATE_SECTION_ORDER:
+	  update_section_order = *entry->tv_u.tv_update_section_order;
+	  break;
+	case LDPT_ALLOW_SECTION_ORDERING:
+	  allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
+	  break;
         default:
           break;
         }
@@ -179,6 +203,42 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if (get_input_section_count == NULL)
+    {
+      fprintf(stderr, "tv_get_input_section_count interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_input_section_type == NULL)
+    {
+      fprintf(stderr, "tv_get_input_section_type interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_input_section_name == NULL)
+    {
+      fprintf(stderr, "tv_get_input_section_name interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_input_section_contents == NULL)
+    {
+      fprintf(stderr, "tv_get_input_section_contents interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (update_section_order == NULL)
+    {
+      fprintf(stderr, "tv_update_section_order interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (allow_section_ordering == NULL)
+    {
+      fprintf(stderr, "tv_allow_section_ordering interface missing\n");
+      return LDPS_ERR;
+    }
+
   return LDPS_OK;
 }
 


More information about the Binutils mailing list