public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
@ 2011-03-03 23:58 Sriraman Tallam
  2011-03-10  0:45 ` Cary Coutant
  0 siblings, 1 reply; 19+ messages in thread
From: Sriraman Tallam @ 2011-03-03 23:58 UTC (permalink / raw)
  To: binutils, Ian Lance Taylor, Cary Coutant

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

Hi,

  I am working on a linker plugin to use callgraph edge profiles
generated by GCC to guide function layout in the linker. The compiler
passes the callgraph edge profile values to the linker via special
.note sections, I am working on a GCC patch to do this. The linker
plugin reads the .note sections and constructs an annotated callgraph
with the edge profiles. It then uses the Pettis-Hansen algorithm,
"Profile-guided Code Positioning, PLDI 1990, K. Pettis, and R.C.
Hansen.", to determine the order of functions in the final layout.

  In order for my plugin to do the above, I need the interfaces to
read section contents & attributes and reorder them. I have attached a
patch for review that adds these interfaces to the GOLD plugin
infrastructure. I have also made appropriate changes to allow section
ordering from a plugin.

	* layout.cc (Layout::Layout): Initialize section_ordering_specified_,
	input_section_position_, and input_section_glob_.
	(Layout::update_layout_of_sections): New function.
	(read_layout_from_file): Add parameter filename and call function
	section_ordering_specified.
	* layout.h (is_section_ordering_specified): New function.
	(section_ordering_specified): New function.
	(read_layout_from_file): Add parameter filename.
	(update_layout_of_sections): New function.
	(section_ordering_specified_): New boolean member.
	* main.cc(main): Call load_plugins after layout object is defined.
	Call read_layout_from_file when section ordering is specified.
	* output.cc (Output_section::add_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.
	* plugin.cc (get_object_handle): New function.
	(get_section_count): New function.
	(get_section_type): New function.
	(get_section_name): New function.
	(get_section_contents): New function.
	(read_layout_from_file): New function.
	(allow_section_ordering): New function.	
	(Plugin::load): Add the new interfaces to the transfer vector.
	(Plugin_manager::load_plugins): New parameter.
	* plugin.h (input_objects): New function.
	(layout): New function.
	* plugin_test.c (get_object_handle): 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.
	(read_layout_from_file): New function pointer.
	(allow_section_ordering): New function pointer.
	(onload): Check if the new interfaces exist.

Thanks,
-Sri.

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

Index: plugin-api.h
===================================================================
RCS file: /cvs/src/src/include/plugin-api.h,v
retrieving revision 1.13
diff -u -u -p -r1.13 plugin-api.h
--- plugin-api.h	3 Jan 2011 21:05:50 -0000	1.13
+++ plugin-api.h	3 Mar 2011 22:28:49 -0000
@@ -240,6 +240,58 @@ typedef
 enum ld_plugin_status
 (*ld_plugin_message) (int level, const char *format, ...);
 
+/* The linker's interface for retrieving the handle (pointer) to an object. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_object_handle) (const char* filename, void** handle);
+
+/* The linker's interface for retrieving the number of sections in an object.
+   The handle parameter can be obtained using the "ld_plugin_get_object_handle"
+   interface.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_count) (void* handle, unsigned int* count);
+
+/* The linker's interface for retrieving the section type of a specific
+   section in an object.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_type) (void* handle, unsigned int shndx,
+                               unsigned int* type);
+
+/* The linker's interface for retrieving the name of specific section in
+   an object.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
+                               char** section_name_ptr);
+/* The linker's interface for retrieving the contents of a specific section
+   in an object.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_contents) (void* handle, unsigned int shndx,
+                                   unsigned char** section_contents,
+                                   unsigned int* len);
+
+/* The linker's interface for specifying the desired order of sections
+   through a file.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_read_layout_from_file) (const char* filename);
+
+/* The linker's interface for specifying that reordering of sections is
+   desired.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_allow_section_ordering) (void);
+
 enum ld_plugin_level
 {
   LDPL_INFO,
@@ -269,7 +321,14 @@ enum ld_plugin_tag
   LDPT_ADD_INPUT_LIBRARY,
   LDPT_OUTPUT_NAME,
   LDPT_SET_EXTRA_LIBRARY_PATH,
-  LDPT_GNU_LD_VERSION
+  LDPT_GNU_LD_VERSION,
+  LDPT_GET_SECTION_COUNT,
+  LDPT_GET_SECTION_TYPE,
+  LDPT_GET_OBJECT_HANDLE,
+  LDPT_GET_SECTION_NAME,
+  LDPT_GET_SECTION_CONTENTS,
+  LDPT_READ_LAYOUT_FROM_FILE,
+  LDPT_ALLOW_SECTION_ORDERING
 };
 
 /* The plugin transfer vector.  */
@@ -292,6 +351,13 @@ 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_object_handle tv_get_object_handle;
+    ld_plugin_get_section_count tv_get_section_count;
+    ld_plugin_get_section_type tv_get_section_type;
+    ld_plugin_get_section_name tv_get_section_name;
+    ld_plugin_get_section_contents tv_get_section_contents;
+    ld_plugin_read_layout_from_file tv_read_layout_from_file;
+    ld_plugin_allow_section_ordering tv_allow_section_ordering;
   } tv_u;
 };
 
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.190
diff -u -u -p -r1.190 layout.cc
--- layout.cc	10 Jan 2011 21:57:31 -0000	1.190
+++ layout.cc	3 Mar 2011 22:29:00 -0000
@@ -207,7 +207,11 @@ Layout::Layout(int number_of_input_files
     record_output_section_data_from_script_(false),
     script_output_section_data_list_(),
     segment_states_(NULL),
-    relaxation_debug_check_(NULL)
+    relaxation_debug_check_(NULL),
+    section_ordering_specified_(false),
+    input_section_position_(),
+    input_section_glob_()
+
 {
   // Make space for more than enough segments for a typical file.
   // This is just for efficiency--it's OK if we wind up needing more.
@@ -1817,13 +1821,27 @@ Layout::find_section_order_index(const s
   return 0;
 }
 
+// Updates the input section order of all output sections.
+
+void
+Layout::update_layout_of_sections()
+{
+  for (Section_list::iterator p = this->section_list_.begin();
+       p != this->section_list_.end();
+       ++p)
+    {
+      if ((*p) == NULL)
+        continue;
+      (*p)->update_section_layout(this);
+    }
+}
+
 // Read the sequence of input sections from the file specified with
 // --section-ordering-file.
 
 void
-Layout::read_layout_from_file()
+Layout::read_layout_from_file(const char* filename)
 {
-  const char* filename = parameters->options().section_ordering_file();
   std::ifstream in;
   std::string line;
 
@@ -1834,6 +1852,7 @@ Layout::read_layout_from_file()
 
   std::getline(in, line);   // this chops off the trailing \n, if any
   unsigned int position = 1;
+  this->section_ordering_specified();  
 
   while (in)
     {
Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.88
diff -u -u -p -r1.88 layout.h
--- layout.h	14 Dec 2010 19:03:30 -0000	1.88
+++ layout.h	3 Mar 2011 22:29:00 -0000
@@ -414,11 +414,23 @@ 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 section_ordering_specified_; }
+
+  void
+  section_ordering_specified()
+  { section_ordering_specified_ = true; }
+
+
   unsigned int
   find_section_order_index(const std::string&);
 
+   void
+  read_layout_from_file(const char* filename);
+
   void
-  read_layout_from_file();
+  update_layout_of_sections();
 
   // Layout an input reloc section when doing a relocatable link.  The
   // section is RELOC_SHNDX in OBJECT, with data in SHDR.
@@ -1147,6 +1159,7 @@ class Layout
   Segment_states* segment_states_;
   // A relaxation debug checker.  We only create one when in debugging mode.
   Relaxation_debug_check* relaxation_debug_check_;
+  bool section_ordering_specified_;
   // 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: main.cc
===================================================================
RCS file: /cvs/src/src/gold/main.cc,v
retrieving revision 1.42
diff -u -u -p -r1.42 main.cc
--- main.cc	14 Dec 2010 19:03:30 -0000	1.42
+++ main.cc	3 Mar 2011 22:29:00 -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());
 
@@ -231,8 +227,13 @@ main(int argc, char** argv)
   if (layout.incremental_inputs() != NULL)
     layout.incremental_inputs()->report_command_line(argc, 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);
+
+  const char* section_ordering_file = parameters->options().section_ordering_file();
+  if (section_ordering_file)
+    layout.read_layout_from_file(section_ordering_file);
 
   // Get the search path from the -L options.
   Dirsearch search_path;
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.140
diff -u -u -p -r1.140 output.cc
--- output.cc	12 Feb 2011 03:19:24 -0000	1.140
+++ output.cc	3 Mar 2011 22:29:00 -0000
@@ -2165,10 +2165,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));
@@ -3041,6 +3041,32 @@ Output_section::Input_section_sort_secti
   return s1_secn_index < s2_secn_index;
 }
 
+// Updates the ordering of input sections in this output section.
+
+void
+Output_section::update_section_layout(Layout* layout)
+{
+  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());
+          std::string section_name = obj->section_name((*p).shndx());
+	  unsigned int section_order_index =
+            layout->find_section_order_index(std::string(section_name));
+	  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
@@ -3083,7 +3109,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: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.118
diff -u -u -p -r1.118 output.h
--- output.h	23 Dec 2010 19:56:14 -0000	1.118
+++ output.h	3 Mar 2011 22:29:00 -0000
@@ -2564,6 +2564,9 @@ class Output_section : public Output_dat
   flags() const
   { return this->flags_; }
 
+  void
+  update_section_layout(Layout* layout);
+
   // Update the output section flags based on input section flags.
   void
   update_flags_for_input_section(elfcpp::Elf_Xword flags);
Index: plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.43
diff -u -u -p -r1.43 plugin.cc
--- plugin.cc	8 Feb 2011 05:03:19 -0000	1.43
+++ plugin.cc	3 Mar 2011 22:29:00 -0000
@@ -86,6 +86,31 @@ set_extra_library_path(const char *path)
 static enum ld_plugin_status
 message(int level, const char *format, ...);
 
+static enum ld_plugin_status
+get_object_handle(const char* filename, void** handle);
+
+static enum ld_plugin_status
+get_section_count(void* handle, unsigned int* count);
+
+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx,
+                 unsigned int* type);
+
+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx,
+                 char** section_name_ptr);
+
+static enum ld_plugin_status
+get_section_contents(void* handle, unsigned int shndx,
+                     unsigned char** section_contents,
+		     unsigned int* len);
+
+static enum ld_plugin_status
+read_layout_from_file(const char* filename);
+
+static enum ld_plugin_status
+allow_section_ordering();
+
 };
 
 #endif // ENABLE_PLUGINS
@@ -130,7 +155,7 @@ Plugin::load()
   sscanf(ver, "%d.%d", &major, &minor);
 
   // Allocate and populate a transfer vector.
-  const int tv_fixed_size = 16;
+  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];
 
@@ -208,6 +233,34 @@ Plugin::load()
   tv[i].tv_tag = LDPT_SET_EXTRA_LIBRARY_PATH;
   tv[i].tv_u.tv_set_extra_library_path = set_extra_library_path;
 
+   ++i;
+  tv[i].tv_tag = LDPT_GET_OBJECT_HANDLE;
+  tv[i].tv_u.tv_get_object_handle = get_object_handle;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_COUNT;
+  tv[i].tv_u.tv_get_section_count = get_section_count;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_TYPE;
+  tv[i].tv_u.tv_get_section_type = get_section_type;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_NAME;
+  tv[i].tv_u.tv_get_section_name = get_section_name;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_CONTENTS;
+  tv[i].tv_u.tv_get_section_contents = get_section_contents;
+
+  ++i;
+  tv[i].tv_tag = LDPT_READ_LAYOUT_FROM_FILE;
+  tv[i].tv_u.tv_read_layout_from_file = read_layout_from_file;
+
+  ++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;
@@ -319,8 +372,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_)
@@ -404,7 +458,7 @@ Plugin_manager::all_symbols_read(Workque
   this->task_ = task;
   this->input_objects_ = input_objects;
   this->symtab_ = symtab;
-  this->layout_ = layout;
+  gold_assert (this->layout_ == layout);
   this->dirpath_ = dirpath;
   this->mapfile_ = mapfile;
   this->this_blocker_ = NULL;
@@ -1317,6 +1371,146 @@ message(int level, const char* format, .
   return LDPS_OK;
 }
 
+// Find the object having the given name.
+// Parameters :
+// FILENAME : The name of the object whose handle needs to be
+//            retrieved.
+// HANDLE   : Storage for the retrieved handle.
+
+static enum ld_plugin_status
+get_object_handle(const char* filename, void** handle)
+{
+  gold_assert(parameters->options().has_plugins());
+  Input_objects* input_objects =
+    parameters->options().plugins()->input_objects();
+  *handle = NULL;
+  if (input_objects == NULL)
+    {
+      return LDPS_ERR;
+    }
+
+  for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
+       p != input_objects->relobj_end();
+       ++p)
+    {
+      if (strcmp((*p)->name().c_str(), filename) == 0)
+        {
+          *handle = static_cast<void*>(*p);
+          break;
+        }
+    }
+
+  if (*handle == NULL)
+    return LDPS_ERR;
+  return LDPS_OK;
+}
+
+// Get the section count of the object corresponding to the handle.
+// Parameters :
+// HANDLE : This is the Relobj pointer.  This can be obtained using
+//          "get_object_handle".
+// COUNT  : Storage for the retrieved section count.
+
+static enum ld_plugin_status
+get_section_count(void* handle, unsigned int* count)
+{
+  gold_assert(parameters->options().has_plugins()
+              && handle != NULL);
+  Relobj* p = static_cast<Relobj*>(handle);
+  *count = p->shnum();
+  return LDPS_OK;
+}
+
+// Get the type of the specified section in the object corresponding
+// to the handle.
+// Parameters :
+// HANDLE : This is the Relobj pointer.  This can be obtained using
+//          "get_object_handle".
+// SHNDX  : Index of the section in the object.
+// TYPE   : Storage for the section type.
+
+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx, unsigned int* type)
+{
+  gold_assert(parameters->options().has_plugins()
+              && handle != NULL);
+  Relobj* p = static_cast<Relobj*>(handle);
+  *type = p->section_type(shndx);
+  return LDPS_OK;
+}
+
+// Get the name of the specified section in the object corresponding
+// to the handle.
+// Parameters :
+// HANDLE           : This is the Relobj pointer.  This can be obtained using
+//                    "get_object_handle".
+// SHNDX            : Index of the section in the object.
+// SECTION_NAME_PTR : Storage for the section name.
+
+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)
+{
+  gold_assert(parameters->options().has_plugins()
+              && handle != NULL);
+  Relobj* p = static_cast<Relobj*>(handle);
+  const char* section_name = p->section_name(shndx).c_str();
+  *section_name_ptr = (char*)malloc(strlen(section_name) + 1);
+  strcpy(*section_name_ptr, section_name);
+  return LDPS_OK;
+}
+
+// Get the contents of the specified section in the object corresponding
+// to the handle.
+// Parameters :
+// HANDLE               : This is the Relobj pointer. This can be obtained
+//                        using "get_object_handle".
+// SHNDX                : Index of the section in the object.
+// SECTION_CONTENTS_PTR : Storage for the section contents.
+// LEN                  : Storage for the section length.
+
+static enum ld_plugin_status
+get_section_contents(void* handle, unsigned int shndx,
+                     unsigned char** section_contents_ptr,
+		     unsigned int* len)
+{
+  gold_assert(parameters->options().has_plugins()
+              && handle != NULL);
+  Relobj* p = static_cast<Relobj*>(handle);
+  section_size_type plen;
+  const unsigned char* section_contents = p->section_contents(shndx, &plen,
+                                                              false);
+  *section_contents_ptr = (unsigned char*)malloc(plen);
+  memcpy(*section_contents_ptr, section_contents, plen);
+  *len = plen;
+  return LDPS_OK;
+}
+
+// Specify the ordering of sections in the final layout in a file. This
+// does what the linker option --section-ordering-file does.
+// Parameters :
+// FILENAME             : The file specifying the order of sections.
+
+static enum ld_plugin_status
+read_layout_from_file(const char* filename)
+{
+  gold_assert(parameters->options().has_plugins());
+  Layout* layout = parameters->options().plugins()->layout();
+  layout->read_layout_from_file(filename);
+  layout->update_layout_of_sections();
+  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->section_ordering_specified();
+  return LDPS_OK;
+}
+
 #endif // ENABLE_PLUGINS
 
 // Allocate a Pluginobj object of the appropriate size and endianness.
Index: plugin.h
===================================================================
RCS file: /cvs/src/src/gold/plugin.h,v
retrieving revision 1.16
diff -u -u -p -r1.16 plugin.h
--- plugin.h	24 Jan 2011 21:48:40 -0000	1.16
+++ plugin.h	3 Mar 2011 22:29:00 -0000
@@ -153,7 +153,7 @@ 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*
@@ -262,6 +262,14 @@ class Plugin_manager
   in_replacement_phase() const
   { return this->in_replacement_phase_; }
 
+  Input_objects*
+  input_objects() const
+  { return input_objects_; }
+
+  Layout*
+  layout()
+  { return layout_; }
+
  private:
   Plugin_manager(const Plugin_manager&);
   Plugin_manager& operator=(const Plugin_manager&);
Index: 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
--- testsuite/plugin_test.c	9 Nov 2009 16:11:34 -0000	1.4
+++ testsuite/plugin_test.c	3 Mar 2011 22:29:00 -0000
@@ -60,6 +60,13 @@ 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_object_handle get_object_handle = NULL;
+static ld_plugin_get_section_count get_section_count = NULL;
+static ld_plugin_get_section_type get_section_type = NULL;
+static ld_plugin_get_section_name get_section_name = NULL;
+static ld_plugin_get_section_contents get_section_contents = NULL;
+static ld_plugin_read_layout_from_file read_layout_from_file = NULL;
+static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
 
 #define MAXOPTS 10
 
@@ -126,6 +133,27 @@ 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_OBJECT_HANDLE:
+          get_object_handle = *entry->tv_u.tv_get_object_handle;
+          break;
+        case LDPT_GET_SECTION_COUNT:
+          get_section_count = *entry->tv_u.tv_get_section_count;
+          break;
+        case LDPT_GET_SECTION_TYPE:
+          get_section_type = *entry->tv_u.tv_get_section_type;
+          break;
+        case LDPT_GET_SECTION_NAME:
+          get_section_name = *entry->tv_u.tv_get_section_name;
+          break;
+        case LDPT_GET_SECTION_CONTENTS:
+          get_section_contents = *entry->tv_u.tv_get_section_contents;
+          break;
+	case LDPT_READ_LAYOUT_FROM_FILE:
+	  read_layout_from_file = *entry->tv_u.tv_read_layout_from_file;
+	  break;
+	case LDPT_ALLOW_SECTION_ORDERING:
+	  allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
+	  break;
         default:
           break;
         }
@@ -179,6 +207,48 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if (get_object_handle == NULL)
+    {
+      fprintf(stderr, "tv_get_object_handle interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_count == NULL)
+    {
+      fprintf(stderr, "tv_get_section_count interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_type == NULL)
+    {
+      fprintf(stderr, "tv_get_section_type interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_name == NULL)
+    {
+      fprintf(stderr, "tv_get_section_name interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_contents == NULL)
+    {
+      fprintf(stderr, "tv_get_section_contents interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (read_layout_from_file == NULL)
+    {
+      fprintf(stderr, "tv_read_layout_from_file 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;
 }
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-03 23:58 Plugin interfaces to do Pettis Hansen style code layout in the gold linker Sriraman Tallam
@ 2011-03-10  0:45 ` Cary Coutant
  2011-03-13  2:37   ` Sriraman Tallam
  0 siblings, 1 reply; 19+ messages in thread
From: Cary Coutant @ 2011-03-10  0:45 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: binutils, Ian Lance Taylor

Here are my comments on your patch. Thanks for working on this -- I
think it's going to be valuable.

-cary



Index: plugin-api.h
===================================================================

You'll need a separate ChangeLog entry for include/. Also, we use
C-style coding conventions in include/plugin-api.h. In particular,
"char* filename" should be "char *filename", etc.

+/* The linker's interface for retrieving the handle (pointer) to an object. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_object_handle) (const char* filename, void** handle);

I'm curious how this interface is going to be used. Where does the
plugin obtain a filename where it doesn't already have a handle? Are
you going to claim the files, or merely observe them and pass them
through unclaimed? If this is the case, why not just keep a list of
the handles in your plugin, and arrange for the handles to remain
valid even for unclaimed files (in the current plugin architecture,
the handle is just an index into the list of claimed files)?

+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
+                               char** section_name_ptr);
+/* The linker's interface for retrieving the contents of a specific section
+   in an object.  */

Missing blank line before this comment.

+/* The linker's interface for specifying the desired order of sections
+   through a file.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_read_layout_from_file) (const char* filename);
+
+/* The linker's interface for specifying that reordering of sections is
+   desired.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_allow_section_ordering) (void);

Why do we need both of these interfaces? Couldn't
read_layout_from_file imply allow_section_ordering?

Index: layout.cc
===================================================================
+    relaxation_debug_check_(NULL),
+    section_ordering_specified_(false),
+    input_section_position_(),
+    input_section_glob_()
+

Extra blank line here.

+      if ((*p) == NULL)
+        continue;
+      (*p)->update_section_layout(this);

This could just be:

+      if ((*p) != NULL)
+        (*p)->update_section_layout(this);

Index: layout.h
===================================================================

+  bool
+  is_section_ordering_specified()
+  { return section_ordering_specified_; }
+
+  void
+  section_ordering_specified()
+  { section_ordering_specified_ = true; }
+
+

Extra blank line here.

   unsigned int
   find_section_order_index(const std::string&);

+   void
+  read_layout_from_file(const char* filename);
+
   void
+  update_layout_of_sections();

These functions should all have comments.

+  bool section_ordering_specified_;

Need a comment here, too.

Index: main.cc
===================================================================

+  const char* section_ordering_file =
parameters->options().section_ordering_file();

Line too long.

Index: output.cc
===================================================================

+	  Object* obj = ((*p).is_input_section() ? (*p).relobj()
+		         : (*p).relaxed_input_section()->relobj());

I'd prefer to see this written like this:

+	  Object* obj = ((*p).is_input_section()
+			 ? (*p).relobj()
+			 : (*p).relaxed_input_section()->relobj());

+          std::string section_name = obj->section_name((*p).shndx());
+	  unsigned int section_order_index =
+            layout->find_section_order_index(std::string(section_name));

section_name is already a string here -- no conversion necessary.

Index: plugin.cc
===================================================================

@@ -404,7 +458,7 @@ Plugin_manager::all_symbols_read(Workque
-  this->layout_ = layout;
+  gold_assert (this->layout_ == layout);

Why not just drop layout from the parameter list for all_symbols_read?

+// Find the object having the given name.
+// Parameters :
+// FILENAME : The name of the object whose handle needs to be
+//            retrieved.
+// HANDLE   : Storage for the retrieved handle.

This comment formatting style doesn't match the rest of the file (or
anywhere else in gold, except for icf.cc). I don't need to see it
changed, though -- I'm not sure about Ian's preferences.

+  if (input_objects == NULL)
+    {
+      return LDPS_ERR;
+    }

Excessive use of braces?


+      if (strcmp((*p)->name().c_str(), filename) == 0)
+        {
+          *handle = static_cast<void*>(*p);
+          break;
+        }

You could just return LDPS_OK here, and return LDPS_ERR
unconditionally below the loop.

The handle returned here is very different from the handle returned by
the existing set of interfaces, and you don't seem to do anything to
tell them apart; this effectively makes it two separate and
non-interoperable APIs. There also isn't any way for the linker side
of the plugin interface to do a sanity check on the handle given it.
I'd suggest keeping the notion of handle as an index into a list of
objects, but extend that list to cover all objects rather than just
the claimed ones.

+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx, unsigned int* type)

+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)

It's looking like you intend for the plugin to iterate over the
sections one at a time, looking for a section by either type or name,
or both. Depending on how you intend to actually use this (and keeping
in mind generality for other potential uses), it might be better to
replace these two interfaces with a single one that can find a section
filtered by type, name, or both (with a provision for iterating
through multiple results).

Also note that the section_type() and section_name() object methods go
to a File_view, and you need a task lock in order to call them (else
you'll get a file descriptor leak). When during the link do you expect
these interfaces to be used? If it's only from the claim-file handler,
it should be OK, but if it's from the all-files-read handler, this is
going to re-open the files. There should be some check in place to
ensure it's called only when it's designed to be called.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-10  0:45 ` Cary Coutant
@ 2011-03-13  2:37   ` Sriraman Tallam
  2011-03-13  7:35     ` Dave Korn
  2011-03-14 18:22     ` Cary Coutant
  0 siblings, 2 replies; 19+ messages in thread
From: Sriraman Tallam @ 2011-03-13  2:37 UTC (permalink / raw)
  To: Cary Coutant; +Cc: binutils, Ian Lance Taylor

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

Hi Cary,


  Like we discussed, I made all the changes. I now have a separate
list of unclaimed objects in the Plugin manager and the handle will be
an index into it. I have also added a new hook called
"inspect_unclaimed_object". This handler allows the plugin to examine
the contents of an unclaimed object. Now, I have disallowed examining
claimed objects here as the methods to get their contents etc. are not
defined in Pluginobj. Also, I have kept the original interfaces to get
section count or type or contents. I think I would need this interface
for my work rather than only get contents based on filters. I guess
more interfaces can be added easily.

Thanks,
-Sri.


Change Log for plugin-api.h


	* plugin-api.h
	(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_read_layout_from_file): 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_READ_LAYOUT_FROM_FILE): 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_read_layout_from_file): New struct members.
	(tv_allow_section_ordering): New struct members.

ChangeLog for gold:


	* layout.cc (Layout::Layout): Initialize section_ordering_specified_,
	input_section_position_, and input_section_glob_.
	(Layout::update_layout_of_sections): New function.
	(read_layout_from_file): Add parameter filename and call function
	section_ordering_specified.
	* layout.h (is_section_ordering_specified): New function.
	(section_ordering_specified): New function.
	(read_layout_from_file): Add parameter filename.
	(update_layout_of_sections): New function.
	(section_ordering_specified_): New boolean member.
	* main.cc(main): Call load_plugins after layout object is defined.
	Call read_layout_from_file when section ordering is specified.
	* output.cc (Output_section::add_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.
	(read_layout_from_file): 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.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.
	(read_layout_from_file): New function pointer.
	(allow_section_ordering): New function pointer.
	(inspect_unclaimed_object_hook): New function.
	(onload): Check if the new interfaces exist.



On Wed, Mar 9, 2011 at 4:40 PM, Cary Coutant <ccoutant@google.com> wrote:
> Here are my comments on your patch. Thanks for working on this -- I
> think it's going to be valuable.
>
> -cary
>
>
>
> Index: plugin-api.h
> ===================================================================
>
> You'll need a separate ChangeLog entry for include/. Also, we use
> C-style coding conventions in include/plugin-api.h. In particular,
> "char* filename" should be "char *filename", etc.
>
> +/* The linker's interface for retrieving the handle (pointer) to an object. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_object_handle) (const char* filename, void** handle);
>
> I'm curious how this interface is going to be used. Where does the
> plugin obtain a filename where it doesn't already have a handle? Are
> you going to claim the files, or merely observe them and pass them
> through unclaimed? If this is the case, why not just keep a list of
> the handles in your plugin, and arrange for the handles to remain
> valid even for unclaimed files (in the current plugin architecture,
> the handle is just an index into the list of claimed files)?
>
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
> +                               char** section_name_ptr);
> +/* The linker's interface for retrieving the contents of a specific section
> +   in an object.  */
>
> Missing blank line before this comment.
>
> +/* The linker's interface for specifying the desired order of sections
> +   through a file.  */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_read_layout_from_file) (const char* filename);
> +
> +/* The linker's interface for specifying that reordering of sections is
> +   desired.  */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_allow_section_ordering) (void);
>
> Why do we need both of these interfaces? Couldn't
> read_layout_from_file imply allow_section_ordering?
>
> Index: layout.cc
> ===================================================================
> +    relaxation_debug_check_(NULL),
> +    section_ordering_specified_(false),
> +    input_section_position_(),
> +    input_section_glob_()
> +
>
> Extra blank line here.
>
> +      if ((*p) == NULL)
> +        continue;
> +      (*p)->update_section_layout(this);
>
> This could just be:
>
> +      if ((*p) != NULL)
> +        (*p)->update_section_layout(this);
>
> Index: layout.h
> ===================================================================
>
> +  bool
> +  is_section_ordering_specified()
> +  { return section_ordering_specified_; }
> +
> +  void
> +  section_ordering_specified()
> +  { section_ordering_specified_ = true; }
> +
> +
>
> Extra blank line here.
>
>   unsigned int
>   find_section_order_index(const std::string&);
>
> +   void
> +  read_layout_from_file(const char* filename);
> +
>   void
> +  update_layout_of_sections();
>
> These functions should all have comments.
>
> +  bool section_ordering_specified_;
>
> Need a comment here, too.
>
> Index: main.cc
> ===================================================================
>
> +  const char* section_ordering_file =
> parameters->options().section_ordering_file();
>
> Line too long.
>
> Index: output.cc
> ===================================================================
>
> +         Object* obj = ((*p).is_input_section() ? (*p).relobj()
> +                        : (*p).relaxed_input_section()->relobj());
>
> I'd prefer to see this written like this:
>
> +         Object* obj = ((*p).is_input_section()
> +                        ? (*p).relobj()
> +                        : (*p).relaxed_input_section()->relobj());
>
> +          std::string section_name = obj->section_name((*p).shndx());
> +         unsigned int section_order_index =
> +            layout->find_section_order_index(std::string(section_name));
>
> section_name is already a string here -- no conversion necessary.
>
> Index: plugin.cc
> ===================================================================
>
> @@ -404,7 +458,7 @@ Plugin_manager::all_symbols_read(Workque
> -  this->layout_ = layout;
> +  gold_assert (this->layout_ == layout);
>
> Why not just drop layout from the parameter list for all_symbols_read?
>
> +// Find the object having the given name.
> +// Parameters :
> +// FILENAME : The name of the object whose handle needs to be
> +//            retrieved.
> +// HANDLE   : Storage for the retrieved handle.
>
> This comment formatting style doesn't match the rest of the file (or
> anywhere else in gold, except for icf.cc). I don't need to see it
> changed, though -- I'm not sure about Ian's preferences.
>
> +  if (input_objects == NULL)
> +    {
> +      return LDPS_ERR;
> +    }
>
> Excessive use of braces?
>
>
> +      if (strcmp((*p)->name().c_str(), filename) == 0)
> +        {
> +          *handle = static_cast<void*>(*p);
> +          break;
> +        }
>
> You could just return LDPS_OK here, and return LDPS_ERR
> unconditionally below the loop.
>
> The handle returned here is very different from the handle returned by
> the existing set of interfaces, and you don't seem to do anything to
> tell them apart; this effectively makes it two separate and
> non-interoperable APIs. There also isn't any way for the linker side
> of the plugin interface to do a sanity check on the handle given it.
> I'd suggest keeping the notion of handle as an index into a list of
> objects, but extend that list to cover all objects rather than just
> the claimed ones.
>
> +static enum ld_plugin_status
> +get_section_type(void* handle, unsigned int shndx, unsigned int* type)
>
> +static enum ld_plugin_status
> +get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)
>
> It's looking like you intend for the plugin to iterate over the
> sections one at a time, looking for a section by either type or name,
> or both. Depending on how you intend to actually use this (and keeping
> in mind generality for other potential uses), it might be better to
> replace these two interfaces with a single one that can find a section
> filtered by type, name, or both (with a provision for iterating
> through multiple results).
>
> Also note that the section_type() and section_name() object methods go
> to a File_view, and you need a task lock in order to call them (else
> you'll get a file descriptor leak). When during the link do you expect
> these interfaces to be used? If it's only from the claim-file handler,
> it should be OK, but if it's from the all-files-read handler, this is
> going to re-open the files. There should be some check in place to
> ensure it's called only when it's designed to be called.
>

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

Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.190
diff -u -u -p -r1.190 layout.cc
--- layout.cc	10 Jan 2011 21:57:31 -0000	1.190
+++ layout.cc	13 Mar 2011 02:31:36 -0000
@@ -207,7 +207,10 @@ Layout::Layout(int number_of_input_files
     record_output_section_data_from_script_(false),
     script_output_section_data_list_(),
     segment_states_(NULL),
-    relaxation_debug_check_(NULL)
+    relaxation_debug_check_(NULL),
+    section_ordering_specified_(false),
+    input_section_position_(),
+    input_section_glob_()
 {
   // Make space for more than enough segments for a typical file.
   // This is just for efficiency--it's OK if we wind up needing more.
@@ -1817,13 +1820,28 @@ Layout::find_section_order_index(const s
   return 0;
 }
 
+// Updates the input section order of all output sections.  This
+// is called when the section order is specified via plugins.
+
+void
+Layout::update_layout_of_sections()
+{
+  for (Section_list::iterator p = this->section_list_.begin();
+       p != this->section_list_.end();
+       ++p)
+    {
+      if ((*p) == NULL)
+        continue;
+      (*p)->update_section_layout(this);
+    }
+}
+
 // Read the sequence of input sections from the file specified with
-// --section-ordering-file.
+// linker option --section-ordering-file.
 
 void
-Layout::read_layout_from_file()
+Layout::read_layout_from_file(const char* filename)
 {
-  const char* filename = parameters->options().section_ordering_file();
   std::ifstream in;
   std::string line;
 
@@ -1834,6 +1852,7 @@ Layout::read_layout_from_file()
 
   std::getline(in, line);   // this chops off the trailing \n, if any
   unsigned int position = 1;
+  this->section_ordering_specified();
 
   while (in)
     {
Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.88
diff -u -u -p -r1.88 layout.h
--- layout.h	14 Dec 2010 19:03:30 -0000	1.88
+++ layout.h	13 Mar 2011 02:31:36 -0000
@@ -414,11 +414,25 @@ 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 section_ordering_specified_; }
+
+  void
+  section_ordering_specified()
+  { section_ordering_specified_ = true; }
+
   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(const char* filename);
+
+  // Updates the order of input sections in the output sections.
   void
-  read_layout_from_file();
+  update_layout_of_sections();
 
   // Layout an input reloc section when doing a relocatable link.  The
   // section is RELOC_SHNDX in OBJECT, with data in SHDR.
@@ -1147,6 +1161,9 @@ class Layout
   Segment_states* segment_states_;
   // A relaxation debug checker.  We only create one when in debugging mode.
   Relaxation_debug_check* relaxation_debug_check_;
+  // True if the input sections in the output sections should be sorted
+  // as specified in a section ordering file.
+  bool section_ordering_specified_;
   // 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: main.cc
===================================================================
RCS file: /cvs/src/src/gold/main.cc,v
retrieving revision 1.42
diff -u -u -p -r1.42 main.cc
--- main.cc	14 Dec 2010 19:03:30 -0000	1.42
+++ main.cc	13 Mar 2011 02:31:36 -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());
 
@@ -231,8 +227,14 @@ main(int argc, char** argv)
   if (layout.incremental_inputs() != NULL)
     layout.incremental_inputs()->report_command_line(argc, 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);
+
+  const char* section_ordering_file
+    = parameters->options().section_ordering_file();
+  if (section_ordering_file)
+    layout.read_layout_from_file(section_ordering_file);
 
   // Get the search path from the -L options.
   Dirsearch search_path;
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.140
diff -u -u -p -r1.140 output.cc
--- output.cc	12 Feb 2011 03:19:24 -0000	1.140
+++ output.cc	13 Mar 2011 02:31:36 -0000
@@ -2165,10 +2165,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));
@@ -3041,6 +3041,34 @@ Output_section::Input_section_sort_secti
   return s1_secn_index < s2_secn_index;
 }
 
+// Updates the ordering of input sections in this output section.
+
+void
+Output_section::update_section_layout(Layout* layout)
+{
+  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());
+
+          std::string section_name = obj->section_name((*p).shndx());
+	  unsigned int section_order_index =
+            layout->find_section_order_index(section_name);
+	  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
@@ -3083,7 +3111,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: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.118
diff -u -u -p -r1.118 output.h
--- output.h	23 Dec 2010 19:56:14 -0000	1.118
+++ output.h	13 Mar 2011 02:31:36 -0000
@@ -2564,6 +2564,9 @@ class Output_section : public Output_dat
   flags() const
   { return this->flags_; }
 
+  void
+  update_section_layout(Layout* layout);
+
   // Update the output section flags based on input section flags.
   void
   update_flags_for_input_section(elfcpp::Elf_Xword flags);
Index: plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.43
diff -u -u -p -r1.43 plugin.cc
--- plugin.cc	8 Feb 2011 05:03:19 -0000	1.43
+++ plugin.cc	13 Mar 2011 02:31:36 -0000
@@ -57,6 +57,9 @@ static enum ld_plugin_status
 register_claim_file(ld_plugin_claim_file_handler handler);
 
 static enum ld_plugin_status
+register_inspect_unclaimed_object(ld_plugin_inspect_unclaimed_object_handler handler);
+
+static enum ld_plugin_status
 register_all_symbols_read(ld_plugin_all_symbols_read_handler handler);
 
 static enum ld_plugin_status
@@ -86,6 +89,28 @@ set_extra_library_path(const char *path)
 static enum ld_plugin_status
 message(int level, const char *format, ...);
 
+static enum ld_plugin_status
+get_section_count(const void* handle, unsigned int* count);
+
+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx,
+                 unsigned int* type);
+
+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx,
+                 char** section_name_ptr);
+
+static enum ld_plugin_status
+get_section_contents(void* handle, unsigned int shndx,
+                     unsigned char** section_contents,
+		     unsigned int* len);
+
+static enum ld_plugin_status
+read_layout_from_file(const char* filename);
+
+static enum ld_plugin_status
+allow_section_ordering();
+
 };
 
 #endif // ENABLE_PLUGINS
@@ -130,7 +155,7 @@ Plugin::load()
   sscanf(ver, "%d.%d", &major, &minor);
 
   // Allocate and populate a transfer vector.
-  const int tv_fixed_size = 16;
+  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];
 
@@ -173,6 +198,11 @@ Plugin::load()
   tv[i].tv_u.tv_register_claim_file = register_claim_file;
 
   ++i;
+  tv[i].tv_tag = LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK;
+  tv[i].tv_u.tv_register_inspect_unclaimed_object
+    = register_inspect_unclaimed_object;
+
+  ++i;
   tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK;
   tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read;
 
@@ -209,6 +239,30 @@ Plugin::load()
   tv[i].tv_u.tv_set_extra_library_path = set_extra_library_path;
 
   ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_COUNT;
+  tv[i].tv_u.tv_get_section_count = get_section_count;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_TYPE;
+  tv[i].tv_u.tv_get_section_type = get_section_type;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_NAME;
+  tv[i].tv_u.tv_get_section_name = get_section_name;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_CONTENTS;
+  tv[i].tv_u.tv_get_section_contents = get_section_contents;
+
+  ++i;
+  tv[i].tv_tag = LDPT_READ_LAYOUT_FROM_FILE;
+  tv[i].tv_u.tv_read_layout_from_file = read_layout_from_file;
+
+  ++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;
 
@@ -237,6 +291,16 @@ Plugin::claim_file(struct ld_plugin_inpu
   return false;
 }
 
+// Call the plugin inspect_unclaimed_object handler.
+
+inline void
+Plugin::inspect_unclaimed_object(unsigned int index)
+{
+  void* handle =  reinterpret_cast<void*>(index);
+  if (this->inspect_unclaimed_object_handler_ != NULL)
+      (*this->inspect_unclaimed_object_handler_)(handle);
+}
+
 // Call the all-symbols-read handler.
 
 inline void
@@ -319,8 +383,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_)
@@ -365,6 +430,27 @@ Plugin_manager::claim_file(Input_file* i
   return NULL;
 }
 
+// Call the plugin inspect_unclaimed_object handlers to allow them to inspect
+// the unclaimed object. Pass the handle of the object which is the index
+// into the vector containing the unclaimed objects.
+
+void
+Plugin_manager::inspect_unclaimed_object(Object* obj)
+{
+  unsigned int index;
+  index = this->unclaimed_objects_.size();
+  this->unclaimed_objects_.push_back(obj);
+
+  this->in_inspect_unclaimed_object_handler_ = true;
+
+  for (this->current_ = this->plugins_.begin();
+       this->current_ != this->plugins_.end();
+       ++this->current_)
+    (*this->current_)->inspect_unclaimed_object(index);
+
+  this->in_inspect_unclaimed_object_handler_ = false;
+}
+
 // Save an archive.  This is used so that a plugin can add a file
 // which refers to a symbol which was not previously referenced.  In
 // that case we want to pretend that the symbol was referenced before,
@@ -395,7 +481,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)
 {
@@ -404,7 +490,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;
@@ -635,6 +720,20 @@ Plugin_manager::release_input_file(unsig
   return LDPS_OK;
 }
 
+// Get the object from the list of unclaimed objects with
+// index specified in handle.
+
+Object*
+Plugin_manager::get_unclaimed_object(const void* handle)
+{
+  unsigned int index =  static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle));
+  Object* obj = NULL;
+
+  obj = parameters->options().plugins()->unclaimed_object(index);
+
+  return obj;
+}
+
 // Add a new library path.
 
 ld_plugin_status
@@ -1168,7 +1267,6 @@ Plugin_hook::run(Workqueue* workqueue)
                                              this,
                                              this->input_objects_,
                                              this->symtab_,
-                                             this->layout_,
                                              this->dirpath_,
                                              this->mapfile_,
                                              &this->this_blocker_);
@@ -1190,6 +1288,18 @@ register_claim_file(ld_plugin_claim_file
   return LDPS_OK;
 }
 
+//Register a inspect_unclaimed_object handler.
+
+static enum ld_plugin_status
+register_inspect_unclaimed_object
+  (ld_plugin_inspect_unclaimed_object_handler handler)
+{
+  gold_assert(parameters->options().has_plugins());
+  parameters->options().plugins()->set_inspect_unclaimed_object_handler(
+    handler);
+  return LDPS_OK;
+}
+
 // Register an all-symbols-read handler.
 
 static enum ld_plugin_status
@@ -1317,6 +1427,123 @@ 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 inspect_unclaimed_object
+// handler of the plugin.
+
+static enum ld_plugin_status
+get_section_count(const void* handle, unsigned int* count)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  *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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx, unsigned int* type)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  *type = obj->section_type(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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  const char* section_name = obj->section_name(shndx).c_str();
+  *section_name_ptr = (char*)malloc(strlen(section_name) + 1);
+  strcpy(*section_name_ptr, section_name);
+  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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_contents(void* handle, unsigned int shndx,
+                     unsigned char** section_contents_ptr,
+		     unsigned int* len)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  section_size_type plen;
+  const unsigned char* section_contents = obj->section_contents(shndx, &plen,
+                                                              false);
+  *section_contents_ptr = (unsigned char*)malloc(plen);
+  memcpy(*section_contents_ptr, section_contents, plen);
+  *len = plen;
+  return LDPS_OK;
+}
+
+// Specify the ordering of sections in the final layout in a file. This
+// does what the linker option --section-ordering-file does.
+
+static enum ld_plugin_status
+read_layout_from_file(const char* filename)
+{
+  gold_assert(parameters->options().has_plugins());
+  Layout* layout = parameters->options().plugins()->layout();
+  layout->read_layout_from_file(filename);
+  layout->update_layout_of_sections();
+  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->section_ordering_specified();
+  return LDPS_OK;
+}
+
 #endif // ENABLE_PLUGINS
 
 // Allocate a Pluginobj object of the appropriate size and endianness.
Index: plugin.h
===================================================================
RCS file: /cvs/src/src/gold/plugin.h,v
retrieving revision 1.16
diff -u -u -p -r1.16 plugin.h
--- plugin.h	24 Jan 2011 21:48:40 -0000	1.16
+++ plugin.h	13 Mar 2011 02:31:36 -0000
@@ -58,6 +58,7 @@ class Plugin
       filename_(filename),
       args_(),
       claim_file_handler_(NULL),
+      inspect_unclaimed_object_handler_(NULL),
       all_symbols_read_handler_(NULL),
       cleanup_handler_(NULL),
       cleanup_done_(false)
@@ -74,6 +75,10 @@ class Plugin
   bool
   claim_file(struct ld_plugin_input_file* plugin_input_file);
 
+  // Call the inspect_unclaimed_object handler.
+  void
+  inspect_unclaimed_object(unsigned int index);
+
   // Call the all-symbols-read handler.
   void
   all_symbols_read();
@@ -87,6 +92,12 @@ class Plugin
   set_claim_file_handler(ld_plugin_claim_file_handler handler)
   { this->claim_file_handler_ = handler; }
 
+  // Register a inspect_unclaimed_object handler.
+  void
+  set_inspect_unclaimed_object_handler
+    (ld_plugin_inspect_unclaimed_object_handler handler)
+  { this->inspect_unclaimed_object_handler_ = handler; }
+
   // Register an all-symbols-read handler.
   void
   set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
@@ -116,6 +127,7 @@ class Plugin
   std::vector<std::string> args_;
   // The plugin's event handlers.
   ld_plugin_claim_file_handler claim_file_handler_;
+  ld_plugin_inspect_unclaimed_object_handler inspect_unclaimed_object_handler_;
   ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
   ld_plugin_cleanup_handler cleanup_handler_;
   // TRUE if the cleanup handlers have been called.
@@ -128,9 +140,11 @@ class Plugin_manager
 {
  public:
   Plugin_manager(const General_options& options)
-    : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
+    : plugins_(), objects_(), unclaimed_objects_(),
+      deferred_layout_objects_(), input_file_(NULL),
       plugin_input_file_(), rescannable_(), undefined_symbols_(),
       any_claimed_(false), in_replacement_phase_(false), any_added_(false),
+      in_inspect_unclaimed_object_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,12 +167,26 @@ 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);
 
+  // Call the plugin inspect_unclaimed_object handlers to allow them
+  // to inspect the file.
+  void
+  inspect_unclaimed_object(Object* obj);
+
+  Object*
+  get_unclaimed_object(const void* handle);
+
+  // True if the inspect_unclaimed_object handler of the plugins are being
+  // called.
+  bool
+  in_inspect_unclaimed_object_handler()
+  { return in_inspect_unclaimed_object_handler_; }
+
   // Let the plugin manager save an archive for later rescanning.
   // This takes ownership of the Archive pointer.
   void
@@ -173,7 +201,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
@@ -197,6 +225,15 @@ class Plugin_manager
     (*this->current_)->set_claim_file_handler(handler);
   }
 
+  // Register a inspect_unclaimed_object handler.
+  void
+  set_inspect_unclaimed_object_handler
+    (ld_plugin_inspect_unclaimed_object_handler handler)
+  {
+    gold_assert(this->current_ != plugins_.end());
+    (*this->current_)->set_inspect_unclaimed_object_handler(handler);
+  }
+
   // Register an all-symbols-read handler.
   void
   set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
@@ -227,6 +264,15 @@ class Plugin_manager
     return this->objects_[handle];
   }
 
+  // Return the unclaimed object associated with the given HANDLE.
+  Object*
+  unclaimed_object(unsigned int handle) const
+  {
+    if (handle >= this->unclaimed_objects_.size())
+      return NULL;
+    return this->unclaimed_objects_[handle];
+  }
+
   // Return TRUE if any input files have been claimed by a plugin
   // and we are still in the initial input phase.
   bool
@@ -262,6 +308,14 @@ class Plugin_manager
   in_replacement_phase() const
   { return this->in_replacement_phase_; }
 
+  Input_objects*
+  input_objects() const
+  { return input_objects_; }
+
+  Layout*
+  layout()
+  { return layout_; }
+
  private:
   Plugin_manager(const Plugin_manager&);
   Plugin_manager& operator=(const Plugin_manager&);
@@ -291,6 +345,7 @@ class Plugin_manager
 
   typedef std::list<Plugin*> Plugin_list;
   typedef std::vector<Pluginobj*> Object_list;
+  typedef std::vector<Object*> Unclaimed_object_list;
   typedef std::vector<Relobj*> Deferred_layout_list;
   typedef std::vector<Rescannable> Rescannable_list;
   typedef std::vector<Symbol*> Undefined_symbol_list;
@@ -312,6 +367,12 @@ class Plugin_manager
   // serves as the "handle" that we pass to the plugins.
   Object_list objects_;
 
+  // The list of unclaimed objects.  The negative of the index of an
+  // in this list serves as the "handle" that we pass to the plugins.
+  // Postive integer values for "handle" are for the claimed objects
+  // and negative values are for the unclaimed objects.
+  Unclaimed_object_list unclaimed_objects_;
+
   // The list of regular objects whose layout has been deferred.
   Deferred_layout_list deferred_layout_objects_;
 
@@ -337,6 +398,10 @@ class Plugin_manager
   // Whether any input files or libraries were added by a plugin.
   bool any_added_;
 
+  // Set to true when the inspect_unclaimed_object_handler of the plugins are being
+  // called.
+  bool in_inspect_unclaimed_object_handler_;
+
   const General_options& options_;
   Workqueue* workqueue_;
   Task* task_;
Index: readsyms.cc
===================================================================
RCS file: /cvs/src/src/gold/readsyms.cc,v
retrieving revision 1.47
diff -u -u -p -r1.47 readsyms.cc
--- readsyms.cc	24 Jan 2011 21:48:40 -0000	1.47
+++ readsyms.cc	13 Mar 2011 02:31:36 -0000
@@ -380,6 +380,10 @@ Read_symbols::do_read_symbols(Workqueue*
 	  return false;
 	}
 
+      // Allow the plugins to inspect the unclaimed object now.
+      if (parameters->options().has_plugins())
+        parameters->options().plugins()->inspect_unclaimed_object(obj);
+
       Read_symbols_data* sd = new Read_symbols_data;
       obj->read_symbols(sd);
 
cvs diff: Diffing po
cvs diff: Diffing testsuite
Index: 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
--- testsuite/plugin_test.c	9 Nov 2009 16:11:34 -0000	1.4
+++ testsuite/plugin_test.c	13 Mar 2011 02:31:37 -0000
@@ -52,6 +52,8 @@ static struct claimed_file* first_claime
 static struct claimed_file* last_claimed_file = NULL;
 
 static ld_plugin_register_claim_file register_claim_file_hook = NULL;
+static ld_plugin_register_inspect_unclaimed_object
+  register_inspect_unclaimed_object_hook = NULL;
 static ld_plugin_register_all_symbols_read register_all_symbols_read_hook = NULL;
 static ld_plugin_register_cleanup register_cleanup_hook = NULL;
 static ld_plugin_add_symbols add_symbols = NULL;
@@ -60,6 +62,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_section_count get_section_count = NULL;
+static ld_plugin_get_section_type get_section_type = NULL;
+static ld_plugin_get_section_name get_section_name = NULL;
+static ld_plugin_get_section_contents get_section_contents = NULL;
+static ld_plugin_read_layout_from_file read_layout_from_file = NULL;
+static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
 
 #define MAXOPTS 10
 
@@ -69,6 +77,7 @@ static int nopts = 0;
 enum ld_plugin_status onload(struct ld_plugin_tv *tv);
 enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
                                       int *claimed);
+enum ld_plugin_status inspect_unclaimed_object_hook(void* handle);
 enum ld_plugin_status all_symbols_read_hook(void);
 enum ld_plugin_status cleanup_hook(void);
 
@@ -101,6 +110,10 @@ onload(struct ld_plugin_tv *tv)
         case LDPT_REGISTER_CLAIM_FILE_HOOK:
           register_claim_file_hook = entry->tv_u.tv_register_claim_file;
           break;
+	case LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK:
+          register_inspect_unclaimed_object_hook
+            = entry->tv_u.tv_register_inspect_unclaimed_object;
+          break;
         case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
           register_all_symbols_read_hook =
             entry->tv_u.tv_register_all_symbols_read;
@@ -126,6 +139,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_SECTION_COUNT:
+          get_section_count = *entry->tv_u.tv_get_section_count;
+          break;
+        case LDPT_GET_SECTION_TYPE:
+          get_section_type = *entry->tv_u.tv_get_section_type;
+          break;
+        case LDPT_GET_SECTION_NAME:
+          get_section_name = *entry->tv_u.tv_get_section_name;
+          break;
+        case LDPT_GET_SECTION_CONTENTS:
+          get_section_contents = *entry->tv_u.tv_get_section_contents;
+          break;
+	case LDPT_READ_LAYOUT_FROM_FILE:
+	  read_layout_from_file = *entry->tv_u.tv_read_layout_from_file;
+	  break;
+	case LDPT_ALLOW_SECTION_ORDERING:
+	  allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
+	  break;
         default:
           break;
         }
@@ -143,6 +174,13 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if (register_inspect_unclaimed_object_hook == NULL)
+    {
+      fprintf(stderr,
+              "tv_register_inspect_unclaimed_object_hook interface missing\n");
+      return LDPS_ERR;
+    }
+
   if (register_all_symbols_read_hook == NULL)
     {
       fprintf(stderr, "tv_register_all_symbols_read_hook interface missing\n");
@@ -167,6 +205,14 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if ((*register_inspect_unclaimed_object_hook)
+        (inspect_unclaimed_object_hook) != LDPS_OK)
+    {
+      (*message)(LDPL_ERROR,
+                 "error registering inspect unclaimed object hook");
+      return LDPS_ERR;
+    }
+
   if ((*register_all_symbols_read_hook)(all_symbols_read_hook) != LDPS_OK)
     {
       (*message)(LDPL_ERROR, "error registering all symbols read hook");
@@ -179,10 +225,53 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if (get_section_count == NULL)
+    {
+      fprintf(stderr, "tv_get_section_count interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_type == NULL)
+    {
+      fprintf(stderr, "tv_get_section_type interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_name == NULL)
+    {
+      fprintf(stderr, "tv_get_section_name interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_contents == NULL)
+    {
+      fprintf(stderr, "tv_get_section_contents interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (read_layout_from_file == NULL)
+    {
+      fprintf(stderr, "tv_read_layout_from_file 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;
 }
 
 enum ld_plugin_status
+inspect_unclaimed_object_hook (void* handle)
+{
+  (*message)(LDPL_INFO, "Inspect unclaimed object hook called with handle: %p",
+             handle);
+  return LDPS_OK;
+}
+enum ld_plugin_status
 claim_file_hook (const struct ld_plugin_input_file* file, int* claimed)
 {
   int len;
Index: plugin-api.h
===================================================================
RCS file: /cvs/src/src/include/plugin-api.h,v
retrieving revision 1.13
diff -u -u -p -r1.13 plugin-api.h
--- plugin-api.h	3 Jan 2011 21:05:50 -0000	1.13
+++ plugin-api.h	13 Mar 2011 02:24:32 -0000
@@ -157,6 +157,12 @@ enum ld_plugin_status
 (*ld_plugin_claim_file_handler) (
   const struct ld_plugin_input_file *file, int *claimed);
 
+/* The plugin library's "observe file" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_inspect_unclaimed_object_handler) (void *);
+
 /* The plugin library's "all symbols read" handler.  */
 
 typedef
@@ -175,6 +181,13 @@ typedef
 enum ld_plugin_status
 (*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler);
 
+/* The linker's interface for registering the "observe file" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_inspect_unclaimed_object)
+  (ld_plugin_inspect_unclaimed_object_handler handler);
+
 /* The linker's interface for registering the "all symbols read" handler.  */
 
 typedef
@@ -240,6 +253,59 @@ 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 inspect_unclaimed_object_handler.  This
+   interface should only be invoked in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_count) (const void* handle, unsigned int* count);
+
+/* The linker's interface for retrieving the section type of a specific
+   section in an object.  The handle is obtained in the
+   inspect_unclaimed_object_handler.  This interface should only be
+   invoked in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_type) (void* handle, unsigned int shndx,
+                               unsigned int* type);
+
+/* The linker's interface for retrieving the name of specific section in
+   an object. The handle is obtained in the inspect_unclaimed_object_handler.
+   This interface should only be invoked in the
+   inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
+                               char** section_name_ptr);
+
+/* The linker's interface for retrieving the contents of a specific section
+   in an object.  The handle is obtained in the
+   inspect_unclaimed_object_handler.  This interface should only be invoked
+   in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_contents) (void* handle, unsigned int shndx,
+                                   unsigned char** section_contents,
+                                   unsigned int* len);
+
+/* The linker's interface for specifying the desired order of sections
+   through a file.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_read_layout_from_file) (const char* filename);
+
+/* The linker's interface for specifying that reordering of sections is
+   desired.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_allow_section_ordering) (void);
+
 enum ld_plugin_level
 {
   LDPL_INFO,
@@ -258,6 +324,7 @@ enum ld_plugin_tag
   LDPT_LINKER_OUTPUT,
   LDPT_OPTION,
   LDPT_REGISTER_CLAIM_FILE_HOOK,
+  LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK,
   LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
   LDPT_REGISTER_CLEANUP_HOOK,
   LDPT_ADD_SYMBOLS,
@@ -269,7 +336,13 @@ enum ld_plugin_tag
   LDPT_ADD_INPUT_LIBRARY,
   LDPT_OUTPUT_NAME,
   LDPT_SET_EXTRA_LIBRARY_PATH,
-  LDPT_GNU_LD_VERSION
+  LDPT_GNU_LD_VERSION,
+  LDPT_GET_SECTION_COUNT,
+  LDPT_GET_SECTION_TYPE,
+  LDPT_GET_SECTION_NAME,
+  LDPT_GET_SECTION_CONTENTS,
+  LDPT_READ_LAYOUT_FROM_FILE,
+  LDPT_ALLOW_SECTION_ORDERING
 };
 
 /* The plugin transfer vector.  */
@@ -282,6 +355,8 @@ struct ld_plugin_tv
     int tv_val;
     const char *tv_string;
     ld_plugin_register_claim_file tv_register_claim_file;
+    ld_plugin_register_inspect_unclaimed_object
+      tv_register_inspect_unclaimed_object;
     ld_plugin_register_all_symbols_read tv_register_all_symbols_read;
     ld_plugin_register_cleanup tv_register_cleanup;
     ld_plugin_add_symbols tv_add_symbols;
@@ -292,6 +367,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_section_count tv_get_section_count;
+    ld_plugin_get_section_type tv_get_section_type;
+    ld_plugin_get_section_name tv_get_section_name;
+    ld_plugin_get_section_contents tv_get_section_contents;
+    ld_plugin_read_layout_from_file tv_read_layout_from_file;
+    ld_plugin_allow_section_ordering tv_allow_section_ordering;
   } tv_u;
 };
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-13  2:37   ` Sriraman Tallam
@ 2011-03-13  7:35     ` Dave Korn
  2011-03-14  3:40       ` Sriraman Tallam
  2011-03-14 18:22     ` Cary Coutant
  1 sibling, 1 reply; 19+ messages in thread
From: Dave Korn @ 2011-03-13  7:35 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: Cary Coutant, binutils, Ian Lance Taylor

On 13/03/2011 02:37, Sriraman Tallam wrote:
> Hi Cary,
> 
> 
>   Like we discussed, I made all the changes. I now have a separate
> list of unclaimed objects in the Plugin manager and the handle will be
> an index into it. I have also added a new hook called
> "inspect_unclaimed_object". This handler allows the plugin to examine
> the contents of an unclaimed object. Now, I have disallowed examining
> claimed objects here as the methods to get their contents etc. are not
> defined in Pluginobj. Also, I have kept the original interfaces to get
> section count or type or contents. I think I would need this interface
> for my work rather than only get contents based on filters. I guess
> more interfaces can be added easily.

  This new functionality lacks a spec.  Can you add an update to
http://gcc.gnu.org/wiki/whopr/driver to explain the new callbacks please?

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-13  7:35     ` Dave Korn
@ 2011-03-14  3:40       ` Sriraman Tallam
  0 siblings, 0 replies; 19+ messages in thread
From: Sriraman Tallam @ 2011-03-14  3:40 UTC (permalink / raw)
  To: Dave Korn; +Cc: Cary Coutant, binutils, Ian Lance Taylor

On Sat, Mar 12, 2011 at 9:37 PM, Dave Korn <dave.korn.cygwin@gmail.com> wrote:
> On 13/03/2011 02:37, Sriraman Tallam wrote:
>> Hi Cary,
>>
>>
>>   Like we discussed, I made all the changes. I now have a separate
>> list of unclaimed objects in the Plugin manager and the handle will be
>> an index into it. I have also added a new hook called
>> "inspect_unclaimed_object". This handler allows the plugin to examine
>> the contents of an unclaimed object. Now, I have disallowed examining
>> claimed objects here as the methods to get their contents etc. are not
>> defined in Pluginobj. Also, I have kept the original interfaces to get
>> section count or type or contents. I think I would need this interface
>> for my work rather than only get contents based on filters. I guess
>> more interfaces can be added easily.
>
>  This new functionality lacks a spec.  Can you add an update to
> http://gcc.gnu.org/wiki/whopr/driver to explain the new callbacks please?

Yes, will do immediately after I submit my patch.

Thanks,
-Sriraman.


>
>    cheers,
>      DaveK
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-13  2:37   ` Sriraman Tallam
  2011-03-13  7:35     ` Dave Korn
@ 2011-03-14 18:22     ` Cary Coutant
  2011-03-14 18:45       ` Sriraman Tallam
  1 sibling, 1 reply; 19+ messages in thread
From: Cary Coutant @ 2011-03-14 18:22 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: binutils, Ian Lance Taylor

>  Like we discussed, I made all the changes. I now have a separate
> list of unclaimed objects in the Plugin manager and the handle will be
> an index into it. I have also added a new hook called
> "inspect_unclaimed_object". This handler allows the plugin to examine
> the contents of an unclaimed object. Now, I have disallowed examining
> claimed objects here as the methods to get their contents etc. are not
> defined in Pluginobj. Also, I have kept the original interfaces to get
> section count or type or contents. I think I would need this interface
> for my work rather than only get contents based on filters. I guess
> more interfaces can be added easily.

Index: main.cc
===================================================================
+  const char* section_ordering_file
+    = parameters->options().section_ordering_file();

We usually indent continuations like this by 4 spaces.


Index: plugin.cc
===================================================================
+register_inspect_unclaimed_object(ld_plugin_inspect_unclaimed_object_handler
handler);

Line too long.

+Plugin_manager::get_unclaimed_object(const void* handle)
+{
+  unsigned int index =  static_cast<unsigned
int>(reinterpret_cast<intptr_t>(handle));

Line too long.


+static enum ld_plugin_status
+register_inspect_unclaimed_object
+  (ld_plugin_inspect_unclaimed_object_handler handler)
+{
+  gold_assert(parameters->options().has_plugins());
+  parameters->options().plugins()->set_inspect_unclaimed_object_handler(
+    handler);

Also indent here by 4 spaces.

+  const unsigned char* section_contents = obj->section_contents(shndx, &plen,
+                                                              false);

I think the indentation here is not quite correct.


Index: plugin.h
===================================================================
+  // Register a inspect_unclaimed_object handler.
+  void
+  set_inspect_unclaimed_object_handler
+    (ld_plugin_inspect_unclaimed_object_handler handler)

The left paren should be at the end of the line above, and the
continuation line indented 4 spaces.

+  // Register a inspect_unclaimed_object handler.
+  void
+  set_inspect_unclaimed_object_handler
+    (ld_plugin_inspect_unclaimed_object_handler handler)

Same here.

+  // The list of unclaimed objects.  The negative of the index of an
+  // in this list serves as the "handle" that we pass to the plugins.
+  // Postive integer values for "handle" are for the claimed objects
+  // and negative values are for the unclaimed objects.

It doesn't look like this is how you implemented it -- I think you're
returning straight non-negative indices in both cases. Also, remember
that 0 is used as a handle for the first claimed object, so it should
really be negative vs. "non-negative".

This looks good to me with these changes. (You need Ian's approval to
commit, though.)

Thanks!

-cary

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-14 18:22     ` Cary Coutant
@ 2011-03-14 18:45       ` Sriraman Tallam
  2011-03-15 14:44         ` Ian Lance Taylor
  0 siblings, 1 reply; 19+ messages in thread
From: Sriraman Tallam @ 2011-03-14 18:45 UTC (permalink / raw)
  To: Cary Coutant; +Cc: binutils, Ian Lance Taylor

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

Hi,

   I made all the changes. It is true that I always pass non-negative
values as handles. The comment was a left-over from a previous
implementation that I forgot to cleanup, sorry. I have attached the
new patch with all the changes made.

Thanks,
-Sri.

On Mon, Mar 14, 2011 at 11:22 AM, Cary Coutant <ccoutant@google.com> wrote:
>>  Like we discussed, I made all the changes. I now have a separate
>> list of unclaimed objects in the Plugin manager and the handle will be
>> an index into it. I have also added a new hook called
>> "inspect_unclaimed_object". This handler allows the plugin to examine
>> the contents of an unclaimed object. Now, I have disallowed examining
>> claimed objects here as the methods to get their contents etc. are not
>> defined in Pluginobj. Also, I have kept the original interfaces to get
>> section count or type or contents. I think I would need this interface
>> for my work rather than only get contents based on filters. I guess
>> more interfaces can be added easily.
>
> Index: main.cc
> ===================================================================
> +  const char* section_ordering_file
> +    = parameters->options().section_ordering_file();
>
> We usually indent continuations like this by 4 spaces.
>
>
> Index: plugin.cc
> ===================================================================
> +register_inspect_unclaimed_object(ld_plugin_inspect_unclaimed_object_handler
> handler);
>
> Line too long.
>
> +Plugin_manager::get_unclaimed_object(const void* handle)
> +{
> +  unsigned int index =  static_cast<unsigned
> int>(reinterpret_cast<intptr_t>(handle));
>
> Line too long.
>
>
> +static enum ld_plugin_status
> +register_inspect_unclaimed_object
> +  (ld_plugin_inspect_unclaimed_object_handler handler)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +  parameters->options().plugins()->set_inspect_unclaimed_object_handler(
> +    handler);
>
> Also indent here by 4 spaces.
>
> +  const unsigned char* section_contents = obj->section_contents(shndx, &plen,
> +                                                              false);
>
> I think the indentation here is not quite correct.
>
>
> Index: plugin.h
> ===================================================================
> +  // Register a inspect_unclaimed_object handler.
> +  void
> +  set_inspect_unclaimed_object_handler
> +    (ld_plugin_inspect_unclaimed_object_handler handler)
>
> The left paren should be at the end of the line above, and the
> continuation line indented 4 spaces.
>
> +  // Register a inspect_unclaimed_object handler.
> +  void
> +  set_inspect_unclaimed_object_handler
> +    (ld_plugin_inspect_unclaimed_object_handler handler)
>
> Same here.
>
> +  // The list of unclaimed objects.  The negative of the index of an
> +  // in this list serves as the "handle" that we pass to the plugins.
> +  // Postive integer values for "handle" are for the claimed objects
> +  // and negative values are for the unclaimed objects.
>
> It doesn't look like this is how you implemented it -- I think you're
> returning straight non-negative indices in both cases. Also, remember
> that 0 is used as a handle for the first claimed object, so it should
> really be negative vs. "non-negative".
>
> This looks good to me with these changes. (You need Ian's approval to
> commit, though.)
>
> Thanks!
>
> -cary
>

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

Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.190
diff -u -u -p -r1.190 layout.cc
--- layout.cc	10 Jan 2011 21:57:31 -0000	1.190
+++ layout.cc	14 Mar 2011 18:40:50 -0000
@@ -207,7 +207,10 @@ Layout::Layout(int number_of_input_files
     record_output_section_data_from_script_(false),
     script_output_section_data_list_(),
     segment_states_(NULL),
-    relaxation_debug_check_(NULL)
+    relaxation_debug_check_(NULL),
+    section_ordering_specified_(false),
+    input_section_position_(),
+    input_section_glob_()
 {
   // Make space for more than enough segments for a typical file.
   // This is just for efficiency--it's OK if we wind up needing more.
@@ -1817,13 +1820,28 @@ Layout::find_section_order_index(const s
   return 0;
 }
 
+// Updates the input section order of all output sections.  This
+// is called when the section order is specified via plugins.
+
+void
+Layout::update_layout_of_sections()
+{
+  for (Section_list::iterator p = this->section_list_.begin();
+       p != this->section_list_.end();
+       ++p)
+    {
+      if ((*p) == NULL)
+        continue;
+      (*p)->update_section_layout(this);
+    }
+}
+
 // Read the sequence of input sections from the file specified with
-// --section-ordering-file.
+// linker option --section-ordering-file.
 
 void
-Layout::read_layout_from_file()
+Layout::read_layout_from_file(const char* filename)
 {
-  const char* filename = parameters->options().section_ordering_file();
   std::ifstream in;
   std::string line;
 
@@ -1834,6 +1852,7 @@ Layout::read_layout_from_file()
 
   std::getline(in, line);   // this chops off the trailing \n, if any
   unsigned int position = 1;
+  this->section_ordering_specified();
 
   while (in)
     {
Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.88
diff -u -u -p -r1.88 layout.h
--- layout.h	14 Dec 2010 19:03:30 -0000	1.88
+++ layout.h	14 Mar 2011 18:40:50 -0000
@@ -414,11 +414,25 @@ 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 section_ordering_specified_; }
+
+  void
+  section_ordering_specified()
+  { section_ordering_specified_ = true; }
+
   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(const char* filename);
+
+  // Updates the order of input sections in the output sections.
   void
-  read_layout_from_file();
+  update_layout_of_sections();
 
   // Layout an input reloc section when doing a relocatable link.  The
   // section is RELOC_SHNDX in OBJECT, with data in SHDR.
@@ -1147,6 +1161,9 @@ class Layout
   Segment_states* segment_states_;
   // A relaxation debug checker.  We only create one when in debugging mode.
   Relaxation_debug_check* relaxation_debug_check_;
+  // True if the input sections in the output sections should be sorted
+  // as specified in a section ordering file.
+  bool section_ordering_specified_;
   // 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: main.cc
===================================================================
RCS file: /cvs/src/src/gold/main.cc,v
retrieving revision 1.42
diff -u -u -p -r1.42 main.cc
--- main.cc	14 Dec 2010 19:03:30 -0000	1.42
+++ main.cc	14 Mar 2011 18:40:50 -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());
 
@@ -231,8 +227,15 @@ main(int argc, char** argv)
   if (layout.incremental_inputs() != NULL)
     layout.incremental_inputs()->report_command_line(argc, 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);
+
+  const char* section_ordering_file
+      = parameters->options().section_ordering_file();
+
+  if (section_ordering_file)
+    layout.read_layout_from_file(section_ordering_file);
 
   // Get the search path from the -L options.
   Dirsearch search_path;
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.140
diff -u -u -p -r1.140 output.cc
--- output.cc	12 Feb 2011 03:19:24 -0000	1.140
+++ output.cc	14 Mar 2011 18:40:50 -0000
@@ -2165,10 +2165,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));
@@ -3041,6 +3041,34 @@ Output_section::Input_section_sort_secti
   return s1_secn_index < s2_secn_index;
 }
 
+// Updates the ordering of input sections in this output section.
+
+void
+Output_section::update_section_layout(Layout* layout)
+{
+  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());
+
+          std::string section_name = obj->section_name((*p).shndx());
+	  unsigned int section_order_index =
+            layout->find_section_order_index(section_name);
+	  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
@@ -3083,7 +3111,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: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.118
diff -u -u -p -r1.118 output.h
--- output.h	23 Dec 2010 19:56:14 -0000	1.118
+++ output.h	14 Mar 2011 18:40:50 -0000
@@ -2564,6 +2564,9 @@ class Output_section : public Output_dat
   flags() const
   { return this->flags_; }
 
+  void
+  update_section_layout(Layout* layout);
+
   // Update the output section flags based on input section flags.
   void
   update_flags_for_input_section(elfcpp::Elf_Xword flags);
Index: plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.43
diff -u -u -p -r1.43 plugin.cc
--- plugin.cc	8 Feb 2011 05:03:19 -0000	1.43
+++ plugin.cc	14 Mar 2011 18:40:50 -0000
@@ -57,6 +57,10 @@ static enum ld_plugin_status
 register_claim_file(ld_plugin_claim_file_handler handler);
 
 static enum ld_plugin_status
+register_inspect_unclaimed_object(
+    ld_plugin_inspect_unclaimed_object_handler handler);
+
+static enum ld_plugin_status
 register_all_symbols_read(ld_plugin_all_symbols_read_handler handler);
 
 static enum ld_plugin_status
@@ -86,6 +90,28 @@ set_extra_library_path(const char *path)
 static enum ld_plugin_status
 message(int level, const char *format, ...);
 
+static enum ld_plugin_status
+get_section_count(const void* handle, unsigned int* count);
+
+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx,
+                 unsigned int* type);
+
+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx,
+                 char** section_name_ptr);
+
+static enum ld_plugin_status
+get_section_contents(void* handle, unsigned int shndx,
+                     unsigned char** section_contents,
+		     unsigned int* len);
+
+static enum ld_plugin_status
+read_layout_from_file(const char* filename);
+
+static enum ld_plugin_status
+allow_section_ordering();
+
 };
 
 #endif // ENABLE_PLUGINS
@@ -130,7 +156,7 @@ Plugin::load()
   sscanf(ver, "%d.%d", &major, &minor);
 
   // Allocate and populate a transfer vector.
-  const int tv_fixed_size = 16;
+  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];
 
@@ -173,6 +199,11 @@ Plugin::load()
   tv[i].tv_u.tv_register_claim_file = register_claim_file;
 
   ++i;
+  tv[i].tv_tag = LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK;
+  tv[i].tv_u.tv_register_inspect_unclaimed_object
+    = register_inspect_unclaimed_object;
+
+  ++i;
   tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK;
   tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read;
 
@@ -209,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_SECTION_COUNT;
+  tv[i].tv_u.tv_get_section_count = get_section_count;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_TYPE;
+  tv[i].tv_u.tv_get_section_type = get_section_type;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_NAME;
+  tv[i].tv_u.tv_get_section_name = get_section_name;
+
+  ++i;
+  tv[i].tv_tag = LDPT_GET_SECTION_CONTENTS;
+  tv[i].tv_u.tv_get_section_contents = get_section_contents;
+
+  ++i;
+  tv[i].tv_tag = LDPT_READ_LAYOUT_FROM_FILE;
+  tv[i].tv_u.tv_read_layout_from_file = read_layout_from_file;
+
+  ++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;
 
@@ -237,6 +292,16 @@ Plugin::claim_file(struct ld_plugin_inpu
   return false;
 }
 
+// Call the plugin inspect_unclaimed_object handler.
+
+inline void
+Plugin::inspect_unclaimed_object(unsigned int index)
+{
+  void* handle =  reinterpret_cast<void*>(index);
+  if (this->inspect_unclaimed_object_handler_ != NULL)
+      (*this->inspect_unclaimed_object_handler_)(handle);
+}
+
 // Call the all-symbols-read handler.
 
 inline void
@@ -319,8 +384,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_)
@@ -365,6 +431,27 @@ Plugin_manager::claim_file(Input_file* i
   return NULL;
 }
 
+// Call the plugin inspect_unclaimed_object handlers to allow them to inspect
+// the unclaimed object. Pass the handle of the object which is the index
+// into the vector containing the unclaimed objects.
+
+void
+Plugin_manager::inspect_unclaimed_object(Object* obj)
+{
+  unsigned int index;
+  index = this->unclaimed_objects_.size();
+  this->unclaimed_objects_.push_back(obj);
+
+  this->in_inspect_unclaimed_object_handler_ = true;
+
+  for (this->current_ = this->plugins_.begin();
+       this->current_ != this->plugins_.end();
+       ++this->current_)
+    (*this->current_)->inspect_unclaimed_object(index);
+
+  this->in_inspect_unclaimed_object_handler_ = false;
+}
+
 // Save an archive.  This is used so that a plugin can add a file
 // which refers to a symbol which was not previously referenced.  In
 // that case we want to pretend that the symbol was referenced before,
@@ -395,7 +482,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)
 {
@@ -404,7 +491,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;
@@ -635,6 +721,21 @@ Plugin_manager::release_input_file(unsig
   return LDPS_OK;
 }
 
+// Get the object from the list of unclaimed objects with
+// index specified in handle.
+
+Object*
+Plugin_manager::get_unclaimed_object(const void* handle)
+{
+  unsigned int index
+      =  static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle));
+  Object* obj = NULL;
+
+  obj = parameters->options().plugins()->unclaimed_object(index);
+
+  return obj;
+}
+
 // Add a new library path.
 
 ld_plugin_status
@@ -1168,7 +1269,6 @@ Plugin_hook::run(Workqueue* workqueue)
                                              this,
                                              this->input_objects_,
                                              this->symtab_,
-                                             this->layout_,
                                              this->dirpath_,
                                              this->mapfile_,
                                              &this->this_blocker_);
@@ -1190,6 +1290,18 @@ register_claim_file(ld_plugin_claim_file
   return LDPS_OK;
 }
 
+//Register a inspect_unclaimed_object handler.
+
+static enum ld_plugin_status
+register_inspect_unclaimed_object
+  (ld_plugin_inspect_unclaimed_object_handler handler)
+{
+  gold_assert(parameters->options().has_plugins());
+  parameters->options().plugins()->set_inspect_unclaimed_object_handler(
+      handler);
+  return LDPS_OK;
+}
+
 // Register an all-symbols-read handler.
 
 static enum ld_plugin_status
@@ -1317,6 +1429,123 @@ 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 inspect_unclaimed_object
+// handler of the plugin.
+
+static enum ld_plugin_status
+get_section_count(const void* handle, unsigned int* count)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  *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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx, unsigned int* type)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  *type = obj->section_type(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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  const char* section_name = obj->section_name(shndx).c_str();
+  *section_name_ptr = (char*)malloc(strlen(section_name) + 1);
+  strcpy(*section_name_ptr, section_name);
+  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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_contents(void* handle, unsigned int shndx,
+                     unsigned char** section_contents_ptr,
+		     unsigned int* len)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  section_size_type plen;
+  const unsigned char* section_contents = obj->section_contents(shndx, &plen,
+                                                                false);
+  *section_contents_ptr = (unsigned char*)malloc(plen);
+  memcpy(*section_contents_ptr, section_contents, plen);
+  *len = plen;
+  return LDPS_OK;
+}
+
+// Specify the ordering of sections in the final layout in a file. This
+// does what the linker option --section-ordering-file does.
+
+static enum ld_plugin_status
+read_layout_from_file(const char* filename)
+{
+  gold_assert(parameters->options().has_plugins());
+  Layout* layout = parameters->options().plugins()->layout();
+  layout->read_layout_from_file(filename);
+  layout->update_layout_of_sections();
+  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->section_ordering_specified();
+  return LDPS_OK;
+}
+
 #endif // ENABLE_PLUGINS
 
 // Allocate a Pluginobj object of the appropriate size and endianness.
Index: plugin.h
===================================================================
RCS file: /cvs/src/src/gold/plugin.h,v
retrieving revision 1.16
diff -u -u -p -r1.16 plugin.h
--- plugin.h	24 Jan 2011 21:48:40 -0000	1.16
+++ plugin.h	14 Mar 2011 18:40:51 -0000
@@ -58,6 +58,7 @@ class Plugin
       filename_(filename),
       args_(),
       claim_file_handler_(NULL),
+      inspect_unclaimed_object_handler_(NULL),
       all_symbols_read_handler_(NULL),
       cleanup_handler_(NULL),
       cleanup_done_(false)
@@ -74,6 +75,10 @@ class Plugin
   bool
   claim_file(struct ld_plugin_input_file* plugin_input_file);
 
+  // Call the inspect_unclaimed_object handler.
+  void
+  inspect_unclaimed_object(unsigned int index);
+
   // Call the all-symbols-read handler.
   void
   all_symbols_read();
@@ -87,6 +92,12 @@ class Plugin
   set_claim_file_handler(ld_plugin_claim_file_handler handler)
   { this->claim_file_handler_ = handler; }
 
+  // Register a inspect_unclaimed_object handler.
+  void
+  set_inspect_unclaimed_object_handler(
+      ld_plugin_inspect_unclaimed_object_handler handler)
+  { this->inspect_unclaimed_object_handler_ = handler; }
+
   // Register an all-symbols-read handler.
   void
   set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
@@ -116,6 +127,7 @@ class Plugin
   std::vector<std::string> args_;
   // The plugin's event handlers.
   ld_plugin_claim_file_handler claim_file_handler_;
+  ld_plugin_inspect_unclaimed_object_handler inspect_unclaimed_object_handler_;
   ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
   ld_plugin_cleanup_handler cleanup_handler_;
   // TRUE if the cleanup handlers have been called.
@@ -128,9 +140,11 @@ class Plugin_manager
 {
  public:
   Plugin_manager(const General_options& options)
-    : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
+    : plugins_(), objects_(), unclaimed_objects_(),
+      deferred_layout_objects_(), input_file_(NULL),
       plugin_input_file_(), rescannable_(), undefined_symbols_(),
       any_claimed_(false), in_replacement_phase_(false), any_added_(false),
+      in_inspect_unclaimed_object_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,12 +167,26 @@ 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);
 
+  // Call the plugin inspect_unclaimed_object handlers to allow them
+  // to inspect the file.
+  void
+  inspect_unclaimed_object(Object* obj);
+
+  Object*
+  get_unclaimed_object(const void* handle);
+
+  // True if the inspect_unclaimed_object handler of the plugins are being
+  // called.
+  bool
+  in_inspect_unclaimed_object_handler()
+  { return in_inspect_unclaimed_object_handler_; }
+
   // Let the plugin manager save an archive for later rescanning.
   // This takes ownership of the Archive pointer.
   void
@@ -173,7 +201,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
@@ -197,6 +225,15 @@ class Plugin_manager
     (*this->current_)->set_claim_file_handler(handler);
   }
 
+  // Register a inspect_unclaimed_object handler.
+  void
+  set_inspect_unclaimed_object_handler(
+      ld_plugin_inspect_unclaimed_object_handler handler)
+  {
+    gold_assert(this->current_ != plugins_.end());
+    (*this->current_)->set_inspect_unclaimed_object_handler(handler);
+  }
+
   // Register an all-symbols-read handler.
   void
   set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
@@ -227,6 +264,15 @@ class Plugin_manager
     return this->objects_[handle];
   }
 
+  // Return the unclaimed object associated with the given HANDLE.
+  Object*
+  unclaimed_object(unsigned int handle) const
+  {
+    if (handle >= this->unclaimed_objects_.size())
+      return NULL;
+    return this->unclaimed_objects_[handle];
+  }
+
   // Return TRUE if any input files have been claimed by a plugin
   // and we are still in the initial input phase.
   bool
@@ -262,6 +308,14 @@ class Plugin_manager
   in_replacement_phase() const
   { return this->in_replacement_phase_; }
 
+  Input_objects*
+  input_objects() const
+  { return input_objects_; }
+
+  Layout*
+  layout()
+  { return layout_; }
+
  private:
   Plugin_manager(const Plugin_manager&);
   Plugin_manager& operator=(const Plugin_manager&);
@@ -291,6 +345,7 @@ class Plugin_manager
 
   typedef std::list<Plugin*> Plugin_list;
   typedef std::vector<Pluginobj*> Object_list;
+  typedef std::vector<Object*> Unclaimed_object_list;
   typedef std::vector<Relobj*> Deferred_layout_list;
   typedef std::vector<Rescannable> Rescannable_list;
   typedef std::vector<Symbol*> Undefined_symbol_list;
@@ -312,6 +367,11 @@ class Plugin_manager
   // serves as the "handle" that we pass to the plugins.
   Object_list objects_;
 
+  // The list of unclaimed objects.  The the index of an item in this
+  // in this list serves as the "handle" that we pass to the plugins
+  // in inspect_unclaimed_object_handler.
+  Unclaimed_object_list unclaimed_objects_;
+
   // The list of regular objects whose layout has been deferred.
   Deferred_layout_list deferred_layout_objects_;
 
@@ -337,6 +397,10 @@ class Plugin_manager
   // Whether any input files or libraries were added by a plugin.
   bool any_added_;
 
+  // Set to true when the inspect_unclaimed_object_handler of the plugins are being
+  // called.
+  bool in_inspect_unclaimed_object_handler_;
+
   const General_options& options_;
   Workqueue* workqueue_;
   Task* task_;
Index: readsyms.cc
===================================================================
RCS file: /cvs/src/src/gold/readsyms.cc,v
retrieving revision 1.47
diff -u -u -p -r1.47 readsyms.cc
--- readsyms.cc	24 Jan 2011 21:48:40 -0000	1.47
+++ readsyms.cc	14 Mar 2011 18:40:51 -0000
@@ -380,6 +380,10 @@ Read_symbols::do_read_symbols(Workqueue*
 	  return false;
 	}
 
+      // Allow the plugins to inspect the unclaimed object now.
+      if (parameters->options().has_plugins())
+        parameters->options().plugins()->inspect_unclaimed_object(obj);
+
       Read_symbols_data* sd = new Read_symbols_data;
       obj->read_symbols(sd);
 
cvs diff: Diffing po
cvs diff: Diffing testsuite
Index: 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
--- testsuite/plugin_test.c	9 Nov 2009 16:11:34 -0000	1.4
+++ testsuite/plugin_test.c	14 Mar 2011 18:40:51 -0000
@@ -52,6 +52,8 @@ static struct claimed_file* first_claime
 static struct claimed_file* last_claimed_file = NULL;
 
 static ld_plugin_register_claim_file register_claim_file_hook = NULL;
+static ld_plugin_register_inspect_unclaimed_object
+  register_inspect_unclaimed_object_hook = NULL;
 static ld_plugin_register_all_symbols_read register_all_symbols_read_hook = NULL;
 static ld_plugin_register_cleanup register_cleanup_hook = NULL;
 static ld_plugin_add_symbols add_symbols = NULL;
@@ -60,6 +62,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_section_count get_section_count = NULL;
+static ld_plugin_get_section_type get_section_type = NULL;
+static ld_plugin_get_section_name get_section_name = NULL;
+static ld_plugin_get_section_contents get_section_contents = NULL;
+static ld_plugin_read_layout_from_file read_layout_from_file = NULL;
+static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
 
 #define MAXOPTS 10
 
@@ -69,6 +77,7 @@ static int nopts = 0;
 enum ld_plugin_status onload(struct ld_plugin_tv *tv);
 enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
                                       int *claimed);
+enum ld_plugin_status inspect_unclaimed_object_hook(void* handle);
 enum ld_plugin_status all_symbols_read_hook(void);
 enum ld_plugin_status cleanup_hook(void);
 
@@ -101,6 +110,10 @@ onload(struct ld_plugin_tv *tv)
         case LDPT_REGISTER_CLAIM_FILE_HOOK:
           register_claim_file_hook = entry->tv_u.tv_register_claim_file;
           break;
+	case LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK:
+          register_inspect_unclaimed_object_hook
+            = entry->tv_u.tv_register_inspect_unclaimed_object;
+          break;
         case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
           register_all_symbols_read_hook =
             entry->tv_u.tv_register_all_symbols_read;
@@ -126,6 +139,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_SECTION_COUNT:
+          get_section_count = *entry->tv_u.tv_get_section_count;
+          break;
+        case LDPT_GET_SECTION_TYPE:
+          get_section_type = *entry->tv_u.tv_get_section_type;
+          break;
+        case LDPT_GET_SECTION_NAME:
+          get_section_name = *entry->tv_u.tv_get_section_name;
+          break;
+        case LDPT_GET_SECTION_CONTENTS:
+          get_section_contents = *entry->tv_u.tv_get_section_contents;
+          break;
+	case LDPT_READ_LAYOUT_FROM_FILE:
+	  read_layout_from_file = *entry->tv_u.tv_read_layout_from_file;
+	  break;
+	case LDPT_ALLOW_SECTION_ORDERING:
+	  allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
+	  break;
         default:
           break;
         }
@@ -143,6 +174,13 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if (register_inspect_unclaimed_object_hook == NULL)
+    {
+      fprintf(stderr,
+              "tv_register_inspect_unclaimed_object_hook interface missing\n");
+      return LDPS_ERR;
+    }
+
   if (register_all_symbols_read_hook == NULL)
     {
       fprintf(stderr, "tv_register_all_symbols_read_hook interface missing\n");
@@ -167,6 +205,14 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if ((*register_inspect_unclaimed_object_hook)
+        (inspect_unclaimed_object_hook) != LDPS_OK)
+    {
+      (*message)(LDPL_ERROR,
+                 "error registering inspect unclaimed object hook");
+      return LDPS_ERR;
+    }
+
   if ((*register_all_symbols_read_hook)(all_symbols_read_hook) != LDPS_OK)
     {
       (*message)(LDPL_ERROR, "error registering all symbols read hook");
@@ -179,10 +225,53 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if (get_section_count == NULL)
+    {
+      fprintf(stderr, "tv_get_section_count interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_type == NULL)
+    {
+      fprintf(stderr, "tv_get_section_type interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_name == NULL)
+    {
+      fprintf(stderr, "tv_get_section_name interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (get_section_contents == NULL)
+    {
+      fprintf(stderr, "tv_get_section_contents interface missing\n");
+      return LDPS_ERR;
+    }
+
+  if (read_layout_from_file == NULL)
+    {
+      fprintf(stderr, "tv_read_layout_from_file 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;
 }
 
 enum ld_plugin_status
+inspect_unclaimed_object_hook (void* handle)
+{
+  (*message)(LDPL_INFO, "Inspect unclaimed object hook called with handle: %p",
+             handle);
+  return LDPS_OK;
+}
+enum ld_plugin_status
 claim_file_hook (const struct ld_plugin_input_file* file, int* claimed)
 {
   int len;
Index: plugin-api.h
===================================================================
RCS file: /cvs/src/src/include/plugin-api.h,v
retrieving revision 1.13
diff -u -u -p -r1.13 plugin-api.h
--- plugin-api.h	3 Jan 2011 21:05:50 -0000	1.13
+++ plugin-api.h	13 Mar 2011 02:24:32 -0000
@@ -157,6 +157,12 @@ enum ld_plugin_status
 (*ld_plugin_claim_file_handler) (
   const struct ld_plugin_input_file *file, int *claimed);
 
+/* The plugin library's "observe file" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_inspect_unclaimed_object_handler) (void *);
+
 /* The plugin library's "all symbols read" handler.  */
 
 typedef
@@ -175,6 +181,13 @@ typedef
 enum ld_plugin_status
 (*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler);
 
+/* The linker's interface for registering the "observe file" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_inspect_unclaimed_object)
+  (ld_plugin_inspect_unclaimed_object_handler handler);
+
 /* The linker's interface for registering the "all symbols read" handler.  */
 
 typedef
@@ -240,6 +253,59 @@ 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 inspect_unclaimed_object_handler.  This
+   interface should only be invoked in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_count) (const void* handle, unsigned int* count);
+
+/* The linker's interface for retrieving the section type of a specific
+   section in an object.  The handle is obtained in the
+   inspect_unclaimed_object_handler.  This interface should only be
+   invoked in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_type) (void* handle, unsigned int shndx,
+                               unsigned int* type);
+
+/* The linker's interface for retrieving the name of specific section in
+   an object. The handle is obtained in the inspect_unclaimed_object_handler.
+   This interface should only be invoked in the
+   inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
+                               char** section_name_ptr);
+
+/* The linker's interface for retrieving the contents of a specific section
+   in an object.  The handle is obtained in the
+   inspect_unclaimed_object_handler.  This interface should only be invoked
+   in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_contents) (void* handle, unsigned int shndx,
+                                   unsigned char** section_contents,
+                                   unsigned int* len);
+
+/* The linker's interface for specifying the desired order of sections
+   through a file.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_read_layout_from_file) (const char* filename);
+
+/* The linker's interface for specifying that reordering of sections is
+   desired.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_allow_section_ordering) (void);
+
 enum ld_plugin_level
 {
   LDPL_INFO,
@@ -258,6 +324,7 @@ enum ld_plugin_tag
   LDPT_LINKER_OUTPUT,
   LDPT_OPTION,
   LDPT_REGISTER_CLAIM_FILE_HOOK,
+  LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK,
   LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
   LDPT_REGISTER_CLEANUP_HOOK,
   LDPT_ADD_SYMBOLS,
@@ -269,7 +336,13 @@ enum ld_plugin_tag
   LDPT_ADD_INPUT_LIBRARY,
   LDPT_OUTPUT_NAME,
   LDPT_SET_EXTRA_LIBRARY_PATH,
-  LDPT_GNU_LD_VERSION
+  LDPT_GNU_LD_VERSION,
+  LDPT_GET_SECTION_COUNT,
+  LDPT_GET_SECTION_TYPE,
+  LDPT_GET_SECTION_NAME,
+  LDPT_GET_SECTION_CONTENTS,
+  LDPT_READ_LAYOUT_FROM_FILE,
+  LDPT_ALLOW_SECTION_ORDERING
 };
 
 /* The plugin transfer vector.  */
@@ -282,6 +355,8 @@ struct ld_plugin_tv
     int tv_val;
     const char *tv_string;
     ld_plugin_register_claim_file tv_register_claim_file;
+    ld_plugin_register_inspect_unclaimed_object
+      tv_register_inspect_unclaimed_object;
     ld_plugin_register_all_symbols_read tv_register_all_symbols_read;
     ld_plugin_register_cleanup tv_register_cleanup;
     ld_plugin_add_symbols tv_add_symbols;
@@ -292,6 +367,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_section_count tv_get_section_count;
+    ld_plugin_get_section_type tv_get_section_type;
+    ld_plugin_get_section_name tv_get_section_name;
+    ld_plugin_get_section_contents tv_get_section_contents;
+    ld_plugin_read_layout_from_file tv_read_layout_from_file;
+    ld_plugin_allow_section_ordering tv_allow_section_ordering;
   } tv_u;
 };
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-14 18:45       ` Sriraman Tallam
@ 2011-03-15 14:44         ` Ian Lance Taylor
  2011-03-15 17:48           ` Cary Coutant
  2011-06-04  0:46           ` Sriraman Tallam
  0 siblings, 2 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-03-15 14:44 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: Cary Coutant, binutils

Sriraman Tallam <tmsriram@google.com> writes:

> +void
> +Layout::update_layout_of_sections()
> +{
> +  for (Section_list::iterator p = this->section_list_.begin();
> +       p != this->section_list_.end();
> +       ++p)
> +    {
> +      if ((*p) == NULL)
> +        continue;
> +      (*p)->update_section_layout(this);

The check for NULL should be unnecessary.  Nothing should push NULL on
section_list_.  Please remove it.  If it were needed, several other
loops would have to be changed as well.

> +  void
> +  section_ordering_specified()
> +  { section_ordering_specified_ = true; }

This needs to be named set_section_ordering_specified as in other cases
in gold.  Calling it section_ordering_specified makes it look like an
accessor function.


> @@ -1147,6 +1161,9 @@ class Layout
>    Segment_states* segment_states_;
>    // A relaxation debug checker.  We only create one when in debugging mode.
>    Relaxation_debug_check* relaxation_debug_check_;
> +  // True if the input sections in the output sections should be sorted
> +  // as specified in a section ordering file.
> +  bool section_ordering_specified_;

Put this with the other bool members.

> +  // Load plugin libraries.
> +  if (command_line.options().has_plugins())
> +    command_line.options().plugins()->load_plugins(&layout);
> +
> +  const char* section_ordering_file
> +      = parameters->options().section_ordering_file();
> +
> +  if (section_ordering_file)
> +    layout.read_layout_from_file(section_ordering_file);

Remove the blank line after the declaration.  Write the conditional as
  if (section_ordering_file != NULL)

> +// Updates the ordering of input sections in this output section.
> +
> +void
> +Output_section::update_section_layout(Layout* layout)
> +{
> +  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());
> +
> +          std::string section_name = obj->section_name((*p).shndx());
> +	  unsigned int section_order_index =
> +            layout->find_section_order_index(section_name);
> +	  if (section_order_index != 0)
> +            {
> +              (*p).set_section_order_index(section_order_index);
> +              this->set_input_section_order_specified();
> +	    }
> +         }
> +    }
> +}

When calling obj->section_name(), you must lock the object.  See the
Output_section::Input_section_sort_entry constructor.  As that code
says, section_name() is a slow operation.  It would be better if we
could avoid calling it for every single input section if possible.

> +// Call the plugin inspect_unclaimed_object handler.
> +
> +inline void
> +Plugin::inspect_unclaimed_object(unsigned int index)
> +{
> +  void* handle =  reinterpret_cast<void*>(index);
> +  if (this->inspect_unclaimed_object_handler_ != NULL)
> +      (*this->inspect_unclaimed_object_handler_)(handle);
> +}

Extra space after '=' sign.

Write the cast as
  reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(index))

However, I don't see why you are using an index here.  You have an
Object* pointer.  Why not just use that as the handle?

> +Object*
> +Plugin_manager::get_unclaimed_object(const void* handle)
> +{
> +  unsigned int index
> +      =  static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle));
> +  Object* obj = NULL;
> +
> +  obj = parameters->options().plugins()->unclaimed_object(index);
> +
> +  return obj;
> +}

Extra space after '=' in index, but as I say I don't see why this
function is needed at all.

> +// Get the name of the specified section in the object corresponding
> +// to the handle.  This plugin interface can only be called in the
> +// inspect_unclaimed_object handler of the plugin.
> +
> +static enum ld_plugin_status
> +get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +
> +  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
> +    return LDPS_ERR;
> +
> +  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
> +
> +  if (obj == NULL)
> +    return LDPS_BAD_HANDLE;
> +
> +  const char* section_name = obj->section_name(shndx).c_str();
> +  *section_name_ptr = (char*)malloc(strlen(section_name) + 1);
> +  strcpy(*section_name_ptr, section_name);
> +  return LDPS_OK;
> +}

*section_name_ptr = static_cast<char*>(malloc(strlen(section_name) + 1));

> +// Get the contents of the specified section in the object corresponding
> +// to the handle.  This plugin interface can only be called in the
> +// inspect_unclaimed_object handler of the plugin.
> +
> +static enum ld_plugin_status
> +get_section_contents(void* handle, unsigned int shndx,
> +                     unsigned char** section_contents_ptr,
> +		     unsigned int* len)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +
> +  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
> +    return LDPS_ERR;
> +
> +  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
> +
> +  if (obj == NULL)
> +    return LDPS_BAD_HANDLE;
> +
> +  section_size_type plen;
> +  const unsigned char* section_contents = obj->section_contents(shndx, &plen,
> +                                                                false);
> +  *section_contents_ptr = (unsigned char*)malloc(plen);
> +  memcpy(*section_contents_ptr, section_contents, plen);
> +  *len = plen;
> +  return LDPS_OK;
> +}

If we expect plugins to actually use this, I think a better interface
would be to return a pointer to the data rather than to copy the entire
section contents.  We could say that the pointer returned would be valid
until the inspect_unclaimed_object_handler returns.  The plugin could
copy the section contents itself if it needs it longer than that.

> +// Specify the ordering of sections in the final layout in a file. This
> +// does what the linker option --section-ordering-file does.
> +
> +static enum ld_plugin_status
> +read_layout_from_file(const char* filename)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +  Layout* layout = parameters->options().plugins()->layout();
> +  layout->read_layout_from_file(filename);
> +  layout->update_layout_of_sections();
> +  return LDPS_OK;
> +}

This is a strange interface.  We have a plugin that has assembled all
the information it needs in memory.  Now we are saying that it should
write it out to a file, and then ask the linker to read that file.  That
does not make sense to me.  All that the file contains is a sequence of
strings.  Why not just have an interface which we can pass strings to?
Either an array of strings, or call the interface once per string,
whatever is most convenient.

> +  // The list of unclaimed objects.  The the index of an item in this
> +  // in this list serves as the "handle" that we pass to the plugins
> +  // in inspect_unclaimed_object_handler.
> +  Unclaimed_object_list unclaimed_objects_;

If you use an Object* as the handle, I don't think you need this list at
all.

> Index: plugin-api.h

Note that this file lives in the gcc repository too.

> +/* The plugin library's "observe file" handler.  */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_inspect_unclaimed_object_handler) (void *);

I think it would be useful to use a typedef here, to lessen the change
of confusion between the two different kinds of handles.  E.g.,

typedef void *unclaimed_object_handle;

Then use unclaimed_object_handle where appropriate.

> +/* The linker's interface for registering the "observe file" handler.  */

s/observe/inspect/.

> +/* The linker's interface for retrieving the number of sections in an object.
> +   The handle is obtained in the inspect_unclaimed_object_handler.  This
> +   interface should only be invoked in the inspect_unclaimed_object_handler. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_section_count) (const void* handle, unsigned int* count);

I think this should be named get_input_section_count.

The comment should say that the function sets *COUNT.

> +
> +/* The linker's interface for retrieving the section type of a specific
> +   section in an object.  The handle is obtained in the
> +   inspect_unclaimed_object_handler.  This interface should only be
> +   invoked in the inspect_unclaimed_object_handler. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_section_type) (void* handle, unsigned int shndx,
> +                               unsigned int* type);

I think this should be named get_input_section_type.

The comment should say that the function sets *TYPE to an ELF SHT_xxx
value.

> +/* The linker's interface for retrieving the name of specific section in
> +   an object. The handle is obtained in the inspect_unclaimed_object_handler.
> +   This interface should only be invoked in the
> +   inspect_unclaimed_object_handler. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
> +                               char** section_name_ptr);

I think this should be named get_input_section_name.

The command needs to say that the function sets *section_name_ptr to a
null-terminated buffer allocated by malloc.

> +/* The linker's interface for retrieving the contents of a specific section
> +   in an object.  The handle is obtained in the
> +   inspect_unclaimed_object_handler.  This interface should only be invoked
> +   in the inspect_unclaimed_object_handler. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_section_contents) (void* handle, unsigned int shndx,
> +                                   unsigned char** section_contents,
> +                                   unsigned int* len);

I think this should be named get_input_section_contents.

As noted above, I think we should return a pointer to a memory buffer
that is valid until inspect_unclaimed_object_handle returns.


> +/* The linker's interface for specifying the desired order of sections
> +   through a file.  */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_read_layout_from_file) (const char* filename);
> +
> +/* The linker's interface for specifying that reordering of sections is
> +   desired.  */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_allow_section_ordering) (void);

The comments need to say something about why both hooks are needed, and
when they may be called.

Ian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-15 14:44         ` Ian Lance Taylor
@ 2011-03-15 17:48           ` Cary Coutant
  2011-03-15 20:11             ` Ian Lance Taylor
  2011-06-04  0:46           ` Sriraman Tallam
  1 sibling, 1 reply; 19+ messages in thread
From: Cary Coutant @ 2011-03-15 17:48 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Sriraman Tallam, binutils

> However, I don't see why you are using an index here.  You have an
> Object* pointer.  Why not just use that as the handle?

Sri's first patch did use the Object* as the handle, but I suggested
using an index like the original plugin APIs do. This makes it more
consistent with the existing interfaces, and also makes it easier to
sanity check the value passed in from a plugin library.

-cary

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-15 17:48           ` Cary Coutant
@ 2011-03-15 20:11             ` Ian Lance Taylor
  0 siblings, 0 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-03-15 20:11 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Sriraman Tallam, binutils

Cary Coutant <ccoutant@google.com> writes:

>> However, I don't see why you are using an index here.  You have an
>> Object* pointer.  Why not just use that as the handle?
>
> Sri's first patch did use the Object* as the handle, but I suggested
> using an index like the original plugin APIs do. This makes it more
> consistent with the existing interfaces, and also makes it easier to
> sanity check the value passed in from a plugin library.

Hmmmm, well, OK.

Ian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-03-15 14:44         ` Ian Lance Taylor
  2011-03-15 17:48           ` Cary Coutant
@ 2011-06-04  0:46           ` Sriraman Tallam
  2011-06-24 22:25             ` Cary Coutant
  1 sibling, 1 reply; 19+ messages in thread
From: Sriraman Tallam @ 2011-06-04  0:46 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Cary Coutant, binutils

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

Hi,

  Finally, I managed to make all these changes and I have attached the
new patch. Thanks.

-Sri.


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



On Tue, Mar 15, 2011 at 7:44 AM, Ian Lance Taylor <iant@google.com> wrote:
> Sriraman Tallam <tmsriram@google.com> writes:
>
>> +void
>> +Layout::update_layout_of_sections()
>> +{
>> +  for (Section_list::iterator p = this->section_list_.begin();
>> +       p != this->section_list_.end();
>> +       ++p)
>> +    {
>> +      if ((*p) == NULL)
>> +        continue;
>> +      (*p)->update_section_layout(this);
>
> The check for NULL should be unnecessary.  Nothing should push NULL on
> section_list_.  Please remove it.  If it were needed, several other
> loops would have to be changed as well.
>
>> +  void
>> +  section_ordering_specified()
>> +  { section_ordering_specified_ = true; }
>
> This needs to be named set_section_ordering_specified as in other cases
> in gold.  Calling it section_ordering_specified makes it look like an
> accessor function.
>
>
>> @@ -1147,6 +1161,9 @@ class Layout
>>    Segment_states* segment_states_;
>>    // A relaxation debug checker.  We only create one when in debugging mode.
>>    Relaxation_debug_check* relaxation_debug_check_;
>> +  // True if the input sections in the output sections should be sorted
>> +  // as specified in a section ordering file.
>> +  bool section_ordering_specified_;
>
> Put this with the other bool members.
>
>> +  // Load plugin libraries.
>> +  if (command_line.options().has_plugins())
>> +    command_line.options().plugins()->load_plugins(&layout);
>> +
>> +  const char* section_ordering_file
>> +      = parameters->options().section_ordering_file();
>> +
>> +  if (section_ordering_file)
>> +    layout.read_layout_from_file(section_ordering_file);
>
> Remove the blank line after the declaration.  Write the conditional as
>  if (section_ordering_file != NULL)
>
>> +// Updates the ordering of input sections in this output section.
>> +
>> +void
>> +Output_section::update_section_layout(Layout* layout)
>> +{
>> +  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());
>> +
>> +          std::string section_name = obj->section_name((*p).shndx());
>> +       unsigned int section_order_index =
>> +            layout->find_section_order_index(section_name);
>> +       if (section_order_index != 0)
>> +            {
>> +              (*p).set_section_order_index(section_order_index);
>> +              this->set_input_section_order_specified();
>> +         }
>> +         }
>> +    }
>> +}
>
> When calling obj->section_name(), you must lock the object.  See the
> Output_section::Input_section_sort_entry constructor.  As that code
> says, section_name() is a slow operation.  It would be better if we
> could avoid calling it for every single input section if possible.
>
>> +// Call the plugin inspect_unclaimed_object handler.
>> +
>> +inline void
>> +Plugin::inspect_unclaimed_object(unsigned int index)
>> +{
>> +  void* handle =  reinterpret_cast<void*>(index);
>> +  if (this->inspect_unclaimed_object_handler_ != NULL)
>> +      (*this->inspect_unclaimed_object_handler_)(handle);
>> +}
>
> Extra space after '=' sign.
>
> Write the cast as
>  reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(index))
>
> However, I don't see why you are using an index here.  You have an
> Object* pointer.  Why not just use that as the handle?
>
>> +Object*
>> +Plugin_manager::get_unclaimed_object(const void* handle)
>> +{
>> +  unsigned int index
>> +      =  static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle));
>> +  Object* obj = NULL;
>> +
>> +  obj = parameters->options().plugins()->unclaimed_object(index);
>> +
>> +  return obj;
>> +}
>
> Extra space after '=' in index, but as I say I don't see why this
> function is needed at all.
>
>> +// Get the name of the specified section in the object corresponding
>> +// to the handle.  This plugin interface can only be called in the
>> +// inspect_unclaimed_object handler of the plugin.
>> +
>> +static enum ld_plugin_status
>> +get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)
>> +{
>> +  gold_assert(parameters->options().has_plugins());
>> +
>> +  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
>> +    return LDPS_ERR;
>> +
>> +  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
>> +
>> +  if (obj == NULL)
>> +    return LDPS_BAD_HANDLE;
>> +
>> +  const char* section_name = obj->section_name(shndx).c_str();
>> +  *section_name_ptr = (char*)malloc(strlen(section_name) + 1);
>> +  strcpy(*section_name_ptr, section_name);
>> +  return LDPS_OK;
>> +}
>
> *section_name_ptr = static_cast<char*>(malloc(strlen(section_name) + 1));
>
>> +// Get the contents of the specified section in the object corresponding
>> +// to the handle.  This plugin interface can only be called in the
>> +// inspect_unclaimed_object handler of the plugin.
>> +
>> +static enum ld_plugin_status
>> +get_section_contents(void* handle, unsigned int shndx,
>> +                     unsigned char** section_contents_ptr,
>> +                  unsigned int* len)
>> +{
>> +  gold_assert(parameters->options().has_plugins());
>> +
>> +  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
>> +    return LDPS_ERR;
>> +
>> +  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
>> +
>> +  if (obj == NULL)
>> +    return LDPS_BAD_HANDLE;
>> +
>> +  section_size_type plen;
>> +  const unsigned char* section_contents = obj->section_contents(shndx, &plen,
>> +                                                                false);
>> +  *section_contents_ptr = (unsigned char*)malloc(plen);
>> +  memcpy(*section_contents_ptr, section_contents, plen);
>> +  *len = plen;
>> +  return LDPS_OK;
>> +}
>
> If we expect plugins to actually use this, I think a better interface
> would be to return a pointer to the data rather than to copy the entire
> section contents.  We could say that the pointer returned would be valid
> until the inspect_unclaimed_object_handler returns.  The plugin could
> copy the section contents itself if it needs it longer than that.
>
>> +// Specify the ordering of sections in the final layout in a file. This
>> +// does what the linker option --section-ordering-file does.
>> +
>> +static enum ld_plugin_status
>> +read_layout_from_file(const char* filename)
>> +{
>> +  gold_assert(parameters->options().has_plugins());
>> +  Layout* layout = parameters->options().plugins()->layout();
>> +  layout->read_layout_from_file(filename);
>> +  layout->update_layout_of_sections();
>> +  return LDPS_OK;
>> +}
>
> This is a strange interface.  We have a plugin that has assembled all
> the information it needs in memory.  Now we are saying that it should
> write it out to a file, and then ask the linker to read that file.  That
> does not make sense to me.  All that the file contains is a sequence of
> strings.  Why not just have an interface which we can pass strings to?
> Either an array of strings, or call the interface once per string,
> whatever is most convenient.
>
>> +  // The list of unclaimed objects.  The the index of an item in this
>> +  // in this list serves as the "handle" that we pass to the plugins
>> +  // in inspect_unclaimed_object_handler.
>> +  Unclaimed_object_list unclaimed_objects_;
>
> If you use an Object* as the handle, I don't think you need this list at
> all.
>
>> Index: plugin-api.h
>
> Note that this file lives in the gcc repository too.
>
>> +/* The plugin library's "observe file" handler.  */
>> +
>> +typedef
>> +enum ld_plugin_status
>> +(*ld_plugin_inspect_unclaimed_object_handler) (void *);
>
> I think it would be useful to use a typedef here, to lessen the change
> of confusion between the two different kinds of handles.  E.g.,
>
> typedef void *unclaimed_object_handle;
>
> Then use unclaimed_object_handle where appropriate.
>
>> +/* The linker's interface for registering the "observe file" handler.  */
>
> s/observe/inspect/.
>
>> +/* The linker's interface for retrieving the number of sections in an object.
>> +   The handle is obtained in the inspect_unclaimed_object_handler.  This
>> +   interface should only be invoked in the inspect_unclaimed_object_handler. */
>> +
>> +typedef
>> +enum ld_plugin_status
>> +(*ld_plugin_get_section_count) (const void* handle, unsigned int* count);
>
> I think this should be named get_input_section_count.
>
> The comment should say that the function sets *COUNT.
>
>> +
>> +/* The linker's interface for retrieving the section type of a specific
>> +   section in an object.  The handle is obtained in the
>> +   inspect_unclaimed_object_handler.  This interface should only be
>> +   invoked in the inspect_unclaimed_object_handler. */
>> +
>> +typedef
>> +enum ld_plugin_status
>> +(*ld_plugin_get_section_type) (void* handle, unsigned int shndx,
>> +                               unsigned int* type);
>
> I think this should be named get_input_section_type.
>
> The comment should say that the function sets *TYPE to an ELF SHT_xxx
> value.
>
>> +/* The linker's interface for retrieving the name of specific section in
>> +   an object. The handle is obtained in the inspect_unclaimed_object_handler.
>> +   This interface should only be invoked in the
>> +   inspect_unclaimed_object_handler. */
>> +
>> +typedef
>> +enum ld_plugin_status
>> +(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
>> +                               char** section_name_ptr);
>
> I think this should be named get_input_section_name.
>
> The command needs to say that the function sets *section_name_ptr to a
> null-terminated buffer allocated by malloc.
>
>> +/* The linker's interface for retrieving the contents of a specific section
>> +   in an object.  The handle is obtained in the
>> +   inspect_unclaimed_object_handler.  This interface should only be invoked
>> +   in the inspect_unclaimed_object_handler. */
>> +
>> +typedef
>> +enum ld_plugin_status
>> +(*ld_plugin_get_section_contents) (void* handle, unsigned int shndx,
>> +                                   unsigned char** section_contents,
>> +                                   unsigned int* len);
>
> I think this should be named get_input_section_contents.
>
> As noted above, I think we should return a pointer to a memory buffer
> that is valid until inspect_unclaimed_object_handle returns.
>
>
>> +/* The linker's interface for specifying the desired order of sections
>> +   through a file.  */
>> +
>> +typedef
>> +enum ld_plugin_status
>> +(*ld_plugin_read_layout_from_file) (const char* filename);
>> +
>> +/* The linker's interface for specifying that reordering of sections is
>> +   desired.  */
>> +
>> +typedef
>> +enum ld_plugin_status
>> +(*ld_plugin_allow_section_ordering) (void);
>
> The comments need to say something about why both hooks are needed, and
> when they may be called.
>
> Ian
>

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

Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.197
diff -u -u -p -r1.197 layout.cc
--- layout.cc	25 May 2011 00:17:46 -0000	1.197
+++ layout.cc	4 Jun 2011 00:26:16 -0000
@@ -386,11 +386,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_()
 {
@@ -2063,7 +2066,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()
@@ -2079,6 +2082,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: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.91
diff -u -u -p -r1.91 layout.h
--- layout.h	24 May 2011 21:41:10 -0000	1.91
+++ layout.h	4 Jun 2011 00:26:16 -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 section_ordering_specified_; }
+
+  void
+  set_section_ordering_specified()
+  { 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();
 
@@ -1224,6 +1234,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: main.cc
===================================================================
RCS file: /cvs/src/src/gold/main.cc,v
retrieving revision 1.43
diff -u -u -p -r1.43 main.cc
--- main.cc	12 Apr 2011 00:44:48 -0000	1.43
+++ main.cc	4 Jun 2011 00:26:16 -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: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.148
diff -u -u -p -r1.148 output.cc
--- output.cc	2 Jun 2011 13:43:21 -0000	1.148
+++ output.cc	4 Jun 2011 00:26:16 -0000
@@ -2291,7 +2291,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;
@@ -2330,10 +2330,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));
@@ -2414,7 +2414,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);
@@ -3266,6 +3266,39 @@ 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(
+  std::map<Section_id, unsigned int>& 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();
+	  std::map<Section_id, unsigned int>::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
@@ -3308,7 +3341,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: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.124
diff -u -u -p -r1.124 output.h
--- output.h	25 May 2011 00:17:46 -0000	1.124
+++ output.h	4 Jun 2011 00:26:16 -0000
@@ -2665,6 +2665,9 @@ class Output_section : public Output_dat
   flags() const
   { return this->flags_; }
 
+  void
+  update_section_layout(std::map<Section_id, unsigned int>& order_map);
+
   // Update the output section flags based on input section flags.
   void
   update_flags_for_input_section(elfcpp::Elf_Xword flags);
Index: plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.47
diff -u -u -p -r1.47 plugin.cc
--- plugin.cc	25 May 2011 00:17:47 -0000	1.47
+++ plugin.cc	4 Jun 2011 00:26:16 -0000
@@ -57,6 +57,10 @@ static enum ld_plugin_status
 register_claim_file(ld_plugin_claim_file_handler handler);
 
 static enum ld_plugin_status
+register_inspect_unclaimed_object(
+    ld_plugin_inspect_unclaimed_object_handler handler);
+
+static enum ld_plugin_status
 register_all_symbols_read(ld_plugin_all_symbols_read_handler handler);
 
 static enum ld_plugin_status
@@ -89,6 +93,30 @@ 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 unclaimed_object_handle handle,
+                        unsigned int* count);
+
+static enum ld_plugin_status
+get_input_section_type(unclaimed_object_handle handle, unsigned int shndx,
+                       unsigned int* type);
+
+static enum ld_plugin_status
+get_input_section_name(unclaimed_object_handle handle, unsigned int shndx,
+                       char** section_name_ptr);
+
+static enum ld_plugin_status
+get_input_section_contents(unclaimed_object_handle handle, unsigned int shndx,
+                           const unsigned char** section_contents,
+		           unsigned int* len);
+
+static enum ld_plugin_status
+update_section_order(void **handles, unsigned int *shndx,
+		     unsigned int num_sections);
+
+static enum ld_plugin_status
+allow_section_ordering();
+
 };
 
 #endif // ENABLE_PLUGINS
@@ -133,7 +161,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 = 24;
+
   int tv_size = this->args_.size() + tv_fixed_size;
   ld_plugin_tv* tv = new ld_plugin_tv[tv_size];
 
@@ -176,6 +205,11 @@ Plugin::load()
   tv[i].tv_u.tv_register_claim_file = register_claim_file;
 
   ++i;
+  tv[i].tv_tag = LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK;
+  tv[i].tv_u.tv_register_inspect_unclaimed_object
+    = register_inspect_unclaimed_object;
+
+  ++i;
   tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK;
   tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read;
 
@@ -216,6 +250,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;
 
@@ -244,6 +302,17 @@ Plugin::claim_file(struct ld_plugin_inpu
   return false;
 }
 
+// Call the plugin inspect_unclaimed_object handler.
+
+inline void
+Plugin::inspect_unclaimed_object(unsigned int index)
+{
+  unclaimed_object_handle handle
+      = reinterpret_cast<unclaimed_object_handle>(index);
+  if (this->inspect_unclaimed_object_handler_ != NULL)
+      (*this->inspect_unclaimed_object_handler_)(handle);
+}
+
 // Call the all-symbols-read handler.
 
 inline void
@@ -326,8 +395,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_)
@@ -372,6 +442,27 @@ Plugin_manager::claim_file(Input_file* i
   return NULL;
 }
 
+// Call the plugin inspect_unclaimed_object handlers to allow them to inspect
+// the unclaimed object. Pass the handle of the object which is the index
+// into the vector containing the unclaimed objects.
+
+void
+Plugin_manager::inspect_unclaimed_object(Object* obj)
+{
+  unsigned int index;
+  index = this->unclaimed_objects_.size();
+  this->unclaimed_objects_.push_back(obj);
+
+  this->in_inspect_unclaimed_object_handler_ = true;
+
+  for (this->current_ = this->plugins_.begin();
+       this->current_ != this->plugins_.end();
+       ++this->current_)
+    (*this->current_)->inspect_unclaimed_object(index);
+
+  this->in_inspect_unclaimed_object_handler_ = false;
+}
+
 // Save an archive.  This is used so that a plugin can add a file
 // which refers to a symbol which was not previously referenced.  In
 // that case we want to pretend that the symbol was referenced before,
@@ -402,7 +493,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 +502,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;
@@ -642,6 +732,21 @@ Plugin_manager::release_input_file(unsig
   return LDPS_OK;
 }
 
+// Get the object from the list of unclaimed objects with
+// index specified in handle.
+
+Object*
+Plugin_manager::get_unclaimed_object(unclaimed_object_handle handle)
+{
+  unsigned int index
+      = static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle));
+  Object* obj = NULL;
+
+  obj = parameters->options().plugins()->unclaimed_object(index);
+
+  return obj;
+}
+
 ld_plugin_status
 Plugin_manager::get_view(unsigned int handle, const void **viewp)
 {
@@ -1226,7 +1331,6 @@ Plugin_hook::run(Workqueue* workqueue)
                                              this,
                                              this->input_objects_,
                                              this->symtab_,
-                                             this->layout_,
                                              this->dirpath_,
                                              this->mapfile_,
                                              &this->this_blocker_);
@@ -1248,6 +1352,18 @@ register_claim_file(ld_plugin_claim_file
   return LDPS_OK;
 }
 
+//Register a inspect_unclaimed_object handler.
+
+static enum ld_plugin_status
+register_inspect_unclaimed_object
+  (ld_plugin_inspect_unclaimed_object_handler handler)
+{
+  gold_assert(parameters->options().has_plugins());
+  parameters->options().plugins()->set_inspect_unclaimed_object_handler(
+      handler);
+  return LDPS_OK;
+}
+
 // Register an all-symbols-read handler.
 
 static enum ld_plugin_status
@@ -1384,6 +1500,145 @@ 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 inspect_unclaimed_object
+// handler of the plugin.
+
+static enum ld_plugin_status
+get_input_section_count(const unclaimed_object_handle handle,
+                        unsigned int* count)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  *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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_input_section_type(unclaimed_object_handle handle,
+                       unsigned int shndx,
+                       unsigned int* type)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  *type = obj->section_type(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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_input_section_name(unclaimed_object_handle handle,
+                       unsigned int shndx,
+                       char** section_name_ptr)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  const char* section_name = obj->section_name(shndx).c_str();
+  *section_name_ptr = static_cast<char*>(malloc(strlen(section_name) + 1));
+  strcpy(*section_name_ptr, section_name);
+  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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_input_section_contents(unclaimed_object_handle handle, unsigned int shndx,
+                     	   const unsigned char** section_contents_ptr,
+		           unsigned int* len)
+{
+  gold_assert(parameters->options().has_plugins());
+
+  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+    return LDPS_ERR;
+
+  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+  if (obj == NULL)
+    return LDPS_BAD_HANDLE;
+
+  section_size_type plen;
+  *section_contents_ptr
+      = obj->section_contents(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(unclaimed_object_handle* handles, unsigned int* shndx,
+		     unsigned int num_sections)
+{
+  gold_assert(parameters->options().has_plugins());
+  gold_assert(handles && shndx && num_sections);
+
+  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(handles[i]);
+      unsigned int indx = shndx[i];
+      Section_id secn_id(obj, indx);
+      order_map[secn_id] = i + 1;
+    }
+
+  Layout* layout = parameters->options().plugins()->layout();
+  
+  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: plugin.h
===================================================================
RCS file: /cvs/src/src/gold/plugin.h,v
retrieving revision 1.19
diff -u -u -p -r1.19 plugin.h
--- plugin.h	12 Apr 2011 00:44:48 -0000	1.19
+++ plugin.h	4 Jun 2011 00:26:16 -0000
@@ -58,6 +58,7 @@ class Plugin
       filename_(filename),
       args_(),
       claim_file_handler_(NULL),
+      inspect_unclaimed_object_handler_(NULL),
       all_symbols_read_handler_(NULL),
       cleanup_handler_(NULL),
       cleanup_done_(false)
@@ -74,6 +75,10 @@ class Plugin
   bool
   claim_file(struct ld_plugin_input_file* plugin_input_file);
 
+  // Call the inspect_unclaimed_object handler.
+  void
+  inspect_unclaimed_object(unsigned int index);
+
   // Call the all-symbols-read handler.
   void
   all_symbols_read();
@@ -87,6 +92,12 @@ class Plugin
   set_claim_file_handler(ld_plugin_claim_file_handler handler)
   { this->claim_file_handler_ = handler; }
 
+  // Register a inspect_unclaimed_object handler.
+  void
+  set_inspect_unclaimed_object_handler(
+      ld_plugin_inspect_unclaimed_object_handler handler)
+  { this->inspect_unclaimed_object_handler_ = handler; }
+
   // Register an all-symbols-read handler.
   void
   set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
@@ -116,6 +127,7 @@ class Plugin
   std::vector<std::string> args_;
   // The plugin's event handlers.
   ld_plugin_claim_file_handler claim_file_handler_;
+  ld_plugin_inspect_unclaimed_object_handler inspect_unclaimed_object_handler_;
   ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
   ld_plugin_cleanup_handler cleanup_handler_;
   // TRUE if the cleanup handlers have been called.
@@ -128,9 +140,11 @@ class Plugin_manager
 {
  public:
   Plugin_manager(const General_options& options)
-    : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
+    : plugins_(), objects_(), unclaimed_objects_(),
+      deferred_layout_objects_(), input_file_(NULL),
       plugin_input_file_(), rescannable_(), undefined_symbols_(),
       any_claimed_(false), in_replacement_phase_(false), any_added_(false),
+      in_inspect_unclaimed_object_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,12 +167,26 @@ 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);
 
+  // Call the plugin inspect_unclaimed_object handlers to allow them
+  // to inspect the file.
+  void
+  inspect_unclaimed_object(Object* obj);
+
+  Object*
+  get_unclaimed_object(unclaimed_object_handle handle);
+
+  // True if the inspect_unclaimed_object handler of the plugins are being
+  // called.
+  bool
+  in_inspect_unclaimed_object_handler()
+  { return in_inspect_unclaimed_object_handler_; }
+
   // Let the plugin manager save an archive for later rescanning.
   // This takes ownership of the Archive pointer.
   void
@@ -173,7 +201,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
@@ -197,6 +225,15 @@ class Plugin_manager
     (*this->current_)->set_claim_file_handler(handler);
   }
 
+  // Register a inspect_unclaimed_object handler.
+  void
+  set_inspect_unclaimed_object_handler(
+      ld_plugin_inspect_unclaimed_object_handler handler)
+  {
+    gold_assert(this->current_ != plugins_.end());
+    (*this->current_)->set_inspect_unclaimed_object_handler(handler);
+  }
+
   // Register an all-symbols-read handler.
   void
   set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
@@ -227,6 +264,15 @@ class Plugin_manager
     return this->objects_[handle];
   }
 
+  // Return the unclaimed object associated with the given HANDLE.
+  Object*
+  unclaimed_object(unsigned int handle) const
+  {
+    if (handle >= this->unclaimed_objects_.size())
+      return NULL;
+    return this->unclaimed_objects_[handle];
+  }
+
   // Return TRUE if any input files have been claimed by a plugin
   // and we are still in the initial input phase.
   bool
@@ -265,6 +311,14 @@ class Plugin_manager
   in_replacement_phase() const
   { return this->in_replacement_phase_; }
 
+  Input_objects*
+  input_objects() const
+  { return input_objects_; }
+
+  Layout*
+  layout()
+  { return layout_; }
+
  private:
   Plugin_manager(const Plugin_manager&);
   Plugin_manager& operator=(const Plugin_manager&);
@@ -294,6 +348,7 @@ class Plugin_manager
 
   typedef std::list<Plugin*> Plugin_list;
   typedef std::vector<Pluginobj*> Object_list;
+  typedef std::vector<Object*> Unclaimed_object_list;
   typedef std::vector<Relobj*> Deferred_layout_list;
   typedef std::vector<Rescannable> Rescannable_list;
   typedef std::vector<Symbol*> Undefined_symbol_list;
@@ -315,6 +370,11 @@ class Plugin_manager
   // serves as the "handle" that we pass to the plugins.
   Object_list objects_;
 
+  // The list of unclaimed objects.  The the index of an item in this
+  // in this list serves as the "handle" that we pass to the plugins
+  // in inspect_unclaimed_object_handler.
+  Unclaimed_object_list unclaimed_objects_;
+
   // The list of regular objects whose layout has been deferred.
   Deferred_layout_list deferred_layout_objects_;
 
@@ -340,6 +400,10 @@ class Plugin_manager
   // Whether any input files or libraries were added by a plugin.
   bool any_added_;
 
+  // Set to true when the inspect_unclaimed_object_handler of the plugins are being
+  // called.
+  bool in_inspect_unclaimed_object_handler_;
+
   const General_options& options_;
   Workqueue* workqueue_;
   Task* task_;
Index: readsyms.cc
===================================================================
RCS file: /cvs/src/src/gold/readsyms.cc,v
retrieving revision 1.49
diff -u -u -p -r1.49 readsyms.cc
--- readsyms.cc	12 Apr 2011 00:44:48 -0000	1.49
+++ readsyms.cc	4 Jun 2011 00:26:16 -0000
@@ -381,6 +381,10 @@ Read_symbols::do_read_symbols(Workqueue*
 	  return false;
 	}
 
+      // Allow the plugins to inspect the unclaimed object now.
+      if (parameters->options().has_plugins())
+        parameters->options().plugins()->inspect_unclaimed_object(obj);
+
       Read_symbols_data* sd = new Read_symbols_data;
       obj->read_symbols(sd);
 
cvs diff: Diffing po
cvs diff: Diffing testsuite
Index: 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
--- testsuite/plugin_test.c	9 Nov 2009 16:11:34 -0000	1.4
+++ testsuite/plugin_test.c	4 Jun 2011 00:26:17 -0000
@@ -52,6 +52,8 @@ static struct claimed_file* first_claime
 static struct claimed_file* last_claimed_file = NULL;
 
 static ld_plugin_register_claim_file register_claim_file_hook = NULL;
+static ld_plugin_register_inspect_unclaimed_object
+  register_inspect_unclaimed_object_hook = NULL;
 static ld_plugin_register_all_symbols_read register_all_symbols_read_hook = NULL;
 static ld_plugin_register_cleanup register_cleanup_hook = NULL;
 static ld_plugin_add_symbols add_symbols = NULL;
@@ -60,6 +62,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
 
@@ -69,6 +77,7 @@ static int nopts = 0;
 enum ld_plugin_status onload(struct ld_plugin_tv *tv);
 enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
                                       int *claimed);
+enum ld_plugin_status inspect_unclaimed_object_hook(void* handle);
 enum ld_plugin_status all_symbols_read_hook(void);
 enum ld_plugin_status cleanup_hook(void);
 
@@ -101,6 +110,10 @@ onload(struct ld_plugin_tv *tv)
         case LDPT_REGISTER_CLAIM_FILE_HOOK:
           register_claim_file_hook = entry->tv_u.tv_register_claim_file;
           break;
+	case LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK:
+          register_inspect_unclaimed_object_hook
+            = entry->tv_u.tv_register_inspect_unclaimed_object;
+          break;
         case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
           register_all_symbols_read_hook =
             entry->tv_u.tv_register_all_symbols_read;
@@ -126,6 +139,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;
         }
@@ -143,6 +174,13 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if (register_inspect_unclaimed_object_hook == NULL)
+    {
+      fprintf(stderr,
+              "tv_register_inspect_unclaimed_object_hook interface missing\n");
+      return LDPS_ERR;
+    }
+
   if (register_all_symbols_read_hook == NULL)
     {
       fprintf(stderr, "tv_register_all_symbols_read_hook interface missing\n");
@@ -167,6 +205,14 @@ onload(struct ld_plugin_tv *tv)
       return LDPS_ERR;
     }
 
+  if ((*register_inspect_unclaimed_object_hook)
+        (inspect_unclaimed_object_hook) != LDPS_OK)
+    {
+      (*message)(LDPL_ERROR,
+                 "error registering inspect unclaimed object hook");
+      return LDPS_ERR;
+    }
+
   if ((*register_all_symbols_read_hook)(all_symbols_read_hook) != LDPS_OK)
     {
       (*message)(LDPL_ERROR, "error registering all symbols read hook");
@@ -179,10 +225,53 @@ 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;
 }
 
 enum ld_plugin_status
+inspect_unclaimed_object_hook (void* handle)
+{
+  (*message)(LDPL_INFO, "Inspect unclaimed object hook called with handle: %p",
+             handle);
+  return LDPS_OK;
+}
+enum ld_plugin_status
 claim_file_hook (const struct ld_plugin_input_file* file, int* claimed)
 {
   int len;
Index: include/plugin-api.h
===================================================================
RCS file: /cvs/src/src/include/plugin-api.h,v
retrieving revision 1.14
diff -u -r1.14 plugin-api.h
--- include/plugin-api.h	23 Mar 2011 14:09:48 -0000	1.14
+++ include/plugin-api.h	4 Jun 2011 00:41:16 -0000
@@ -157,6 +157,15 @@
 (*ld_plugin_claim_file_handler) (
   const struct ld_plugin_input_file *file, int *claimed);
 
+/* The plugin library's unclaimed object handle. */
+typedef void *unclaimed_object_handle;
+
+/* The plugin library's "inspect unclaimed object" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_inspect_unclaimed_object_handler) (unclaimed_object_handle);
+
 /* The plugin library's "all symbols read" handler.  */
 
 typedef
@@ -175,6 +184,14 @@
 enum ld_plugin_status
 (*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler);
 
+/* The linker's interface for registering the "inspect unclaimed object"
+   handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_inspect_unclaimed_object)
+  (ld_plugin_inspect_unclaimed_object_handler handler);
+
 /* The linker's interface for registering the "all symbols read" handler.  */
 
 typedef
@@ -244,6 +261,78 @@
 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 inspect_unclaimed_object_handler.  This
+   interface should only be invoked in the inspect_unclaimed_object_handler.
+   This function sets *COUNT to the number of sections in the unclaimed
+   object. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_input_section_count) (unclaimed_object_handle handle,
+                                      unsigned int* count);
+
+/* The linker's interface for retrieving the section type of a specific
+   section in an object.  The handle is obtained in the
+   inspect_unclaimed_object_handler.  This interface should only be
+   invoked in the inspect_unclaimed_object_handler.  This function sets
+   *TYPE to an ELF SHT_xxx value .*/
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_input_section_type) (unclaimed_object_handle handle,
+                                     unsigned int shndx,
+                                     unsigned int* type);
+
+/* The linker's interface for retrieving the name of specific section in
+   an object. The handle is obtained in the inspect_unclaimed_object_handler.
+   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.*/
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_input_section_name) (unclaimed_object_handle handle,
+                                     unsigned int shndx,
+                                     char** section_name_ptr);
+
+/* The linker's interface for retrieving the contents of a specific section
+   in an object.  The handle is obtained in the
+   inspect_unclaimed_object_handler.  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 with the size
+   of the buffer. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_input_section_contents) (unclaimed_object_handle handle,
+                                         unsigned int shndx,
+                                         const unsigned char**
+                                             section_contents,
+                                         unsigned int* len);
+
+/* The linker's interface for specifying the desired order of sections.
+   The sections should be specifed as (handle, shndx) pairs using the arrays
+   HANDLES and SHNDX 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) (unclaimed_object_handle* handles,
+				   unsigned int* shndx,
+				   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,
@@ -262,6 +351,7 @@
   LDPT_LINKER_OUTPUT,
   LDPT_OPTION,
   LDPT_REGISTER_CLAIM_FILE_HOOK,
+  LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK,
   LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
   LDPT_REGISTER_CLEANUP_HOOK,
   LDPT_ADD_SYMBOLS,
@@ -274,7 +364,13 @@
   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.  */
@@ -287,6 +383,8 @@
     int tv_val;
     const char *tv_string;
     ld_plugin_register_claim_file tv_register_claim_file;
+    ld_plugin_register_inspect_unclaimed_object
+      tv_register_inspect_unclaimed_object;
     ld_plugin_register_all_symbols_read tv_register_all_symbols_read;
     ld_plugin_register_cleanup tv_register_cleanup;
     ld_plugin_add_symbols tv_add_symbols;
@@ -298,6 +396,12 @@
     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;
 };
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-06-04  0:46           ` Sriraman Tallam
@ 2011-06-24 22:25             ` Cary Coutant
       [not found]               ` <BANLkTimKuKEGo8VSQqMFun_EfCj350R9tEpMejD8mmBrOudyiA@mail.gmail.com>
  0 siblings, 1 reply; 19+ messages in thread
From: Cary Coutant @ 2011-06-24 22:25 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: Ian Lance Taylor, binutils

>  Finally, I managed to make all these changes and I have attached the
> new patch. Thanks.

Here are my comments. This looks good to me (with changes as noted),
but you still need Ian's approval.

Thanks, and sorry for the delay!

BTW, it looks like you did the diff for plugin-api.h separately and
concatenated it to the rest of the patch. It would probably have been
better to do the diff from one level up, so that someone reading your
email can apply the patch more easily.

-cary


> Index: layout.cc
> ===================================================================
> RCS file: /cvs/src/src/gold/layout.cc,v
> retrieving revision 1.197
> diff -u -u -p -r1.197 layout.cc
> --- layout.cc	25 May 2011 00:17:46 -0000	1.197
> +++ layout.cc	4 Jun 2011 00:26:16 -0000
> @@ -386,11 +386,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_()
>  {
> @@ -2063,7 +2066,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()
> @@ -2079,6 +2082,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: layout.h
> ===================================================================
> RCS file: /cvs/src/src/gold/layout.h,v
> retrieving revision 1.91
> diff -u -u -p -r1.91 layout.h
> --- layout.h	24 May 2011 21:41:10 -0000	1.91
> +++ layout.h	4 Jun 2011 00:26:16 -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 section_ordering_specified_; }

Should be "this->section_ordering_specified_".

> +
> +  void
> +  set_section_ordering_specified()
> +  { section_ordering_specified_ = true; }

Likewise.

> +
>    // 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();
>
> @@ -1224,6 +1234,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: main.cc
> ===================================================================
> RCS file: /cvs/src/src/gold/main.cc,v
> retrieving revision 1.43
> diff -u -u -p -r1.43 main.cc
> --- main.cc	12 Apr 2011 00:44:48 -0000	1.43
> +++ main.cc	4 Jun 2011 00:26:16 -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: output.cc
> ===================================================================
> RCS file: /cvs/src/src/gold/output.cc,v
> retrieving revision 1.148
> diff -u -u -p -r1.148 output.cc
> --- output.cc	2 Jun 2011 13:43:21 -0000	1.148
> +++ output.cc	4 Jun 2011 00:26:16 -0000
> @@ -2291,7 +2291,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;
> @@ -2330,10 +2330,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));
> @@ -2414,7 +2414,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);
> @@ -3266,6 +3266,39 @@ 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(
> +  std::map<Section_id, unsigned int>& order_map)

Make the parameter const.  By convention, we don't use non-const references
as parameters.

A typedef for std::map<Section_id, unsigned int> might be nice.

> +{
> +  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());
> +	

Trailing white space.

> +	  unsigned int shndx = (*p).shndx();
> +	  std::map<Section_id, unsigned int>::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
> @@ -3308,7 +3341,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: output.h
> ===================================================================
> RCS file: /cvs/src/src/gold/output.h,v
> retrieving revision 1.124
> diff -u -u -p -r1.124 output.h
> --- output.h	25 May 2011 00:17:46 -0000	1.124
> +++ output.h	4 Jun 2011 00:26:16 -0000
> @@ -2665,6 +2665,9 @@ class Output_section : public Output_dat
>    flags() const
>    { return this->flags_; }
>
> +  void
> +  update_section_layout(std::map<Section_id, unsigned int>& order_map);
> +
>    // Update the output section flags based on input section flags.
>    void
>    update_flags_for_input_section(elfcpp::Elf_Xword flags);
> Index: plugin.cc
> ===================================================================
> RCS file: /cvs/src/src/gold/plugin.cc,v
> retrieving revision 1.47
> diff -u -u -p -r1.47 plugin.cc
> --- plugin.cc	25 May 2011 00:17:47 -0000	1.47
> +++ plugin.cc	4 Jun 2011 00:26:16 -0000
> @@ -57,6 +57,10 @@ static enum ld_plugin_status
>  register_claim_file(ld_plugin_claim_file_handler handler);
>
>  static enum ld_plugin_status
> +register_inspect_unclaimed_object(
> +    ld_plugin_inspect_unclaimed_object_handler handler);
> +
> +static enum ld_plugin_status
>  register_all_symbols_read(ld_plugin_all_symbols_read_handler handler);
>
>  static enum ld_plugin_status
> @@ -89,6 +93,30 @@ 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 unclaimed_object_handle handle,
> +                        unsigned int* count);

For extern "C" interfaces, use the C style: "unsigned int *count" (here and
the next 4 declarations).

> +
> +static enum ld_plugin_status
> +get_input_section_type(unclaimed_object_handle handle, unsigned int shndx,
> +                       unsigned int* type);
> +
> +static enum ld_plugin_status
> +get_input_section_name(unclaimed_object_handle handle, unsigned int shndx,
> +                       char** section_name_ptr);
> +
> +static enum ld_plugin_status
> +get_input_section_contents(unclaimed_object_handle handle, unsigned int shndx,
> +                           const unsigned char** section_contents,
> +		           unsigned int* len);
> +
> +static enum ld_plugin_status
> +update_section_order(void **handles, unsigned int *shndx,
> +		     unsigned int num_sections);
> +
> +static enum ld_plugin_status
> +allow_section_ordering();
> +
>  };
>
>  #endif // ENABLE_PLUGINS
> @@ -133,7 +161,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 = 24;
> +
>    int tv_size = this->args_.size() + tv_fixed_size;
>    ld_plugin_tv* tv = new ld_plugin_tv[tv_size];
>
> @@ -176,6 +205,11 @@ Plugin::load()
>    tv[i].tv_u.tv_register_claim_file = register_claim_file;
>
>    ++i;
> +  tv[i].tv_tag = LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK;
> +  tv[i].tv_u.tv_register_inspect_unclaimed_object
> +    = register_inspect_unclaimed_object;
> +
> +  ++i;
>    tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK;
>    tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read;
>
> @@ -216,6 +250,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;
>
> @@ -244,6 +302,17 @@ Plugin::claim_file(struct ld_plugin_inpu
>    return false;
>  }
>
> +// Call the plugin inspect_unclaimed_object handler.
> +
> +inline void
> +Plugin::inspect_unclaimed_object(unsigned int index)
> +{
> +  unclaimed_object_handle handle
> +      = reinterpret_cast<unclaimed_object_handle>(index);
> +  if (this->inspect_unclaimed_object_handler_ != NULL)
> +      (*this->inspect_unclaimed_object_handler_)(handle);
> +}
> +
>  // Call the all-symbols-read handler.
>
>  inline void
> @@ -326,8 +395,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_)
> @@ -372,6 +442,27 @@ Plugin_manager::claim_file(Input_file* i
>    return NULL;
>  }
>
> +// Call the plugin inspect_unclaimed_object handlers to allow them to inspect
> +// the unclaimed object. Pass the handle of the object which is the index
> +// into the vector containing the unclaimed objects.
> +
> +void
> +Plugin_manager::inspect_unclaimed_object(Object* obj)
> +{
> +  unsigned int index;
> +  index = this->unclaimed_objects_.size();

How about converting index to an unclaimed_object_handle here, and
passing that to Plugin::inspect_unclaimed_object()?

> +  this->unclaimed_objects_.push_back(obj);
> +
> +  this->in_inspect_unclaimed_object_handler_ = true;
> +
> +  for (this->current_ = this->plugins_.begin();
> +       this->current_ != this->plugins_.end();
> +       ++this->current_)
> +    (*this->current_)->inspect_unclaimed_object(index);
> +
> +  this->in_inspect_unclaimed_object_handler_ = false;
> +}
> +
>  // Save an archive.  This is used so that a plugin can add a file
>  // which refers to a symbol which was not previously referenced.  In
>  // that case we want to pretend that the symbol was referenced before,
> @@ -402,7 +493,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 +502,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;
> @@ -642,6 +732,21 @@ Plugin_manager::release_input_file(unsig
>    return LDPS_OK;
>  }
>
> +// Get the object from the list of unclaimed objects with
> +// index specified in handle.
> +
> +Object*
> +Plugin_manager::get_unclaimed_object(unclaimed_object_handle handle)
> +{
> +  unsigned int index
> +      = static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle));
> +  Object* obj = NULL;
> +
> +  obj = parameters->options().plugins()->unclaimed_object(index);
> +
> +  return obj;
> +}

This can be simplified to:

Object*
Plugin_manager::get_unclaimed_object(unclaimed_object_handle handle)
  {
    unsigned int index =
	static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle));
    return this->unclaimed_object(index);
  }

> +
>  ld_plugin_status
>  Plugin_manager::get_view(unsigned int handle, const void **viewp)
>  {
> @@ -1226,7 +1331,6 @@ Plugin_hook::run(Workqueue* workqueue)
>                                               this,
>                                               this->input_objects_,
>                                               this->symtab_,
> -                                             this->layout_,
>                                               this->dirpath_,
>                                               this->mapfile_,
>                                               &this->this_blocker_);
> @@ -1248,6 +1352,18 @@ register_claim_file(ld_plugin_claim_file
>    return LDPS_OK;
>  }
>
> +//Register a inspect_unclaimed_object handler.
> +
> +static enum ld_plugin_status
> +register_inspect_unclaimed_object
> +  (ld_plugin_inspect_unclaimed_object_handler handler)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +  parameters->options().plugins()->set_inspect_unclaimed_object_handler(
> +      handler);
> +  return LDPS_OK;
> +}
> +
>  // Register an all-symbols-read handler.
>
>  static enum ld_plugin_status
> @@ -1384,6 +1500,145 @@ 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 inspect_unclaimed_object
> +// handler of the plugin.
> +
> +static enum ld_plugin_status
> +get_input_section_count(const unclaimed_object_handle handle,
> +                        unsigned int* count)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +
> +  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
> +    return LDPS_ERR;
> +
> +  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
> +
> +  if (obj == NULL)
> +    return LDPS_BAD_HANDLE;
> +
> +  *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
> +// inspect_unclaimed_object handler of the plugin.
> +
> +static enum ld_plugin_status
> +get_input_section_type(unclaimed_object_handle handle,
> +                       unsigned int shndx,
> +                       unsigned int* type)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +
> +  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
> +    return LDPS_ERR;
> +
> +  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
> +
> +  if (obj == NULL)
> +    return LDPS_BAD_HANDLE;
> +
> +  *type = obj->section_type(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
> +// inspect_unclaimed_object handler of the plugin.
> +
> +static enum ld_plugin_status
> +get_input_section_name(unclaimed_object_handle handle,
> +                       unsigned int shndx,
> +                       char** section_name_ptr)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +
> +  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
> +    return LDPS_ERR;
> +
> +  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
> +
> +  if (obj == NULL)
> +    return LDPS_BAD_HANDLE;

I'd suggest asserting "obj->is_locked()" here.

> +
> +  const char* section_name = obj->section_name(shndx).c_str();
> +  *section_name_ptr = static_cast<char*>(malloc(strlen(section_name) + 1));
> +  strcpy(*section_name_ptr, section_name);

Will the plugin free this memory?

> +  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
> +// inspect_unclaimed_object handler of the plugin.
> +
> +static enum ld_plugin_status
> +get_input_section_contents(unclaimed_object_handle handle, unsigned int shndx,
> +                     	   const unsigned char** section_contents_ptr,

Spaces before tab.

> +		           unsigned int* len)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +
> +  if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
> +    return LDPS_ERR;
> +
> +  Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
> +
> +  if (obj == NULL)
> +    return LDPS_BAD_HANDLE;

Assert "obj->is_locked()".

> +
> +  section_size_type plen;
> +  *section_contents_ptr
> +      = obj->section_contents(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(unclaimed_object_handle* handles, unsigned int* shndx,
> +		     unsigned int num_sections)
> +{
> +  gold_assert(parameters->options().has_plugins());
> +  gold_assert(handles && shndx && num_sections);

Use this style for bools only. This should be:

  gold_assert(handles != NULL && shndx != NULL && num_sections > 0);

On further consideration, none of these conditions should trigger an
internal error in gold -- these are API usage errors, and you should
return LDPS_ERR.  If num_sections == 0, I'd be tempted to do nothing
and return LDPS_OK.

I'd suggest changing the name of the parameter "shndx" to "pshndx" or
"shndx_list". (Or, use an array of structs instead of parallel arrays.)

> +
> +  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(handles[i]);
> +      unsigned int indx = shndx[i];
> +      Section_id secn_id(obj, indx);

If you rename "shndx" as suggested above, you can use that name instead
of "indx" here. We use "shndx" throughout gold in this context.

> +      order_map[secn_id] = i + 1;
> +    }
> +
> +  Layout* layout = parameters->options().plugins()->layout();
> +

Trailing white space.

I'd suggest asserting that "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();

I'd suggest asserting that "layout != NULL".

> +  layout->set_section_ordering_specified();
> +  return LDPS_OK;
> +}
> +
>  #endif // ENABLE_PLUGINS
>
>  // Allocate a Pluginobj object of the appropriate size and endianness.
> Index: plugin.h
> ===================================================================
> RCS file: /cvs/src/src/gold/plugin.h,v
> retrieving revision 1.19
> diff -u -u -p -r1.19 plugin.h
> --- plugin.h	12 Apr 2011 00:44:48 -0000	1.19
> +++ plugin.h	4 Jun 2011 00:26:16 -0000
> @@ -58,6 +58,7 @@ class Plugin
>        filename_(filename),
>        args_(),
>        claim_file_handler_(NULL),
> +      inspect_unclaimed_object_handler_(NULL),
>        all_symbols_read_handler_(NULL),
>        cleanup_handler_(NULL),
>        cleanup_done_(false)
> @@ -74,6 +75,10 @@ class Plugin
>    bool
>    claim_file(struct ld_plugin_input_file* plugin_input_file);
>
> +  // Call the inspect_unclaimed_object handler.
> +  void
> +  inspect_unclaimed_object(unsigned int index);
> +
>    // Call the all-symbols-read handler.
>    void
>    all_symbols_read();
> @@ -87,6 +92,12 @@ class Plugin
>    set_claim_file_handler(ld_plugin_claim_file_handler handler)
>    { this->claim_file_handler_ = handler; }
>
> +  // Register a inspect_unclaimed_object handler.
> +  void
> +  set_inspect_unclaimed_object_handler(
> +      ld_plugin_inspect_unclaimed_object_handler handler)
> +  { this->inspect_unclaimed_object_handler_ = handler; }
> +
>    // Register an all-symbols-read handler.
>    void
>    set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
> @@ -116,6 +127,7 @@ class Plugin
>    std::vector<std::string> args_;
>    // The plugin's event handlers.
>    ld_plugin_claim_file_handler claim_file_handler_;
> +  ld_plugin_inspect_unclaimed_object_handler inspect_unclaimed_object_handler_;
>    ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
>    ld_plugin_cleanup_handler cleanup_handler_;
>    // TRUE if the cleanup handlers have been called.
> @@ -128,9 +140,11 @@ class Plugin_manager
>  {
>   public:
>    Plugin_manager(const General_options& options)
> -    : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
> +    : plugins_(), objects_(), unclaimed_objects_(),
> +      deferred_layout_objects_(), input_file_(NULL),
>        plugin_input_file_(), rescannable_(), undefined_symbols_(),
>        any_claimed_(false), in_replacement_phase_(false), any_added_(false),
> +      in_inspect_unclaimed_object_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,12 +167,26 @@ 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);
>
> +  // Call the plugin inspect_unclaimed_object handlers to allow them
> +  // to inspect the file.
> +  void
> +  inspect_unclaimed_object(Object* obj);
> +
> +  Object*
> +  get_unclaimed_object(unclaimed_object_handle handle);
> +
> +  // True if the inspect_unclaimed_object handler of the plugins are being
> +  // called.

s/are/is/

> +  bool
> +  in_inspect_unclaimed_object_handler()
> +  { return in_inspect_unclaimed_object_handler_; }
> +
>    // Let the plugin manager save an archive for later rescanning.
>    // This takes ownership of the Archive pointer.
>    void
> @@ -173,7 +201,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
> @@ -197,6 +225,15 @@ class Plugin_manager
>      (*this->current_)->set_claim_file_handler(handler);
>    }
>
> +  // Register a inspect_unclaimed_object handler.
> +  void
> +  set_inspect_unclaimed_object_handler(
> +      ld_plugin_inspect_unclaimed_object_handler handler)
> +  {
> +    gold_assert(this->current_ != plugins_.end());
> +    (*this->current_)->set_inspect_unclaimed_object_handler(handler);
> +  }
> +
>    // Register an all-symbols-read handler.
>    void
>    set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
> @@ -227,6 +264,15 @@ class Plugin_manager
>      return this->objects_[handle];
>    }
>
> +  // Return the unclaimed object associated with the given HANDLE.
> +  Object*
> +  unclaimed_object(unsigned int handle) const
> +  {
> +    if (handle >= this->unclaimed_objects_.size())
> +      return NULL;
> +    return this->unclaimed_objects_[handle];
> +  }
> +
>    // Return TRUE if any input files have been claimed by a plugin
>    // and we are still in the initial input phase.
>    bool
> @@ -265,6 +311,14 @@ class Plugin_manager
>    in_replacement_phase() const
>    { return this->in_replacement_phase_; }
>
> +  Input_objects*
> +  input_objects() const
> +  { return input_objects_; }

Write "this->input_objects_".

> +
> +  Layout*
> +  layout()
> +  { return layout_; }

Write "this->layout_".

> +
>   private:
>    Plugin_manager(const Plugin_manager&);
>    Plugin_manager& operator=(const Plugin_manager&);
> @@ -294,6 +348,7 @@ class Plugin_manager
>
>    typedef std::list<Plugin*> Plugin_list;
>    typedef std::vector<Pluginobj*> Object_list;
> +  typedef std::vector<Object*> Unclaimed_object_list;
>    typedef std::vector<Relobj*> Deferred_layout_list;
>    typedef std::vector<Rescannable> Rescannable_list;
>    typedef std::vector<Symbol*> Undefined_symbol_list;
> @@ -315,6 +370,11 @@ class Plugin_manager
>    // serves as the "handle" that we pass to the plugins.
>    Object_list objects_;
>
> +  // The list of unclaimed objects.  The the index of an item in this
> +  // in this list serves as the "handle" that we pass to the plugins
> +  // in inspect_unclaimed_object_handler.
> +  Unclaimed_object_list unclaimed_objects_;
> +
>    // The list of regular objects whose layout has been deferred.
>    Deferred_layout_list deferred_layout_objects_;
>
> @@ -340,6 +400,10 @@ class Plugin_manager
>    // Whether any input files or libraries were added by a plugin.
>    bool any_added_;
>
> +  // Set to true when the inspect_unclaimed_object_handler of the plugins are being
> +  // called.
> +  bool in_inspect_unclaimed_object_handler_;
> +
>    const General_options& options_;
>    Workqueue* workqueue_;
>    Task* task_;
> Index: readsyms.cc
> ===================================================================
> RCS file: /cvs/src/src/gold/readsyms.cc,v
> retrieving revision 1.49
> diff -u -u -p -r1.49 readsyms.cc
> --- readsyms.cc	12 Apr 2011 00:44:48 -0000	1.49
> +++ readsyms.cc	4 Jun 2011 00:26:16 -0000
> @@ -381,6 +381,10 @@ Read_symbols::do_read_symbols(Workqueue*
>  	  return false;
>  	}
>
> +      // Allow the plugins to inspect the unclaimed object now.
> +      if (parameters->options().has_plugins())
> +        parameters->options().plugins()->inspect_unclaimed_object(obj);
> +
>        Read_symbols_data* sd = new Read_symbols_data;
>        obj->read_symbols(sd);
>
cvs diff: Diffing po
cvs diff: Diffing testsuite
> Index: 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
> --- testsuite/plugin_test.c	9 Nov 2009 16:11:34 -0000	1.4
> +++ testsuite/plugin_test.c	4 Jun 2011 00:26:17 -0000
> @@ -52,6 +52,8 @@ static struct claimed_file* first_claime
>  static struct claimed_file* last_claimed_file = NULL;
>
>  static ld_plugin_register_claim_file register_claim_file_hook = NULL;
> +static ld_plugin_register_inspect_unclaimed_object
> +  register_inspect_unclaimed_object_hook = NULL;
>  static ld_plugin_register_all_symbols_read register_all_symbols_read_hook = NULL;
>  static ld_plugin_register_cleanup register_cleanup_hook = NULL;
>  static ld_plugin_add_symbols add_symbols = NULL;
> @@ -60,6 +62,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
>
> @@ -69,6 +77,7 @@ static int nopts = 0;
>  enum ld_plugin_status onload(struct ld_plugin_tv *tv);
>  enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
>                                        int *claimed);
> +enum ld_plugin_status inspect_unclaimed_object_hook(void* handle);
>  enum ld_plugin_status all_symbols_read_hook(void);
>  enum ld_plugin_status cleanup_hook(void);
>
> @@ -101,6 +110,10 @@ onload(struct ld_plugin_tv *tv)
>          case LDPT_REGISTER_CLAIM_FILE_HOOK:
>            register_claim_file_hook = entry->tv_u.tv_register_claim_file;
>            break;
> +	case LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK:
> +          register_inspect_unclaimed_object_hook
> +            = entry->tv_u.tv_register_inspect_unclaimed_object;
> +          break;
>          case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
>            register_all_symbols_read_hook =
>              entry->tv_u.tv_register_all_symbols_read;
> @@ -126,6 +139,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;
>          }
> @@ -143,6 +174,13 @@ onload(struct ld_plugin_tv *tv)
>        return LDPS_ERR;
>      }
>
> +  if (register_inspect_unclaimed_object_hook == NULL)
> +    {
> +      fprintf(stderr,
> +              "tv_register_inspect_unclaimed_object_hook interface missing\n");
> +      return LDPS_ERR;
> +    }
> +
>    if (register_all_symbols_read_hook == NULL)
>      {
>        fprintf(stderr, "tv_register_all_symbols_read_hook interface missing\n");
> @@ -167,6 +205,14 @@ onload(struct ld_plugin_tv *tv)
>        return LDPS_ERR;
>      }
>
> +  if ((*register_inspect_unclaimed_object_hook)
> +        (inspect_unclaimed_object_hook) != LDPS_OK)
> +    {
> +      (*message)(LDPL_ERROR,
> +                 "error registering inspect unclaimed object hook");
> +      return LDPS_ERR;
> +    }
> +
>    if ((*register_all_symbols_read_hook)(all_symbols_read_hook) != LDPS_OK)
>      {
>        (*message)(LDPL_ERROR, "error registering all symbols read hook");
> @@ -179,10 +225,53 @@ 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;
>  }
>
>  enum ld_plugin_status
> +inspect_unclaimed_object_hook (void* handle)
> +{
> +  (*message)(LDPL_INFO, "Inspect unclaimed object hook called with handle: %p",
> +             handle);
> +  return LDPS_OK;
> +}
> +enum ld_plugin_status

Need a blank line here.

>  claim_file_hook (const struct ld_plugin_input_file* file, int* claimed)
>  {
>    int len;
> Index: include/plugin-api.h
> ===================================================================
> RCS file: /cvs/src/src/include/plugin-api.h,v
> retrieving revision 1.14
> diff -u -r1.14 plugin-api.h
> --- include/plugin-api.h	23 Mar 2011 14:09:48 -0000	1.14
> +++ include/plugin-api.h	4 Jun 2011 00:41:16 -0000
> @@ -157,6 +157,15 @@
>  (*ld_plugin_claim_file_handler) (
>    const struct ld_plugin_input_file *file, int *claimed);
>
> +/* The plugin library's unclaimed object handle. */
> +typedef void *unclaimed_object_handle;
> +
> +/* The plugin library's "inspect unclaimed object" handler.  */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_inspect_unclaimed_object_handler) (unclaimed_object_handle);
> +
>  /* The plugin library's "all symbols read" handler.  */
>
>  typedef
> @@ -175,6 +184,14 @@
>  enum ld_plugin_status
>  (*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler);
>
> +/* The linker's interface for registering the "inspect unclaimed object"
> +   handler.  */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_register_inspect_unclaimed_object)
> +  (ld_plugin_inspect_unclaimed_object_handler handler);

I think the open paren should be at the end of the previous line,
although I'm not sure if Gnu conventions insist on this.  Still,
it would be consistent with the rest of the file.

> +
>  /* The linker's interface for registering the "all symbols read" handler.  */
>
>  typedef
> @@ -244,6 +261,78 @@
>  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 inspect_unclaimed_object_handler.  This
> +   interface should only be invoked in the inspect_unclaimed_object_handler.
> +   This function sets *COUNT to the number of sections in the unclaimed
> +   object. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_input_section_count) (unclaimed_object_handle handle,
> +                                      unsigned int* count);

Use C-style conventions: "unsigned int *count". (Here and other
cases below.)

> +
> +/* The linker's interface for retrieving the section type of a specific
> +   section in an object.  The handle is obtained in the
> +   inspect_unclaimed_object_handler.  This interface should only be
> +   invoked in the inspect_unclaimed_object_handler.  This function sets
> +   *TYPE to an ELF SHT_xxx value .*/

I think it would read better if you refer to the handler as the "inspect
unclaimed object" handler, like existing references to the "all symbols
read" handler. This would let you wrap lines better, and would sound
better with "the".

> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_input_section_type) (unclaimed_object_handle handle,
> +                                     unsigned int shndx,
> +                                     unsigned int* type);
> +
> +/* The linker's interface for retrieving the name of specific section in
> +   an object. The handle is obtained in the inspect_unclaimed_object_handler.
> +   This interface should only be invoked in the

Trailing white space.

> +   inspect_unclaimed_object_handler.  This function sets *SECTION_NAME_PTR to
> +   a null-terminated buffer allocated by malloc.*/

Need two spaces after ".".  I think you should also say that the plugin
will own the pointer to that buffer, and is responsible for freeing it.

> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_input_section_name) (unclaimed_object_handle handle,
> +                                     unsigned int shndx,
> +                                     char** section_name_ptr);
> +
> +/* The linker's interface for retrieving the contents of a specific section
> +   in an object.  The handle is obtained in the
> +   inspect_unclaimed_object_handler.  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 with the size

s/with/to/

> +   of the buffer. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_input_section_contents) (unclaimed_object_handle handle,
> +                                         unsigned int shndx,
> +                                         const unsigned char**
> +                                             section_contents,
> +                                         unsigned int* len);
> +
> +/* The linker's interface for specifying the desired order of sections.
> +   The sections should be specifed as (handle, shndx) pairs using the arrays
> +   HANDLES and SHNDX 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) (unclaimed_object_handle* handles,
> +				   unsigned int* shndx,
> +				   unsigned int num_sections);

Why use two parallel arrays instead of an array of structs?

> +
> +/* 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,
> @@ -262,6 +351,7 @@
>    LDPT_LINKER_OUTPUT,
>    LDPT_OPTION,
>    LDPT_REGISTER_CLAIM_FILE_HOOK,
> +  LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK,

Adding this in the middle changes the API numbering, which would break
ABI compatibility with older plugins.  Please move this to follow all the
original APIs.

>    LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
>    LDPT_REGISTER_CLEANUP_HOOK,
>    LDPT_ADD_SYMBOLS,
> @@ -274,7 +364,13 @@
>    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.  */
> @@ -287,6 +383,8 @@
>      int tv_val;
>      const char *tv_string;
>      ld_plugin_register_claim_file tv_register_claim_file;
> +    ld_plugin_register_inspect_unclaimed_object
> +      tv_register_inspect_unclaimed_object;

Move this, too, to be consistent with the order in enum ld_plugin_level.

>      ld_plugin_register_all_symbols_read tv_register_all_symbols_read;
>      ld_plugin_register_cleanup tv_register_cleanup;
>      ld_plugin_add_symbols tv_add_symbols;
> @@ -298,6 +396,12 @@
>      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;
>  };
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
       [not found]               ` <BANLkTimKuKEGo8VSQqMFun_EfCj350R9tEpMejD8mmBrOudyiA@mail.gmail.com>
@ 2011-07-05 22:30                 ` Ian Lance Taylor
  2011-07-08  8:47                   ` Sriraman Tallam
  2011-07-13 14:45                   ` Sriraman Tallam
  0 siblings, 2 replies; 19+ messages in thread
From: Ian Lance Taylor @ 2011-07-05 22:30 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: Cary Coutant, binutils

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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-07-05 22:30                 ` Ian Lance Taylor
@ 2011-07-08  8:47                   ` Sriraman Tallam
  2011-07-13 14:45                   ` Sriraman Tallam
  1 sibling, 0 replies; 19+ messages in thread
From: Sriraman Tallam @ 2011-07-08  8:47 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Cary Coutant, binutils

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.

Originally, I added inspect_unclaimed_object because it needs an elf
object to be created before hand where claim_file does not create any
object before hand. However,  it looks like I can create an elf object
for claim_file which means I can inspect all objects in the claim_file
hook of the plugin. If the plugin claims the object then the elf
object will be deleted and replaced with the new Pluginobj that is
created. I will get back with the modified patch doing this.

Thanks,
-Sri.

>
> Ian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-07-05 22:30                 ` Ian Lance Taylor
  2011-07-08  8:47                   ` Sriraman Tallam
@ 2011-07-13 14:45                   ` Sriraman Tallam
  2011-07-13 21:52                     ` Cary Coutant
  1 sibling, 1 reply; 19+ messages in thread
From: Sriraman Tallam @ 2011-07-13 14:45 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Cary Coutant, binutils

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

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
>

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

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;
 }
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-07-13 14:45                   ` Sriraman Tallam
@ 2011-07-13 21:52                     ` Cary Coutant
  2011-07-13 22:50                       ` Sriraman Tallam
  0 siblings, 1 reply; 19+ messages in thread
From: Cary Coutant @ 2011-07-13 21:52 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: Ian Lance Taylor, binutils

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

@@ -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;

If there is no ELF object, this->object(handle) might return null. You
need to check that before trying to downcast.

+Object*
+Plugin_manager::get_elf_object(const void* handle)
+{
+  Object* obj = parameters->options().plugins()->object(
+      static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));

Doesn't "this->object(...)" work here?

@@ -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();

You need to check for NULL.

@@ -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();

And here.

   // Return the Pluginobj associated with the given HANDLE.
-  Pluginobj*
+  Object*
   object(unsigned int handle) const

Update the comment, please.

-cary

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-07-13 21:52                     ` Cary Coutant
@ 2011-07-13 22:50                       ` Sriraman Tallam
  2011-07-14  2:18                         ` Ian Lance Taylor
  0 siblings, 1 reply; 19+ messages in thread
From: Sriraman Tallam @ 2011-07-13 22:50 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Ian Lance Taylor, binutils

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

Hi,

Made the changes and attached the new patch. Please also see function
get_view in plugin.cc. I made the following change to correct the
detection of whether get_view if called from the claim_file_hook.

-  if (this->objects_.size() == handle)
+  if (this->in_claim_file_handler_)
     {
       // We are being called from the claim_file hook.

Thanks,
-Sri.

On Wed, Jul 13, 2011 at 11:20 AM, Cary Coutant <ccoutant@google.com> wrote:
>>   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.
>
> @@ -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;
>
> If there is no ELF object, this->object(handle) might return null. You
> need to check that before trying to downcast.
>
> +Object*
> +Plugin_manager::get_elf_object(const void* handle)
> +{
> +  Object* obj = parameters->options().plugins()->object(
> +      static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
>
> Doesn't "this->object(...)" work here?
>
> @@ -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();
>
> You need to check for NULL.
>
> @@ -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();
>
> And here.
>
>   // Return the Pluginobj associated with the given HANDLE.
> -  Pluginobj*
> +  Object*
>   object(unsigned int handle) const
>
> Update the comment, please.
>
> -cary
>

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

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 19:36:43 -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,65 @@ 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 clam_file 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 claim_file handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_allow_section_ordering) (void);
+
 enum ld_plugin_level
 {
   LDPL_INFO,
@@ -274,7 +341,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 +371,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 19:36:45 -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 19:36:45 -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 19:36:46 -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 19:36:46 -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 19:36:46 -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 19:36:46 -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 19:36:46 -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,11 @@ Plugin_manager::get_input_file(unsigned 
 ld_plugin_status
 Plugin_manager::release_input_file(unsigned int handle)
 {
-  Pluginobj* obj = this->object(handle);
+  if (this->object(handle) == NULL)
+    return LDPS_BAD_HANDLE;
+
+  Pluginobj* obj = this->object(handle)->pluginobj();
+
   if (obj == NULL)
     return LDPS_BAD_HANDLE;
 
@@ -642,13 +708,30 @@ 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 = this->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)
 {
   off_t offset;
   size_t filesize;
   Input_file *input_file;
-  if (this->objects_.size() == handle)
+  if (this->in_claim_file_handler_)
     {
       // We are being called from the claim_file hook.
       const struct ld_plugin_input_file &f = this->plugin_input_file_;
@@ -659,7 +742,9 @@ Plugin_manager::get_view(unsigned int ha
   else
     {
       // An already claimed file.
-      Pluginobj* obj = this->object(handle);
+      if (this->object(handle) == NULL)
+        return LDPS_BAD_HANDLE;
+      Pluginobj* obj = this->object(handle)->pluginobj();
       if (obj == NULL)
         return LDPS_BAD_HANDLE;
       offset = obj->offset();
@@ -1226,7 +1311,6 @@ Plugin_hook::run(Workqueue* workqueue)
                                              this,
                                              this->input_objects_,
                                              this->symtab_,
-                                             this->layout_,
                                              this->dirpath_,
                                              this->mapfile_,
                                              &this->this_blocker_);
@@ -1320,11 +1404,14 @@ static enum ld_plugin_status
 get_symbols(const void* handle, int nsyms, ld_plugin_symbol* syms)
 {
   gold_assert(parameters->options().has_plugins());
-  Pluginobj* obj = parameters->options().plugins()->object(
-      static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
+  Object* obj = parameters->options().plugins()->object(
+    static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
   if (obj == NULL)
     return LDPS_ERR;
-  return obj->get_symbol_resolution_info(nsyms, syms);
+  Pluginobj* plugin_obj = obj->pluginobj();
+  if (plugin_obj == NULL)
+    return LDPS_ERR;
+  return plugin_obj->get_symbol_resolution_info(nsyms, syms);
 }
 
 // Add a new (real) input file generated by a plugin.
@@ -1384,6 +1471,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 19:36:46 -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
@@ -218,8 +230,8 @@ class Plugin_manager
   Pluginobj*
   make_plugin_object(unsigned int handle);
 
-  // Return the Pluginobj associated with the given HANDLE.
-  Pluginobj*
+  // Return the object associated with the given HANDLE.
+  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 19:36:47 -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_,
cvs diff: Diffing gold/po
cvs diff: Diffing gold/testsuite
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 19:36:47 -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;
 }
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-07-13 22:50                       ` Sriraman Tallam
@ 2011-07-14  2:18                         ` Ian Lance Taylor
  2011-07-14  2:39                           ` Sriraman Tallam
  0 siblings, 1 reply; 19+ messages in thread
From: Ian Lance Taylor @ 2011-07-14  2:18 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: Cary Coutant, binutils

Sriraman Tallam <tmsriram@google.com> writes:

> Made the changes and attached the new patch. Please also see function
> get_view in plugin.cc. I made the following change to correct the
> detection of whether get_view if called from the claim_file_hook.
>
> -  if (this->objects_.size() == handle)
> +  if (this->in_claim_file_handler_)
>      {
>        // We are being called from the claim_file hook.

> +  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;

Change to something like
  const std::string section_name = obj->section_name(section.shndx);
  *section_name_ptr = static_cast<char*>(malloc(section_name.length() + 1));
  memcpy(*section_name_ptr, section_name.c_str(),
         section_name.length() + 1);
  return LDPS_OK;


This is OK with that change.

Thanks, and thanks for your patience with this.

Ian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
  2011-07-14  2:18                         ` Ian Lance Taylor
@ 2011-07-14  2:39                           ` Sriraman Tallam
  0 siblings, 0 replies; 19+ messages in thread
From: Sriraman Tallam @ 2011-07-14  2:39 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Cary Coutant, binutils

Thanks, I submitted the patch after making the change.

Thanks,
-Sri.

On Wed, Jul 13, 2011 at 5:35 PM, Ian Lance Taylor <iant@google.com> wrote:
> Sriraman Tallam <tmsriram@google.com> writes:
>
>> Made the changes and attached the new patch. Please also see function
>> get_view in plugin.cc. I made the following change to correct the
>> detection of whether get_view if called from the claim_file_hook.
>>
>> -  if (this->objects_.size() == handle)
>> +  if (this->in_claim_file_handler_)
>>      {
>>        // We are being called from the claim_file hook.
>
>> +  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;
>
> Change to something like
>  const std::string section_name = obj->section_name(section.shndx);
>  *section_name_ptr = static_cast<char*>(malloc(section_name.length() + 1));
>  memcpy(*section_name_ptr, section_name.c_str(),
>         section_name.length() + 1);
>  return LDPS_OK;
>
>
> This is OK with that change.
>
> Thanks, and thanks for your patience with this.
>
> Ian
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2011-07-14  1:01 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-03 23:58 Plugin interfaces to do Pettis Hansen style code layout in the gold linker Sriraman Tallam
2011-03-10  0:45 ` Cary Coutant
2011-03-13  2:37   ` Sriraman Tallam
2011-03-13  7:35     ` Dave Korn
2011-03-14  3:40       ` Sriraman Tallam
2011-03-14 18:22     ` Cary Coutant
2011-03-14 18:45       ` Sriraman Tallam
2011-03-15 14:44         ` Ian Lance Taylor
2011-03-15 17:48           ` Cary Coutant
2011-03-15 20:11             ` Ian Lance Taylor
2011-06-04  0:46           ` Sriraman Tallam
2011-06-24 22:25             ` Cary Coutant
     [not found]               ` <BANLkTimKuKEGo8VSQqMFun_EfCj350R9tEpMejD8mmBrOudyiA@mail.gmail.com>
2011-07-05 22:30                 ` Ian Lance Taylor
2011-07-08  8:47                   ` Sriraman Tallam
2011-07-13 14:45                   ` Sriraman Tallam
2011-07-13 21:52                     ` Cary Coutant
2011-07-13 22:50                       ` Sriraman Tallam
2011-07-14  2:18                         ` Ian Lance Taylor
2011-07-14  2:39                           ` Sriraman Tallam

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