Add plugin API for processing plugin-added input files
authorStephen Crane <sjc@immunant.com>
Mon, 11 Dec 2017 22:58:38 +0000 (14:58 -0800)
committerSriraman Tallam <tmsriram@google.com>
Mon, 11 Dec 2017 22:58:38 +0000 (14:58 -0800)
Gold plugins may wish to further process an input file added by a plugin. For
example, the plugin may need to assign a unique segment for sections in a
plugin-generated input file. This patch adds a plugin callback that the linker
will call when reading symbols from a new input file added after the
all_symbols_read event (i.e. an input file added by a plugin).

2017-12-11  Stephen Crane  <sjc@immunant.com>

* plugin-api.h: Add new plugin hook to allow processing of input
files added by a plugin.
(ld_plugin_new_input_handler): New function hook type.
(ld_plugin_register_new_input): New interface.
(LDPT_REGISTER_NEW_INPUT_HOOK): New enum val.
(tv_register_new_input): New member.

* plugin.cc (Plugin::load): Include hooks for register_new_input
in transfer vector.
(Plugin::new_input): New function.
(register_new_input): New function.
(Plugin_manager::claim_file): Call Plugin::new_input if in
replacement phase.
* plugin.h (Plugin::set_new_input_handler): New function.
* testsuite/plugin_new_section_layout.c: New plugin to test
new_input plugin API.
* testsuite/plugin_final_layout.sh: Add new input test.
* testsuite/Makefile.am (plugin_layout_new_file): New test case.
* testsuite/Makefile.in: Regenerate.

gold/ChangeLog
gold/plugin.cc
gold/plugin.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/plugin_final_layout.sh
gold/testsuite/plugin_new_section_layout.c [new file with mode: 0644]
include/ChangeLog
include/plugin-api.h

index e0048b54cc86cf6d99028c8268cc3d0b3b0ab394..bc0413dfcaa38e947d14bb094a944c23360a42ae 100644 (file)
@@ -1,3 +1,18 @@
+2017-12-11  Stephen Crane  <sjc@immunant.com>
+
+       * plugin.cc (Plugin::load): Include hooks for register_new_input
+       in transfer vector.
+       (Plugin::new_input): New function.
+       (register_new_input): New function.
+       (Plugin_manager::claim_file): Call Plugin::new_input if in
+       replacement phase.
+       * plugin.h (Plugin::set_new_input_handler): New function.
+       * testsuite/plugin_new_section_layout.c: New plugin to test
+       new_input plugin API.
+       * testsuite/plugin_final_layout.sh: Add new input test.
+       * testsuite/Makefile.am (plugin_layout_new_file): New test case.
+       * testsuite/Makefile.in: Regenerate.
+
 2017-12-02  Vladimir Kondratyev  <vladimir@kondratyev.su>
            Cary Coutant  <ccoutant@gmail.com>
 
index 5ea23b5bdd7339cfd46f553bdcd6e6a0f4e363fe..49212b43090adcbb8b9121ab49e302f36afae4b2 100644 (file)
@@ -167,6 +167,9 @@ static enum ld_plugin_status
 get_input_section_size(const struct ld_plugin_section section,
                        uint64_t* secsize);
 
+static enum ld_plugin_status
+register_new_input(ld_plugin_new_input_handler handler);
+
 };
 
 #endif // ENABLE_PLUGINS
@@ -211,7 +214,7 @@ Plugin::load()
   sscanf(ver, "%d.%d", &major, &minor);
 
   // Allocate and populate a transfer vector.
-  const int tv_fixed_size = 29;
+  const int tv_fixed_size = 30;
 
   int tv_size = this->args_.size() + tv_fixed_size;
   ld_plugin_tv* tv = new ld_plugin_tv[tv_size];
@@ -345,6 +348,10 @@ Plugin::load()
   tv[i].tv_tag = LDPT_GET_INPUT_SECTION_SIZE;
   tv[i].tv_u.tv_get_input_section_size = get_input_section_size;
 
+  ++i;
+  tv[i].tv_tag = LDPT_REGISTER_NEW_INPUT_HOOK;
+  tv[i].tv_u.tv_register_new_input = register_new_input;
+
   ++i;
   tv[i].tv_tag = LDPT_NULL;
   tv[i].tv_u.tv_val = 0;
@@ -383,6 +390,15 @@ Plugin::all_symbols_read()
     (*this->all_symbols_read_handler_)();
 }
 
+// Call the new_input handler.
+
+inline void
+Plugin::new_input(struct ld_plugin_input_file* plugin_input_file)
+{
+  if (this->new_input_handler_ != NULL)
+    (*this->new_input_handler_)(plugin_input_file);
+}
+
 // Call the cleanup handler.
 
 inline void
@@ -476,8 +492,6 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset,
 
   gold_assert(lock_initialized);
   Hold_lock hl(*this->lock_);
-  if (this->in_replacement_phase_)
-    return NULL;
 
   unsigned int handle = this->objects_.size();
   this->input_file_ = input_file;
@@ -494,19 +508,28 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset,
        this->current_ != this->plugins_.end();
        ++this->current_)
     {
-      if ((*this->current_)->claim_file(&this->plugin_input_file_))
+      // If we aren't yet in replacement phase, allow plugins to claim input
+      // files, otherwise notify the plugin of the new input file, if needed.
+      if (!this->in_replacement_phase_)
         {
-         this->any_claimed_ = true;
-         this->in_claim_file_handler_ = false;
-
-          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.
-          Pluginobj* obj = this->make_plugin_object(handle);
-          return obj;
+          if ((*this->current_)->claim_file(&this->plugin_input_file_))
+            {
+              this->any_claimed_ = true;
+              this->in_claim_file_handler_ = false;
+
+              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.
+              Pluginobj* obj = this->make_plugin_object(handle);
+              return obj;
+            }
+        }
+      else
+        {
+          (*this->current_)->new_input(&this->plugin_input_file_);
         }
     }
 
@@ -1905,6 +1928,16 @@ unique_segment_for_sections(const char* segment_name,
   return LDPS_OK;
 }
 
+// Register a new_input handler.
+
+static enum ld_plugin_status
+register_new_input(ld_plugin_new_input_handler handler)
+{
+  gold_assert(parameters->options().has_plugins());
+  parameters->options().plugins()->set_new_input_handler(handler);
+  return LDPS_OK;
+}
+
 #endif // ENABLE_PLUGINS
 
 // Allocate a Pluginobj object of the appropriate size and endianness.
index 765866850284c65b460dab75b12c9983cfa28d89..d591d26821d8668713e2c28d5b4e94223dc4459e 100644 (file)
@@ -60,6 +60,7 @@ class Plugin
       claim_file_handler_(NULL),
       all_symbols_read_handler_(NULL),
       cleanup_handler_(NULL),
+      new_input_handler_(NULL),
       cleanup_done_(false)
   { }
 
@@ -78,6 +79,10 @@ class Plugin
   void
   all_symbols_read();
 
+  // Call the new_input handler.
+  void
+  new_input(struct ld_plugin_input_file* plugin_input_file);
+
   // Call the cleanup handler.
   void
   cleanup();
@@ -97,6 +102,11 @@ class Plugin
   set_cleanup_handler(ld_plugin_cleanup_handler handler)
   { this->cleanup_handler_ = handler; }
 
+  // Register a new_input handler.
+  void
+  set_new_input_handler(ld_plugin_new_input_handler handler)
+  { this->new_input_handler_ = handler; }
+
   // Add an argument
   void
   add_option(const char* arg)
@@ -118,6 +128,7 @@ class Plugin
   ld_plugin_claim_file_handler claim_file_handler_;
   ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
   ld_plugin_cleanup_handler cleanup_handler_;
+  ld_plugin_new_input_handler new_input_handler_;
   // TRUE if the cleanup handlers have been called.
   bool cleanup_done_;
 };
@@ -218,6 +229,14 @@ class Plugin_manager
     (*this->current_)->set_all_symbols_read_handler(handler);
   }
 
+  // Register a new_input handler.
+  void
+  set_new_input_handler(ld_plugin_new_input_handler handler)
+  {
+    gold_assert(this->current_ != plugins_.end());
+    (*this->current_)->set_new_input_handler(handler);
+  }
+
   // Register a claim-file handler.
   void
   set_cleanup_handler(ld_plugin_cleanup_handler handler)
index aad244c595f9679cfd731469b4affd0ae74277b1..16cae8004c9cd7ed1ad163476ff4ebf3445cd104 100644 (file)
@@ -2401,6 +2401,23 @@ plugin_section_order.so: plugin_section_order.o gcctestdir/ld
 plugin_section_order.o: plugin_section_order.c
        $(COMPILE) -O0 -c -fpic -o $@ $<
 
+# Uses the plugin_final_layout.sh script above to avoid duplication
+check_DATA += plugin_layout_new_file.stdout plugin_layout_new_file_readelf.stdout
+MOSTLYCLEANFILES += plugin_layout_new_file
+plugin_final_layout.o.syms: plugin_final_layout.o
+       $(TEST_READELF) -sW $< >$@ 2>/dev/null
+plugin_layout_new_file: plugin_final_layout.o.syms plugin_test.so plugin_new_section_layout.so gcctestdir/ld
+       $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_test.so"  -Wl,--plugin,"./plugin_new_section_layout.so" plugin_final_layout.o.syms
+plugin_layout_new_file.stdout: plugin_layout_new_file
+       $(TEST_NM) -n --synthetic plugin_layout_new_file > plugin_layout_new_file.stdout
+plugin_layout_new_file_readelf.stdout: plugin_layout_new_file
+       $(TEST_READELF) -Wl plugin_layout_new_file > plugin_layout_new_file_readelf.stdout
+
+plugin_new_section_layout.so: plugin_new_section_layout.o gcctestdir/ld
+       $(LINK) -Bgcctestdir/ -shared plugin_new_section_layout.o
+plugin_new_section_layout.o: plugin_new_section_layout.c
+       $(COMPILE) -O0 -c -fpic -o $@ $<
+
 check_SCRIPTS += plugin_layout_with_alignment.sh
 check_DATA += plugin_layout_with_alignment.stdout
 MOSTLYCLEANFILES += plugin_layout_with_alignment
index d62590997a520007f45da2e3c28edb8944b04c61..bbf8dc146bb0bd49bd694bf92bf8f6df9adce2e8 100644 (file)
@@ -590,11 +590,16 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@@TLS_TRUE@am__append_51 = plugin_test_tls.err
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_52 = unused.c \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_final_layout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_layout_new_file \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_layout_with_alignment
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_53 = plugin_final_layout.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_layout_with_alignment.sh
+
+# Uses the plugin_final_layout.sh script above to avoid duplication
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_54 = plugin_final_layout.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_final_layout_readelf.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_layout_new_file.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_layout_new_file_readelf.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_layout_with_alignment.stdout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_55 = exclude_libs_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ local_labels_test \
@@ -7057,6 +7062,19 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(LINK) -Bgcctestdir/ -shared plugin_section_order.o
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_order.o: plugin_section_order.c
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(COMPILE) -O0 -c -fpic -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.o.syms: plugin_final_layout.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(TEST_READELF) -sW $< >$@ 2>/dev/null
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_layout_new_file: plugin_final_layout.o.syms plugin_test.so plugin_new_section_layout.so gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_test.so"  -Wl,--plugin,"./plugin_new_section_layout.so" plugin_final_layout.o.syms
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_layout_new_file.stdout: plugin_layout_new_file
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(TEST_NM) -n --synthetic plugin_layout_new_file > plugin_layout_new_file.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_layout_new_file_readelf.stdout: plugin_layout_new_file
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(TEST_READELF) -Wl plugin_layout_new_file > plugin_layout_new_file_readelf.stdout
+
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_new_section_layout.so: plugin_new_section_layout.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(LINK) -Bgcctestdir/ -shared plugin_new_section_layout.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_new_section_layout.o: plugin_new_section_layout.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(COMPILE) -O0 -c -fpic -o $@ $<
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_layout_with_alignment.o: plugin_layout_with_alignment.c
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(COMPILE) -O0 -c -ffunction-sections  -fdata-sections -g -o $@ $<
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_layout_with_alignment: plugin_layout_with_alignment.o plugin_section_alignment.so gcctestdir/ld
index 54985916a75ccbb3a0013d2f7e5884973f629be0..3157beacf40ffaba9441ed509994b16f78e1b620 100755 (executable)
@@ -23,7 +23,7 @@
 # MA 02110-1301, USA.
 
 # The goal of this program is to verify if --section-ordering-file works as
-# intended.  File final_layout.cc is in this test.
+# intended.  File plugin_final_layout.cc is in this test.
 
 
 set -e
@@ -37,7 +37,7 @@ BEGIN { saw1 = 0; saw2 = 0; err = 0; }
      saw2 = 1;
      if (!saw1)
        {
-         printf \"layout of $2 and $3 is not right\\n\";
+         printf \"layout of $2 and $3 is not right in file $1\\n\";
          err = 1;
          exit 1;
        }
@@ -45,12 +45,12 @@ BEGIN { saw1 = 0; saw2 = 0; err = 0; }
 END {
       if (!saw1 && !err)
         {
-         printf \"did not see $2\\n\";
+         printf \"did not see $2 in file $1\\n\";
          exit 1;
        }
       if (!saw2 && !err)
        {
-         printf \"did not see $3\\n\";
+         printf \"did not see $3 in file $1\\n\";
          exit 1;
        }
     }" $1
@@ -74,12 +74,12 @@ BEGIN { saw_section = 0; saw_unique = 0; }
 END {
       if (!saw_section)
        {
-         printf \"Section $2 not seen in output\\n\";
+         printf \"Section $2 not seen in output file $1\\n\";
          exit 1;
        }
       else if (!saw_unique)
        {
-         printf \"Unique segment not seen for: $2\\n\";
+         printf \"Unique segment not seen for: $2 in file $1\\n\";
          exit 1;
        }
     }" $1
@@ -88,3 +88,7 @@ END {
 check plugin_final_layout.stdout "_Z3foov" "_Z3barv"
 check plugin_final_layout.stdout "_Z3barv" "_Z3bazv"
 check_unique_segment plugin_final_layout_readelf.stdout ".text.plugin_created_unique"
+
+check plugin_layout_new_file.stdout "_Z3foov" "_Z3barv"
+check plugin_layout_new_file.stdout "_Z3barv" "_Z3bazv"
+check_unique_segment plugin_layout_new_file_readelf.stdout ".text.plugin_created_unique"
diff --git a/gold/testsuite/plugin_new_section_layout.c b/gold/testsuite/plugin_new_section_layout.c
new file mode 100644 (file)
index 0000000..7bceae6
--- /dev/null
@@ -0,0 +1,182 @@
+/* plugin_new_section_layout.c -- Simple plugin to reorder function sections in
+   plugin-generated objects
+
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   Written by Stephen Crane <sjc@immunant.com>.
+
+   This file is part of gold.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+/* This plugin tests the new_input API of the linker plugin interface that
+ * allows plugins to modify section layout and assign sections to segments for
+ * sections in plugin-generated object files. It assumes that another plugin is
+ * also in use which will add new files. In practice a plugin is likely to
+ * generate new input files itself in all_symbols_read and want to
+ * reorder/assign sections for these files in the new_input_hook callback. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "plugin-api.h"
+#include "elf/common.h"
+
+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_update_section_order update_section_order = NULL;
+static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
+static ld_plugin_allow_unique_segment_for_sections 
+    allow_unique_segment_for_sections = NULL;
+static ld_plugin_unique_segment_for_sections unique_segment_for_sections = NULL;
+
+enum ld_plugin_status onload(struct ld_plugin_tv *tv);
+enum ld_plugin_status new_input_hook(const struct ld_plugin_input_file *file);
+
+/* Plugin entry point.  */
+enum ld_plugin_status
+onload(struct ld_plugin_tv *tv)
+{
+  struct ld_plugin_tv *entry;
+  for (entry = tv; entry->tv_tag != LDPT_NULL; ++entry)
+    {
+      switch (entry->tv_tag)
+        {
+        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_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;
+       case LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS:
+         allow_unique_segment_for_sections
+             = *entry->tv_u.tv_allow_unique_segment_for_sections;
+         break;
+       case LDPT_UNIQUE_SEGMENT_FOR_SECTIONS:
+         unique_segment_for_sections
+             = *entry->tv_u.tv_unique_segment_for_sections;
+         break;
+        case LDPT_REGISTER_NEW_INPUT_HOOK:
+          assert((*entry->tv_u.tv_register_new_input) (new_input_hook)
+                == LDPS_OK);
+          break;
+        default:
+          break;
+        }
+    }
+
+  if (get_input_section_count == NULL
+      || get_input_section_type == NULL
+      || get_input_section_name == NULL
+      || update_section_order == NULL
+      || allow_section_ordering == NULL
+      || allow_unique_segment_for_sections == NULL
+      || unique_segment_for_sections == NULL)
+    {
+      fprintf(stderr, "Some interfaces are missing\n");
+      return LDPS_ERR;
+    }
+
+  /* Inform the linker to prepare for section reordering.  */
+  (*allow_section_ordering)();
+  /* Inform the linker to prepare to map some sections to unique
+     segments.  */
+  (*allow_unique_segment_for_sections)(); 
+
+  return LDPS_OK;
+}
+
+inline static int is_prefix_of(const char *prefix, const char *str)
+{
+  return strncmp(prefix, str, strlen (prefix)) == 0;
+}
+
+/* This function is called by the linker when new files are added by a plugin.
+   We can now tell the linker the desired function order since we have a file
+   handle for the newly added file.  */
+
+enum ld_plugin_status
+new_input_hook(const struct ld_plugin_input_file *file)
+{
+  struct ld_plugin_section section_list[3];
+  int num_entries = 0;
+  unsigned int count;
+
+  if (get_input_section_count(file->handle, &count) != LDPS_OK)
+    return LDPS_ERR;
+
+  unsigned int i;
+  for (i = 0; i < count; ++i)
+  {
+    struct ld_plugin_section section;
+    unsigned int type = 0;
+    char *name = NULL;
+    int position = 3;
+
+    section.handle = file->handle;
+    section.shndx = i;
+
+    if (get_input_section_type(section, &type) != LDPS_OK)
+      return LDPL_FATAL;
+    if (type != SHT_PROGBITS)
+      continue;
+
+    if (get_input_section_name(section, &name))
+      return LDPL_FATAL;
+
+    /* As in plugin_section_order.c, order is foo() followed by bar()
+       followed by baz() */
+    if (is_prefix_of(".text.", name))
+    {
+      if (strstr(name, "_Z3foov") != NULL)
+        position = 0;
+      else if (strstr(name, "_Z3barv") != NULL)
+        position = 1;
+      else if (strstr(name, "_Z3bazv") != NULL)
+        position = 2;
+      else
+        position = 3;
+    }
+    if (position < 3)
+    {
+      section_list[position] = section;
+      num_entries++;
+    }
+  }
+
+  if (num_entries != 3)
+    return LDPL_FATAL;
+
+  update_section_order(section_list, num_entries);
+  unique_segment_for_sections (".text.plugin_created_unique", 0, 0x1000,
+                               section_list, num_entries);
+
+  return LDPS_OK;
+}
index ef1cfe05147089d945d8a767a0cc307362e44e44..8914e269ff15b1fa5b55380f893c17788e1e06ab 100644 (file)
@@ -1,3 +1,12 @@
+2017-12-11  Stephen Crane  <sjc@immunant.com>
+
+       * plugin-api.h: Add new plugin hook to allow processing of input
+       files added by a plugin.
+       (ld_plugin_new_input_handler): New function hook type.
+       (ld_plugin_register_new_input): New interface.
+       (LDPT_REGISTER_NEW_INPUT_HOOK): New enum val.
+       (tv_register_new_input): New member.
+
 2017-12-01  Peter Bergner  <bergner@vnet.ibm.com>
 
        * opcode/ppc.h (PPC_INT_FMT): Define.
index 3a3e8b456db0600f87d955628df589d9adb859ed..f081f85dfaf9da05bb7db7a648f543dd7761eeec 100644 (file)
@@ -365,6 +365,20 @@ enum ld_plugin_status
 (*ld_plugin_get_input_section_size) (const struct ld_plugin_section section,
                                      uint64_t *secsize);
 
+typedef
+enum ld_plugin_status
+(*ld_plugin_new_input_handler) (const struct ld_plugin_input_file *file);
+
+/* The linker's interface for registering the "new_input" handler. This handler
+   will be notified when a new input file has been added after the
+   all_symbols_read event, allowing the plugin to, for example, set a unique
+   segment for sections in plugin-generated input files. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_new_input) (ld_plugin_new_input_handler handler);
+
+
 enum ld_plugin_level
 {
   LDPL_INFO,
@@ -407,7 +421,8 @@ enum ld_plugin_tag
   LDPT_UNIQUE_SEGMENT_FOR_SECTIONS = 27,
   LDPT_GET_SYMBOLS_V3 = 28,
   LDPT_GET_INPUT_SECTION_ALIGNMENT = 29,
-  LDPT_GET_INPUT_SECTION_SIZE = 30
+  LDPT_GET_INPUT_SECTION_SIZE = 30,
+  LDPT_REGISTER_NEW_INPUT_HOOK = 31
 };
 
 /* The plugin transfer vector.  */
@@ -441,6 +456,7 @@ struct ld_plugin_tv
     ld_plugin_unique_segment_for_sections tv_unique_segment_for_sections;
     ld_plugin_get_input_section_alignment tv_get_input_section_alignment;
     ld_plugin_get_input_section_size tv_get_input_section_size;
+    ld_plugin_register_new_input tv_register_new_input;
   } tv_u;
 };