2011-09-29 Sriraman Tallam <tmsriram@google.com>
authorSriraman Tallam <tmsriram@google.com>
Thu, 29 Sep 2011 23:45:57 +0000 (23:45 +0000)
committerSriraman Tallam <tmsriram@google.com>
Thu, 29 Sep 2011 23:45:57 +0000 (23:45 +0000)
* layout.h (section_order_map_): New member.
(get_section_order_map): New member function.
* output.cc (Output_section::add_input_section): Check for patterns
only when --section-ordering-file is specified.
* gold.cc (queue_middle_tasks): Delay updating order of sections till
output_sections have been formed.
* layout.cc (Layout_Layout): Initialize section_order_map_.
* plugin.cc (update_section_order): Store order in order_map. Do not
update the order.
* testsuite/Makefile.am: Add test case for plugin_final_layout.
* testsuite/Makefile.in: Regenerate.
* testsuite/plugin_section_order.c: New file.
* testsuite/plugin_final_layout.cc: New file.
* testsuite/plugin_final_layout.sh: New file.

12 files changed:
gold/ChangeLog
gold/gold.cc
gold/layout.cc
gold/layout.h
gold/output.cc
gold/output.h
gold/plugin.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/plugin_final_layout.cc [new file with mode: 0644]
gold/testsuite/plugin_final_layout.sh [new file with mode: 0755]
gold/testsuite/plugin_section_order.c [new file with mode: 0644]

index a00a8e4..e12a151 100644 (file)
@@ -1,3 +1,20 @@
+2011-09-29  Sriraman Tallam  <tmsriram@google.com>
+
+       * layout.h (section_order_map_): New member.
+       (get_section_order_map): New member function.
+       * output.cc (Output_section::add_input_section): Check for patterns
+       only when --section-ordering-file is specified.
+       * gold.cc (queue_middle_tasks): Delay updating order of sections till
+       output_sections have been formed.
+       * layout.cc (Layout_Layout): Initialize section_order_map_.
+       * plugin.cc (update_section_order): Store order in order_map. Do not
+       update the order.
+       * testsuite/Makefile.am: Add test case for plugin_final_layout.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/plugin_section_order.c: New file.
+       * testsuite/plugin_final_layout.cc: New file.
+       * testsuite/plugin_final_layout.sh: New file.
+
 2011-09-29  Cary Coutant  <ccoutant@google.com>
 
        * gold/incremental.cc (Sized_incremental_binary::do_process_got_plt):
index 693ff79..2700bdb 100644 (file)
@@ -539,6 +539,20 @@ queue_middle_tasks(const General_options& options,
         }
     }
 
+  /* If plugins have specified a section order, re-arrange input sections
+     according to a specified section order.  If --section-ordering-file is
+     also specified, do not do anything here.  */
+  if (parameters->options().has_plugins()
+      && layout->is_section_ordering_specified()
+      && !parameters->options().section_ordering_file ())
+    {
+      for (Layout::Section_list::const_iterator p
+            = layout->section_list().begin();
+           p != layout->section_list().end();
+           ++p)
+        (*p)->update_section_layout(layout->get_section_order_map());
+    }
+
   // Layout deferred objects due to plugins.
   if (parameters->options().has_plugins())
     {
index 1c32bcf..2f77e56 100644 (file)
@@ -410,6 +410,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options)
     script_output_section_data_list_(),
     segment_states_(NULL),
     relaxation_debug_check_(NULL),
+    section_order_map_(),
     input_section_position_(),
     input_section_glob_(),
     incremental_base_(NULL),
index 05cb50f..d76fc96 100644 (file)
@@ -522,6 +522,10 @@ class Layout
         const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
         unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
 
+  std::map<Section_id, unsigned int>*
+  get_section_order_map()
+  { return &this->section_order_map_; }
   bool
   is_section_ordering_specified()
   { return this->section_ordering_specified_; }
@@ -1322,6 +1326,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_;
+  // Plugins specify section_ordering using this map.  This is set in
+  // update_section_order in plugin.cc
+  std::map<Section_id, unsigned int> section_order_map_;
   // 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 29d8e3d..63f0109 100644 (file)
@@ -2476,7 +2476,10 @@ Output_section::add_input_section(Layout* layout,
       || layout->is_section_ordering_specified())
     {
       Input_section isecn(object, shndx, input_section_size, addralign);
-      if (layout->is_section_ordering_specified())
+      /* If section ordering is requested by specifying a ordering file,
+        using --section-ordering-file, match the section name with
+        a pattern.  */
+      if (parameters->options().section_ordering_file())
         {
           unsigned int section_order_index =
             layout->find_section_order_index(std::string(secname));
@@ -3485,7 +3488,7 @@ Output_section::Input_section_sort_section_order_index_compare::operator()(
 
 void
 Output_section::update_section_layout(
-  const Section_layout_order& order_map)
+  const Section_layout_order* order_map)
 {
   for (Input_section_list::iterator p = this->input_sections_.begin();
        p != this->input_sections_.end();
@@ -3499,8 +3502,8 @@ Output_section::update_section_layout(
                         : 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())
+           = 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)
index 1bec2c0..cabec5c 100644 (file)
@@ -2761,7 +2761,7 @@ class Output_section : public Output_data
   typedef std::map<Section_id, unsigned int> Section_layout_order;
 
   void
-  update_section_layout(const Section_layout_order& order_map);
+  update_section_layout(const Section_layout_order* order_map);
 
   // Update the output section flags based on input section flags.
   void
index 3ccd8d0..b5880a1 100644 (file)
@@ -1630,7 +1630,7 @@ get_input_section_contents(const struct ld_plugin_section section,
 // which they should appear in the final layout.
 
 static enum ld_plugin_status
-update_section_order(const struct ld_plugin_section *section_list,
+update_section_order(const struct ld_plugin_sectionsection_list,
                     unsigned int num_sections)
 {
   gold_assert(parameters->options().has_plugins());
@@ -1641,8 +1641,14 @@ update_section_order(const struct ld_plugin_section *section_list,
   if (section_list == NULL)
     return LDPS_ERR;
 
-  std::map<Section_id, unsigned int> order_map;
+  Layout* layout = parameters->options().plugins()->layout();
+  gold_assert (layout != NULL);
 
+  std::map<Section_id, unsigned int>* order_map
+    = layout->get_section_order_map();
+
+  /* Store the mapping from Section_id to section position in layout's
+     order_map to consult after output sections are added.  */
   for (unsigned int i = 0; i < num_sections; ++i)
     {
       Object* obj = parameters->options().plugins()->get_elf_object(
@@ -1651,17 +1657,9 @@ update_section_order(const struct ld_plugin_section *section_list,
        return LDPS_BAD_HANDLE;
       unsigned int shndx = section_list[i].shndx;
       Section_id secn_id(obj, shndx);
-      order_map[secn_id] = i + 1;
+      (*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;
 }
 
index 72917f9..06e1fd2 100644 (file)
@@ -1510,6 +1510,20 @@ unused.o: unused.c
 unused.c:
        @cp /dev/null $@
 
+check_SCRIPTS += plugin_final_layout.sh
+check_DATA += plugin_final_layout.stdout
+plugin_final_layout.o: plugin_final_layout.cc
+       $(CXXCOMPILE) -O0 -c -ffunction-sections  -fdata-sections -g -o $@ $<
+plugin_final_layout: plugin_final_layout.o plugin_section_order.so gcctestdir/ld
+       $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_order.so" plugin_final_layout.o
+plugin_final_layout.stdout: plugin_final_layout
+       $(TEST_NM) -n plugin_final_layout > plugin_final_layout.stdout
+
+plugin_section_order.so: plugin_section_order.o
+       $(LINK) -Bgcctestdir/ -shared plugin_section_order.o
+plugin_section_order.o: plugin_section_order.c
+       $(COMPILE) -O0 -c -fpic -o $@ $<
+
 endif PLUGINS
 
 check_PROGRAMS += exclude_libs_test
index c00f0d0..0b4cd1c 100644 (file)
@@ -306,7 +306,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_3.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_4.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_6.sh \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_7.sh
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_7.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_final_layout.sh
 
 # Test that symbols known in the IR file but not in the replacement file
 # produce an unresolved symbol error.
@@ -318,7 +319,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_6.err \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_7.err \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_7.syms \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_9.err
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_9.err \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_final_layout.stdout
 # Make a copy of two_file_test_1.o, which does not define the symbol _Z4t16av.
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_36 =  \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   plugin_test_1.err \
@@ -3644,6 +3646,8 @@ plugin_test_6.sh.log: plugin_test_6.sh
        @p='plugin_test_6.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 plugin_test_7.sh.log: plugin_test_7.sh
        @p='plugin_test_7.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+plugin_final_layout.sh.log: plugin_final_layout.sh
+       @p='plugin_final_layout.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 exclude_libs_test.sh.log: exclude_libs_test.sh
        @p='exclude_libs_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 discard_locals_test.sh.log: discard_locals_test.sh
@@ -4756,6 +4760,17 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(COMPILE) -c -o $@ $<
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@unused.c:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   @cp /dev/null $@
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.o: plugin_final_layout.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(CXXCOMPILE) -O0 -c -ffunction-sections  -fdata-sections -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout: plugin_final_layout.o plugin_section_order.so gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_order.so" plugin_final_layout.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.stdout: plugin_final_layout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@   $(TEST_NM) -n plugin_final_layout > plugin_final_layout.stdout
+
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_order.so: plugin_section_order.o
+@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@exclude_libs_test.syms: exclude_libs_test
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null
 @GCC_TRUE@@NATIVE_LINKER_TRUE@libexclude_libs_test_1.a: exclude_libs_test_1.o
diff --git a/gold/testsuite/plugin_final_layout.cc b/gold/testsuite/plugin_final_layout.cc
new file mode 100644 (file)
index 0000000..3e264f6
--- /dev/null
@@ -0,0 +1,41 @@
+// plugin_final_layout.cc -- a test case for gold
+
+// Copyright 2011 Free Software Foundation, Inc.
+// Written by Sriraman Tallam <tmsriram@google.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.
+
+// The goal of this program is to verify if section ordering
+// via plugins happens correctly.
+
+void bar ()
+{
+}
+
+void baz ()
+{
+}
+
+void foo ()
+{
+}
+
+int main ()
+{
+  return 0;
+}
diff --git a/gold/testsuite/plugin_final_layout.sh b/gold/testsuite/plugin_final_layout.sh
new file mode 100755 (executable)
index 0000000..600f8e2
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+# plugin_final_layout.sh -- test
+
+# Copyright 2011 Free Software Foundation, Inc.
+# Written by Sriraman Tallam <tmsriram@google.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.
+
+# The goal of this program is to verify if --section-ordering-file works as
+# intended.  File final_layout.cc is in this test.
+
+
+set -e
+
+check()
+{
+    awk "
+BEGIN { saw1 = 0; saw2 = 0; err = 0; }
+/.*$2\$/ { saw1 = 1; }
+/.*$3\$/ {
+     saw2 = 1;
+     if (!saw1)
+       {
+         printf \"layout of $2 and $3 is not right\\n\";
+         err = 1;
+         exit 1;
+       }
+    }
+END {
+      if (!saw1 && !err)
+        {
+         printf \"did not see $2\\n\";
+         exit 1;
+       }
+      if (!saw2 && !err)
+       {
+         printf \"did not see $3\\n\";
+         exit 1;
+       }
+    }" $1
+}
+
+check plugin_final_layout.stdout "_Z3foov" "_Z3barv"
+check plugin_final_layout.stdout "_Z3barv" "_Z3bazv"
diff --git a/gold/testsuite/plugin_section_order.c b/gold/testsuite/plugin_section_order.c
new file mode 100644 (file)
index 0000000..0e2079b
--- /dev/null
@@ -0,0 +1,167 @@
+/* plugin_section_reorder.c -- Simple plugin to reorder function sections
+
+   Copyright 2011 Free Software Foundation, Inc.
+   Written by Sriraman Tallam <tmsriram@google.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.  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "plugin-api.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_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;
+
+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 all_symbols_read_hook(void);
+
+/* 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_REGISTER_CLAIM_FILE_HOOK:
+          assert((*entry->tv_u.tv_register_claim_file) (claim_file_hook) == LDPS_OK);
+          break;
+       case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
+          assert((*entry->tv_u.tv_register_all_symbols_read) (all_symbols_read_hook)
+                 == LDPS_OK);
+          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;
+        }
+    }
+
+  if (get_input_section_count == NULL
+      || get_input_section_type == NULL
+      || get_input_section_name == NULL
+      || get_input_section_contents == NULL
+      || update_section_order == NULL
+      || allow_section_ordering == NULL)
+    {
+      fprintf(stderr, "Some interfaces are missing\n");
+      return LDPS_ERR;
+    }
+
+  return LDPS_OK;
+}
+
+inline static int is_prefix_of(const char *prefix, const char *str)
+{
+  return strncmp(prefix, str, strlen (prefix)) == 0;
+}
+
+struct ld_plugin_section section_list[3];
+int num_entries = 0;
+
+/* This function is called by the linker for every new object it encounters.  */
+enum ld_plugin_status
+claim_file_hook(const struct ld_plugin_input_file *file, int *claimed)
+{
+  static int is_ordering_specified = 0;
+  struct ld_plugin_section section;
+  unsigned int count = 0;
+  unsigned int shndx;
+
+  *claimed = 0;
+  if (is_ordering_specified == 0)
+    {
+      /* Inform the linker to prepare for section reordering.  */
+      (*allow_section_ordering)();
+      is_ordering_specified = 1;
+    }
+
+  (*get_input_section_count)(file->handle, &count);
+
+  for (shndx = 0; shndx < count; ++shndx)
+    {
+      char *name = NULL;
+      int position = 3;
+
+      section.handle = file->handle;
+      section.shndx = shndx;
+      (*get_input_section_name)(section, &name);
+
+      /* 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].handle = file->handle;
+         section_list[position].shndx = shndx;
+         num_entries++;
+       }
+    }
+  return LDPS_OK;
+}
+
+/* This function is called by the linker after all the symbols have been read.
+   At this stage, it is fine to tell the linker the desired function order.  */
+
+enum ld_plugin_status
+all_symbols_read_hook(void)
+{
+  if (num_entries == 3)
+    update_section_order(section_list, num_entries);
+
+  return LDPS_OK;
+}
+