OSDN Git Service

* incremental.cc (Incremental_inputs::report_command_line): Ignore
authorccoutant <ccoutant>
Wed, 6 Jul 2011 21:19:31 +0000 (21:19 +0000)
committerccoutant <ccoutant>
Wed, 6 Jul 2011 21:19:31 +0000 (21:19 +0000)
--incremental-patch option.
* layout.cc (Free_list::allocate): Extend allocation beyond original
end if enabled.
(Layout::make_output_section): Mark sections that should get
patch space.
* options.cc (parse_percent): New function.
* options.h (parse_percent): New function.
(DEFINE_percent): New macro.
(General_options): Add --incremental-patch option.
* output.cc (Output_section::Output_section): Initialize new data
members.
(Output_section::add_input_section): Print section name when out
of patch space.
(Output_section::add_output_section_data): Likewise.
(Output_section::set_final_data_size): Add patch space when
doing --incremental-full.
(Output_section::do_reset_address_and_file_offset): Remove patch
space.
(Output_segment::set_section_list_addresses): Print debug output
only if --incremental-update.
* output.h (Output_section::set_is_patch_space_allowed): New function.
(Output_section::is_patch_space_allowed_): New data member.
(Output_section::patch_space_): New data member.
* parameters.cc (Parameters::incremental_full): New function.
* parameters.h (Parameters::incremental_full): New function
* testsuite/Makefile.am (incremental_test_2): Add test for
--incremental-patch option.
* testsuite/Makefile.in: Regenerate.
* testsuite/two_file_test_1_v1.cc (t1, t2, t3): Add comments.
(t18): Remove function body.

12 files changed:
gold/ChangeLog
gold/incremental.cc
gold/layout.cc
gold/options.cc
gold/options.h
gold/output.cc
gold/output.h
gold/parameters.cc
gold/parameters.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/two_file_test_1_v1.cc

index ec8e8f1..f975788 100644 (file)
@@ -1,3 +1,37 @@
+2011-07-06  Cary Coutant  <ccoutant@google.com>
+
+       * incremental.cc (Incremental_inputs::report_command_line): Ignore
+       --incremental-patch option.
+       * layout.cc (Free_list::allocate): Extend allocation beyond original
+       end if enabled.
+       (Layout::make_output_section): Mark sections that should get
+       patch space.
+       * options.cc (parse_percent): New function.
+       * options.h (parse_percent): New function.
+       (DEFINE_percent): New macro.
+       (General_options): Add --incremental-patch option.
+       * output.cc (Output_section::Output_section): Initialize new data
+       members.
+       (Output_section::add_input_section): Print section name when out
+       of patch space.
+       (Output_section::add_output_section_data): Likewise.
+       (Output_section::set_final_data_size): Add patch space when
+       doing --incremental-full.
+       (Output_section::do_reset_address_and_file_offset): Remove patch
+       space.
+       (Output_segment::set_section_list_addresses): Print debug output
+       only if --incremental-update.
+       * output.h (Output_section::set_is_patch_space_allowed): New function.
+       (Output_section::is_patch_space_allowed_): New data member.
+       (Output_section::patch_space_): New data member.
+       * parameters.cc (Parameters::incremental_full): New function.
+       * parameters.h (Parameters::incremental_full): New function
+       * testsuite/Makefile.am (incremental_test_2): Add test for
+       --incremental-patch option.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/two_file_test_1_v1.cc (t1, t2, t3): Add comments.
+       (t18): Remove function body.
+
 2011-07-05  Doug Kwan  <dougkwan@google.com>
 
        PR gold/12771
index c92bb07..f0be7f0 100644 (file)
@@ -925,9 +925,11 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
          || strcmp(argv[i], "--incremental-unchanged") == 0
          || strcmp(argv[i], "--incremental-unknown") == 0
          || is_prefix_of("--incremental-base=", argv[i])
+         || is_prefix_of("--incremental-patch=", argv[i])
          || is_prefix_of("--debug=", argv[i]))
         continue;
       if (strcmp(argv[i], "--incremental-base") == 0
+         || strcmp(argv[i], "--incremental-patch") == 0
          || strcmp(argv[i], "--debug") == 0)
        {
          // When these options are used without the '=', skip the
index e6fd7e5..3c3b5b3 100644 (file)
@@ -168,6 +168,11 @@ Free_list::allocate(off_t len, uint64_t align, off_t minoff)
       off_t start = p->start_ > minoff ? p->start_ : minoff;
       start = align_address(start, align);
       off_t end = start + len;
+      if (end > p->end_ && p->end_ == this->length_ && this->extend_)
+       {
+         this->length_ = end;
+         p->end_ = end;
+       }
       if (end <= p->end_)
        {
          if (p->start_ + 3 >= start && p->end_ <= end + 3)
@@ -186,6 +191,12 @@ Free_list::allocate(off_t len, uint64_t align, off_t minoff)
          return start;
        }
     }
+  if (this->extend_)
+    {
+      off_t start = align_address(this->length_, align);
+      this->length_ = start + len;
+      return start;
+    }
   return -1;
 }
 
@@ -1413,6 +1424,21 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
       && strcmp(name + strlen(name) - 3, "str") == 0)
     this->have_stabstr_section_ = true;
 
+  // During a full incremental link, we add patch space to most
+  // PROGBITS and NOBITS sections.  Flag those that may be
+  // arbitrarily padded.
+  if ((type == elfcpp::SHT_PROGBITS || type == elfcpp::SHT_NOBITS)
+      && order != ORDER_INTERP
+      && order != ORDER_INIT
+      && order != ORDER_PLT
+      && order != ORDER_FINI
+      && order != ORDER_RELRO_LAST
+      && order != ORDER_NON_RELRO_FIRST
+      && strcmp(name, ".ctors") != 0
+      && strcmp(name, ".dtors") != 0
+      && strcmp(name, ".jcr") != 0)
+    os->set_is_patch_space_allowed();
+
   // If we have already attached the sections to segments, then we
   // need to attach this one now.  This happens for sections created
   // directly by the linker.
index f1dc1cb..05d6f88 100644 (file)
@@ -235,6 +235,17 @@ parse_double(const char* option_name, const char* arg, double* retval)
 }
 
 void
+parse_percent(const char* option_name, const char* arg, double* retval)
+{
+  char* endptr;
+  *retval = strtod(arg, &endptr) / 100.0;
+  if (*endptr != '\0')
+    gold_fatal(_("%s: invalid option value "
+                "(expected a floating point number): %s"),
+              option_name, arg);
+}
+
+void
 parse_string(const char* option_name, const char* arg, const char** retval)
 {
   if (*arg == '\0')
index 57d5810..c73bd45 100644 (file)
@@ -98,6 +98,9 @@ extern void
 parse_double(const char* option_name, const char* arg, double* retval);
 
 extern void
+parse_percent(const char* option_name, const char* arg, double* retval);
+
+extern void
 parse_string(const char* option_name, const char* arg, const char** retval);
 
 extern void
@@ -372,6 +375,12 @@ struct Struct_special : public Struct_var
             #default_value__, helpstring__, helparg__, false,           \
             double, double, options::parse_double)
 
+#define DEFINE_percent(varname__, dashes__, shortname__, default_value__, \
+                      helpstring__, helparg__)                           \
+  DEFINE_var(varname__, dashes__, shortname__, default_value__ / 100.0,          \
+            #default_value__, helpstring__, helparg__, false,            \
+            double, double, options::parse_percent)
+
 #define DEFINE_string(varname__, dashes__, shortname__, default_value__, \
                       helpstring__, helparg__)                           \
   DEFINE_var(varname__, dashes__, shortname__, default_value__,          \
@@ -813,6 +822,10 @@ class General_options
   DEFINE_special(incremental_unknown, options::TWO_DASHES, '\0',
                  N_("Use timestamps to check files (default)"), NULL);
 
+  DEFINE_percent(incremental_patch, options::TWO_DASHES, '\0', 10,
+                N_("Amount of extra space to allocate for patches"),
+                N_("PERCENT"));
+
   DEFINE_string(init, options::ONE_DASH, '\0', "_init",
                 N_("Call SYMBOL at load-time"), N_("SYMBOL"));
 
index 8a781c5..b9cfafd 100644 (file)
@@ -2153,10 +2153,12 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     is_noload_(false),
     always_keeps_input_sections_(false),
     has_fixed_layout_(false),
+    is_patch_space_allowed_(false),
     tls_offset_(0),
     checkpoint_(NULL),
     lookup_maps_(new Output_section_lookup_maps),
-    free_list_()
+    free_list_(),
+    patch_space_(0)
 {
   // An unallocated section has no address.  Forcing this means that
   // we don't need special treatment for symbols defined in debug
@@ -2271,7 +2273,9 @@ Output_section::add_input_section(Layout* layout,
       offset_in_section = this->free_list_.allocate(input_section_size,
                                                    addralign, 0);
       if (offset_in_section == -1)
-        gold_fallback(_("out of patch space; relink with --incremental-full"));
+        gold_fallback(_("out of patch space in section %s; "
+                       "relink with --incremental-full"),
+                     this->name());
       aligned_offset_in_section = offset_in_section;
     }
   else
@@ -2375,8 +2379,9 @@ Output_section::add_output_section_data(Output_section_data* posd)
          offset_in_section = this->free_list_.allocate(posd->data_size(),
                                                        posd->addralign(), 0);
          if (offset_in_section == -1)
-           gold_fallback(_("out of patch space; "
-                           "relink with --incremental-full"));
+           gold_fallback(_("out of patch space in section %s; "
+                           "relink with --incremental-full"),
+                         this->name());
          // Finalize the address and offset now.
          uint64_t addr = this->address();
          off_t offset = this->offset();
@@ -2946,30 +2951,48 @@ Output_section::update_data_size()
 void
 Output_section::set_final_data_size()
 {
+  off_t data_size;
+
   if (this->input_sections_.empty())
+    data_size = this->current_data_size_for_child();
+  else
     {
-      this->set_data_size(this->current_data_size_for_child());
-      return;
-    }
+      if (this->must_sort_attached_input_sections()
+         || this->input_section_order_specified())
+       this->sort_attached_input_sections();
 
-  if (this->must_sort_attached_input_sections()
-      || this->input_section_order_specified())
-    this->sort_attached_input_sections();
+      uint64_t address = this->address();
+      off_t startoff = this->offset();
+      off_t off = startoff + this->first_input_offset_;
+      for (Input_section_list::iterator p = this->input_sections_.begin();
+          p != this->input_sections_.end();
+          ++p)
+       {
+         off = align_address(off, p->addralign());
+         p->set_address_and_file_offset(address + (off - startoff), off,
+                                        startoff);
+         off += p->data_size();
+       }
+      data_size = off - startoff;
+    }
 
-  uint64_t address = this->address();
-  off_t startoff = this->offset();
-  off_t off = startoff + this->first_input_offset_;
-  for (Input_section_list::iterator p = this->input_sections_.begin();
-       p != this->input_sections_.end();
-       ++p)
+  // For full incremental links, we want to allocate some patch space
+  // in most sections for subsequent incremental updates.
+  if (this->is_patch_space_allowed_ && parameters->incremental_full())
     {
-      off = align_address(off, p->addralign());
-      p->set_address_and_file_offset(address + (off - startoff), off,
-                                    startoff);
-      off += p->data_size();
+      double pct = parameters->options().incremental_patch();
+      off_t extra = static_cast<off_t>(data_size * pct);
+      off_t new_size = align_address(data_size + extra, this->addralign());
+      this->patch_space_ = new_size - data_size;
+      gold_debug(DEBUG_INCREMENTAL,
+                "set_final_data_size: %08lx + %08lx: section %s",
+                static_cast<long>(data_size),
+                static_cast<long>(this->patch_space_),
+                this->name());
+      data_size = new_size;
     }
 
-  this->set_data_size(off - startoff);
+  this->set_data_size(data_size);
 }
 
 // Reset the address and file offset.
@@ -2988,8 +3011,16 @@ Output_section::do_reset_address_and_file_offset()
        p != this->input_sections_.end();
        ++p)
     p->reset_address_and_file_offset();
+
+  // Remove any patch space that was added in set_final_data_size.
+  if (this->patch_space_ > 0)
+    {
+      this->set_current_data_size_for_child(this->current_data_size_for_child()
+                                           - this->patch_space_);
+      this->patch_space_ = 0;
+    }
 }
-  
+
 // Return true if address and file offset have the values after reset.
 
 bool
@@ -4265,14 +4296,15 @@ Output_segment::set_section_list_addresses(Layout* layout, bool reset,
          (*p)->finalize_data_size();
        }
 
-      gold_debug(DEBUG_INCREMENTAL,
-                "set_section_list_addresses: %08lx %08lx %s",
-                static_cast<long>(off),
-                static_cast<long>((*p)->data_size()),
-                ((*p)->output_section() != NULL
-                 ? (*p)->output_section()->name() : "(special)"));
-
-      // We want to ignore the size of a SHF_TLS or SHT_NOBITS
+      if (parameters->incremental_update())
+       gold_debug(DEBUG_INCREMENTAL,
+                  "set_section_list_addresses: %08lx %08lx %s",
+                  static_cast<long>(off),
+                  static_cast<long>((*p)->data_size()),
+                  ((*p)->output_section() != NULL
+                   ? (*p)->output_section()->name() : "(special)"));
+
+      // We want to ignore the size of a SHF_TLS SHT_NOBITS
       // section.  Such a section does not affect the size of a
       // PT_LOAD segment.
       if (!(*p)->is_section_flag_set(elfcpp::SHF_TLS)
index 72d1dba..7fb87de 100644 (file)
@@ -3427,6 +3427,12 @@ class Output_section : public Output_data
   has_fixed_layout() const
   { return this->has_fixed_layout_; }
 
+  // Set flag to allow patch space for this section.  Used for full
+  // incremental links.
+  void
+  set_is_patch_space_allowed()
+  { this->is_patch_space_allowed_ = true; }
+
   // Reserve space within the fixed layout for the section.  Used for
   // incremental update links.
   void
@@ -3890,6 +3896,8 @@ class Output_section : public Output_data
   bool always_keeps_input_sections_ : 1;
   // Whether this section has a fixed layout, for incremental update links.
   bool has_fixed_layout_ : 1;
+  // True if we can add patch space to this section.
+  bool is_patch_space_allowed_ : 1;
   // For SHT_TLS sections, the offset of this section relative to the base
   // of the TLS segment.
   uint64_t tls_offset_;
@@ -3900,6 +3908,8 @@ class Output_section : public Output_data
   // List of available regions within the section, for incremental
   // update links.
   Free_list free_list_;
+  // Amount added as patch space for incremental linking.
+  off_t patch_space_;
 };
 
 // An output segment.  PT_LOAD segments are built from collections of
index 1b371d8..0384dd6 100644 (file)
@@ -248,6 +248,14 @@ Parameters::incremental() const
   return this->incremental_mode_ != General_options::INCREMENTAL_OFF;
 }
 
+// Return true if we are doing a full incremental link.
+
+bool
+Parameters::incremental_full() const
+{
+  return this->incremental_mode_ == General_options::INCREMENTAL_FULL;
+}
+
 // Return true if we are doing an incremental update.
 
 bool
index 7867503..09b0516 100644 (file)
@@ -159,6 +159,10 @@ class Parameters
   bool
   incremental() const;
 
+  // Return true if we are doing a full incremental link.
+  bool
+  incremental_full() const;
+
   // Return true if we are doing an incremental update.
   bool
   incremental_update() const;
index 9792400..33ae7c8 100644 (file)
@@ -1903,7 +1903,7 @@ MOSTLYCLEANFILES += two_file_test_tmp_2.o
 incremental_test_2: two_file_test_1_v1.o two_file_test_1.o two_file_test_1b.o \
                    two_file_test_2.o two_file_test_main.o gcctestdir/ld
        cp -f two_file_test_1_v1.o two_file_test_tmp_2.o
-       $(CXXLINK) -Wl,--incremental-full -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
+       $(CXXLINK) -Wl,--incremental-full,--incremental-patch=100 -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
        @sleep 1
        cp -f two_file_test_1.o two_file_test_tmp_2.o
        $(CXXLINK) -Wl,--incremental-update -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
index 5295c52..a25b012 100644 (file)
@@ -4783,7 +4783,7 @@ uninstall-am:
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@incremental_test_2: two_file_test_1_v1.o two_file_test_1.o two_file_test_1b.o \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@                 two_file_test_2.o two_file_test_main.o gcctestdir/ld
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     cp -f two_file_test_1_v1.o two_file_test_tmp_2.o
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(CXXLINK) -Wl,--incremental-full -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(CXXLINK) -Wl,--incremental-full,--incremental-patch=100 -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     @sleep 1
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     cp -f two_file_test_1.o two_file_test_tmp_2.o
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(CXXLINK) -Wl,--incremental-update -Bgcctestdir/ two_file_test_tmp_2.o two_file_test_1b.o two_file_test_2.o two_file_test_main.o
index 6a43d9b..2a23654 100644 (file)
@@ -62,7 +62,7 @@
 bool
 t1()
 {
-  return t1_2() == 0;
+  return t1_2() == 0;  // Intentionally wrong.
 }
 
 // 2  Code in file 1 refers to global data in file 2.
@@ -70,7 +70,7 @@ t1()
 bool
 t2()
 {
-  return v2 == 0;
+  return v2 == 0;  // Intentionally wrong.
 }
 
 // 3  Code in file 1 referes to common symbol in file 2.
@@ -78,7 +78,7 @@ t2()
 bool
 t3()
 {
-  return v3 == 0;
+  return v3 == 0;  // Intentionally wrong.
 }
 
 // 4  Code in file 1 refers to offset within global data in file 2.
@@ -231,13 +231,6 @@ t17()
 bool
 t18()
 {
-  char c = 'a';
-  for (int i = 0; i < T17_COUNT; ++i)
-    {
-      const char* s = f18(i);
-      if (s[0] != c || s[1] != '\0')
-        return false;
-      ++c;
-    }
+  // Stubbed out; full implementation in two_file_test_1.cc.
   return true;
 }