* common.cc (Symbol_table::do_allocate_commons_list): For incremental
authorCary Coutant <ccoutant@google.com>
Wed, 8 Jun 2011 04:05:25 +0000 (04:05 +0000)
committerCary Coutant <ccoutant@google.com>
Wed, 8 Jun 2011 04:05:25 +0000 (04:05 +0000)
update, allocate common from bss section's free list.
* incremental-dump.cc (dump_incremental_inputs): Print flag for
linker-defined symbols.
* incremental.cc (Sized_incremental_binary::do_process_got_plt):
Skip GOT and PLT entries that are no longer referenced.
(Output_section_incremental_inputs::write_info_blocks): Mark
linker-defined symbols.
(Sized_incr_relobj::do_add_symbols): Process linker-defined symbols.
* output.cc (Output_section::allocate): New function.
* output.h (Output_section::allocate): New function.
* resolve.cc (Symbol_table::report_resolve_problem): Add case for
linker-defined symbols.
(Symbol::override_base_with_special): Copy is_predefined_ flag.
* symtab.cc (Symbol::init_fields): Initialize is_predefined_ flag.
(Symbol::init_base_output_data): Likewise.
(Symbol::init_base_output_segment): Likewise.
(Symbol::init_base_constant): Likewise.
(Sized_symbol::init_output_data): Likewise.
(Sized_symbol::init_output_segment): Likewise.
(Sized_symbol::init_constant): Likewise.
(Symbol_table::do_define_in_output_data): Likewise.
(Symbol_table::do_define_in_output_segment): Likewise.
(Symbol_table::do_define_as_constant): Likewise.
* symtab.h (Symbol::is_predefined): New function.
(Symbol::init_base_output_data): Add is_predefined parameter.
(Symbol::init_base_output_segment): Likewise.
(Symbol::init_base_constant): Likewise.
(Symbol::is_predefined_): New data member.
(Sized_symbol::init_output_data): Add is_predefined parameter.
(Sized_symbol::init_output_segment): Likewise.
(Sized_symbol::init_constant): Likewise.
(enum Symbol_table::Defined): Add INCREMENTAL_BASE.

gold/ChangeLog
gold/common.cc
gold/incremental-dump.cc
gold/incremental.cc
gold/output.cc
gold/output.h
gold/resolve.cc
gold/symtab.cc
gold/symtab.h

index 2626867eae126821ad7ed063f6d41d172fe36be2..867d776306d237ce21fe9c665d6275767550dc15 100644 (file)
@@ -1,3 +1,39 @@
+2011-06-07  Cary Coutant  <ccoutant@google.com>
+
+       * common.cc (Symbol_table::do_allocate_commons_list): For incremental
+       update, allocate common from bss section's free list.
+       * incremental-dump.cc (dump_incremental_inputs): Print flag for
+       linker-defined symbols.
+       * incremental.cc (Sized_incremental_binary::do_process_got_plt):
+       Skip GOT and PLT entries that are no longer referenced.
+       (Output_section_incremental_inputs::write_info_blocks): Mark
+       linker-defined symbols.
+       (Sized_incr_relobj::do_add_symbols): Process linker-defined symbols.
+       * output.cc (Output_section::allocate): New function.
+       * output.h (Output_section::allocate): New function.
+       * resolve.cc (Symbol_table::report_resolve_problem): Add case for
+       linker-defined symbols.
+       (Symbol::override_base_with_special): Copy is_predefined_ flag.
+       * symtab.cc (Symbol::init_fields): Initialize is_predefined_ flag.
+       (Symbol::init_base_output_data): Likewise.
+       (Symbol::init_base_output_segment): Likewise.
+       (Symbol::init_base_constant): Likewise.
+       (Sized_symbol::init_output_data): Likewise.
+       (Sized_symbol::init_output_segment): Likewise.
+       (Sized_symbol::init_constant): Likewise.
+       (Symbol_table::do_define_in_output_data): Likewise.
+       (Symbol_table::do_define_in_output_segment): Likewise.
+       (Symbol_table::do_define_as_constant): Likewise.
+       * symtab.h (Symbol::is_predefined): New function.
+       (Symbol::init_base_output_data): Add is_predefined parameter.
+       (Symbol::init_base_output_segment): Likewise.
+       (Symbol::init_base_constant): Likewise.
+       (Symbol::is_predefined_): New data member.
+       (Sized_symbol::init_output_data): Add is_predefined parameter.
+       (Sized_symbol::init_output_segment): Likewise.
+       (Sized_symbol::init_constant): Likewise.
+       (enum Symbol_table::Defined): Add INCREMENTAL_BASE.
+
 2011-06-07  Cary Coutant  <ccoutant@google.com>
 
        * copy-relocs.cc (Copy_relocs::copy_reloc): Call make_copy_reloc
index 6acd2b5bd783acad3936e5644bcd1b13cf6fb0cf..bffa8290d933d1d34923ac53aaa13c000134aa59 100644 (file)
@@ -286,12 +286,23 @@ Symbol_table::do_allocate_commons_list(
       gold_unreachable();
     }
 
-  Output_data_space* poc = new Output_data_space(addralign, ds_name);
-  Output_section* os = layout->add_output_section_data(name,
-                                                      elfcpp::SHT_NOBITS,
-                                                      flags, poc,
-                                                      ORDER_INVALID,
-                                                      false);
+  Output_data_space* poc;
+  Output_section* os;
+
+  if (!parameters->incremental_update())
+    {
+      poc = new Output_data_space(addralign, ds_name);
+      os = layout->add_output_section_data(name, elfcpp::SHT_NOBITS, flags,
+                                          poc, ORDER_INVALID, false);
+    }
+  else
+    {
+      // When doing an incremental update, we need to allocate each common
+      // directly from the output section's free list.
+      poc = NULL;
+      os = layout->find_output_section(name);
+    }
+
   if (os != NULL)
     {
       if (commons_section_type == COMMONS_SMALL)
@@ -329,12 +340,26 @@ Symbol_table::do_allocate_commons_list(
       if (mapfile != NULL)
        mapfile->report_allocate_common(sym, ssym->symsize());
 
-      off = align_address(off, ssym->value());
-      ssym->allocate_common(poc, off);
-      off += ssym->symsize();
+      if (poc != NULL)
+       {
+         off = align_address(off, ssym->value());
+         ssym->allocate_common(poc, off);
+         off += ssym->symsize();
+       }
+      else
+       {
+         // For an incremental update, allocate from the free list.
+         off = os->allocate(ssym->symsize(), ssym->value());
+         if (off == -1)
+           gold_fatal(_("out of patch space in section %s; "
+                        "relink with --incremental-full"),
+                        os->name());
+         ssym->allocate_common(os, off);
+       }
     }
 
-  poc->set_current_data_size(off);
+  if (poc != NULL)
+    poc->set_current_data_size(off);
 
   commons->clear();
 }
index e7e838aaaf8466a7949676bfc52298539d14caf6..fb3d25f2813b7d6c66c03ff30c3a04f960f95191 100644 (file)
@@ -322,12 +322,14 @@ dump_incremental_inputs(const char* argv0, const char* filename,
                symname = "<unknown>";
              printf("    %6d  %6d  %8d  %8d  %8d  %8d  %-5s  %s\n",
                     output_symndx,
-                    info.shndx(),
+                    info.shndx() == -1U ? -1 : info.shndx(),
                     input_file.get_symbol_offset(symndx),
                     info.next_offset(),
                     info.reloc_count(),
                     info.reloc_offset(),
-                    info.shndx() != elfcpp::SHN_UNDEF ? "DEF" : "UNDEF",
+                    (info.shndx() == -1U
+                     ? "BASE"
+                     : info.shndx() == 0 ? "UNDEF" : "DEF"),
                     symname);
            }
        }
index 98f09d073743bc9696417efb1cc13ac6e1c9df1a..c92bb07aa5577ab0af536b3819a7898eec478d97 100644 (file)
@@ -630,10 +630,14 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt(
          // FIXME: This should really be a fatal error (corrupt input).
          gold_assert(symndx >= first_global && symndx < symtab_count);
          Symbol* sym = this->global_symbol(symndx - first_global);
-         gold_debug(DEBUG_INCREMENTAL,
-                    "GOT entry %d, type %02x: %s",
-                    i, got_type, sym->name());
-         target->reserve_global_got_entry(i, sym, got_type);
+         // Add the GOT entry only if the symbol is still referenced.
+         if (sym != NULL && sym->in_reg())
+           {
+             gold_debug(DEBUG_INCREMENTAL,
+                        "GOT entry %d, type %02x: %s",
+                        i, got_type, sym->name());
+             target->reserve_global_got_entry(i, sym, got_type);
+           }
        }
     }
 
@@ -644,10 +648,14 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt(
       // FIXME: This should really be a fatal error (corrupt input).
       gold_assert(plt_desc >= first_global && plt_desc < symtab_count);
       Symbol* sym = this->global_symbol(plt_desc - first_global);
-      gold_debug(DEBUG_INCREMENTAL,
-                "PLT entry %d: %s",
-                i, sym->name());
-      target->register_global_plt_entry(i, sym);
+      // Add the PLT entry only if the symbol is still referenced.
+      if (sym->in_reg())
+       {
+         gold_debug(DEBUG_INCREMENTAL,
+                    "PLT entry %d: %s",
+                    i, sym->name());
+         target->register_global_plt_entry(i, sym);
+       }
     }
 }
 
@@ -1548,14 +1556,24 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
                if (sym->is_forwarder())
                  sym = this->symtab_->resolve_forwards(sym);
                unsigned int shndx = 0;
-               if (sym->source() == Symbol::FROM_OBJECT
-                   && sym->object() == obj
-                   && sym->is_defined())
+               if (sym->source() != Symbol::FROM_OBJECT)
+                 {
+                   // The symbol was defined by the linker (e.g., common).
+                   // We mark these symbols with a special SHNDX of -1,
+                   // but exclude linker-predefined symbols and symbols
+                   // copied from shared objects.
+                   if (!sym->is_predefined()
+                       && !sym->is_copied_from_dynobj())
+                     shndx = -1U;
+                 }
+               else if (sym->object() == obj && sym->is_defined())
                  {
                    bool is_ordinary;
                    unsigned int orig_shndx = sym->shndx(&is_ordinary);
                    if (is_ordinary)
                      shndx = index_map[orig_shndx];
+                   else
+                     shndx = 1;
                  }
                unsigned int symtab_index = sym->symtab_index();
                unsigned int chain = 0;
@@ -2026,7 +2044,7 @@ Sized_relobj_incr<size, big_endian>::do_add_symbols(
         st_bind = elfcpp::STB_GLOBAL;
 
       unsigned int input_shndx = info.shndx();
-      if (input_shndx == 0)
+      if (input_shndx == 0 || input_shndx == -1U)
        {
          shndx = elfcpp::SHN_UNDEF;
          v = 0;
@@ -2053,10 +2071,40 @@ Sized_relobj_incr<size, big_endian>::do_add_symbols(
       osym.put_st_other(gsym.get_st_other());
       osym.put_st_shndx(shndx);
 
-      this->symbols_[i] =
-       symtab->add_from_incrobj(this, name, NULL, &sym);
-      this->ibase_->add_global_symbol(output_symndx - first_global,
-                                     this->symbols_[i]);
+      Symbol* res = symtab->add_from_incrobj(this, name, NULL, &sym);
+
+      // If this is a linker-defined symbol that hasn't yet been defined,
+      // define it now.
+      if (input_shndx == -1U && !res->is_defined())
+       {
+         shndx = gsym.get_st_shndx();
+         v = gsym.get_st_value();
+         Elf_size_type symsize = gsym.get_st_size();
+         if (shndx == elfcpp::SHN_ABS)
+           {
+             symtab->define_as_constant(name, NULL,
+                                        Symbol_table::INCREMENTAL_BASE,
+                                        v, symsize, st_type, st_bind,
+                                        gsym.get_st_visibility(), 0,
+                                        false, false);
+           }
+         else
+           {
+             Output_section* os = this->ibase_->output_section(shndx);
+             gold_assert(os != NULL && os->has_fixed_layout());
+             v -= os->address();
+             if (symsize > 0)
+               os->reserve(v, symsize);
+             symtab->define_in_output_data(name, NULL,
+                                           Symbol_table::INCREMENTAL_BASE,
+                                           os, v, symsize, st_type, st_bind,
+                                           gsym.get_st_visibility(), 0,
+                                           false, false);
+           }
+       }
+
+      this->symbols_[i] = res;
+      this->ibase_->add_global_symbol(output_symndx - first_global, res);
     }
 }
 
index 3f6cb7045c4f448fbe46f2d3c14dacf9b19e7314..0134d338ddaf2492f69356785c8e1e43fdc3b18b 100644 (file)
@@ -3726,12 +3726,22 @@ Output_section::set_fixed_layout(uint64_t sh_addr, off_t sh_offset,
 
 // Reserve space within the fixed layout for the section.  Used for
 // incremental update links.
+
 void
 Output_section::reserve(uint64_t sh_offset, uint64_t sh_size)
 {
   this->free_list_.remove(sh_offset, sh_offset + sh_size);
 }
 
+// Allocate space from the free list for the section.  Used for
+// incremental update links.
+
+off_t
+Output_section::allocate(off_t len, uint64_t addralign)
+{
+  return this->free_list_.allocate(len, addralign, 0);
+}
+
 // Output segment methods.
 
 Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
index 86c308ff73ae57f51ccc6c791e36a52912267ae5..72d1dbaf5e0b87bd5e37fbf8679a907cea8e3fbc 100644 (file)
@@ -3432,6 +3432,11 @@ class Output_section : public Output_data
   void
   reserve(uint64_t sh_offset, uint64_t sh_size);
 
+  // Allocate space from the free list for the section.  Used for
+  // incremental update links.
+  off_t
+  allocate(off_t len, uint64_t addralign);
+
  protected:
   // Return the output section--i.e., the object itself.
   Output_section*
index a9a89fa65d68dfee86dffafebd212abdbd30f9a3..fd0fea6b13a5b4005a2ae30c1e39cb4d3c1bdb30 100644 (file)
@@ -830,6 +830,7 @@ Symbol_table::report_resolve_problem(bool is_error, const char* msg,
       objname = _("linker script");
       break;
     case PREDEFINED:
+    case INCREMENTAL_BASE:
       objname = _("linker defined");
       break;
     default:
@@ -908,6 +909,8 @@ Symbol::override_base_with_special(const Symbol* from)
   if (from->needs_dynsym_value_)
     this->needs_dynsym_value_ = true;
 
+  this->is_predefined_ = from->is_predefined_;
+
   // We shouldn't see these flags.  If we do, we need to handle them
   // somehow.
   gold_assert(!from->is_forwarder_);
index 12e2762bdd0048273684ac74139822884b7fec6b..92f83af852b56bdc3da38386b2ab2e3429abfd1a 100644 (file)
@@ -79,6 +79,7 @@ Symbol::init_fields(const char* name, const char* version,
   this->is_defined_in_discarded_section_ = false;
   this->undef_binding_set_ = false;
   this->undef_binding_weak_ = false;
+  this->is_predefined_ = false;
 }
 
 // Return the demangled version of the symbol's name, but only
@@ -133,7 +134,8 @@ void
 Symbol::init_base_output_data(const char* name, const char* version,
                              Output_data* od, elfcpp::STT type,
                              elfcpp::STB binding, elfcpp::STV visibility,
-                             unsigned char nonvis, bool offset_is_from_end)
+                             unsigned char nonvis, bool offset_is_from_end,
+                             bool is_predefined)
 {
   this->init_fields(name, version, type, binding, visibility, nonvis);
   this->u_.in_output_data.output_data = od;
@@ -141,6 +143,7 @@ Symbol::init_base_output_data(const char* name, const char* version,
   this->source_ = IN_OUTPUT_DATA;
   this->in_reg_ = true;
   this->in_real_elf_ = true;
+  this->is_predefined_ = is_predefined;
 }
 
 // Initialize the fields in the base class Symbol for a symbol defined
@@ -151,7 +154,8 @@ Symbol::init_base_output_segment(const char* name, const char* version,
                                 Output_segment* os, elfcpp::STT type,
                                 elfcpp::STB binding, elfcpp::STV visibility,
                                 unsigned char nonvis,
-                                Segment_offset_base offset_base)
+                                Segment_offset_base offset_base,
+                                bool is_predefined)
 {
   this->init_fields(name, version, type, binding, visibility, nonvis);
   this->u_.in_output_segment.output_segment = os;
@@ -159,6 +163,7 @@ Symbol::init_base_output_segment(const char* name, const char* version,
   this->source_ = IN_OUTPUT_SEGMENT;
   this->in_reg_ = true;
   this->in_real_elf_ = true;
+  this->is_predefined_ = is_predefined;
 }
 
 // Initialize the fields in the base class Symbol for a symbol defined
@@ -167,12 +172,14 @@ Symbol::init_base_output_segment(const char* name, const char* version,
 void
 Symbol::init_base_constant(const char* name, const char* version,
                           elfcpp::STT type, elfcpp::STB binding,
-                          elfcpp::STV visibility, unsigned char nonvis)
+                          elfcpp::STV visibility, unsigned char nonvis,
+                          bool is_predefined)
 {
   this->init_fields(name, version, type, binding, visibility, nonvis);
   this->source_ = IS_CONSTANT;
   this->in_reg_ = true;
   this->in_real_elf_ = true;
+  this->is_predefined_ = is_predefined;
 }
 
 // Initialize the fields in the base class Symbol for an undefined
@@ -227,10 +234,11 @@ Sized_symbol<size>::init_output_data(const char* name, const char* version,
                                     elfcpp::STB binding,
                                     elfcpp::STV visibility,
                                     unsigned char nonvis,
-                                    bool offset_is_from_end)
+                                    bool offset_is_from_end,
+                                    bool is_predefined)
 {
   this->init_base_output_data(name, version, od, type, binding, visibility,
-                             nonvis, offset_is_from_end);
+                             nonvis, offset_is_from_end, is_predefined);
   this->value_ = value;
   this->symsize_ = symsize;
 }
@@ -246,10 +254,11 @@ Sized_symbol<size>::init_output_segment(const char* name, const char* version,
                                        elfcpp::STB binding,
                                        elfcpp::STV visibility,
                                        unsigned char nonvis,
-                                       Segment_offset_base offset_base)
+                                       Segment_offset_base offset_base,
+                                       bool is_predefined)
 {
   this->init_base_output_segment(name, version, os, type, binding, visibility,
-                                nonvis, offset_base);
+                                nonvis, offset_base, is_predefined);
   this->value_ = value;
   this->symsize_ = symsize;
 }
@@ -262,9 +271,11 @@ void
 Sized_symbol<size>::init_constant(const char* name, const char* version,
                                  Value_type value, Size_type symsize,
                                  elfcpp::STT type, elfcpp::STB binding,
-                                 elfcpp::STV visibility, unsigned char nonvis)
+                                 elfcpp::STV visibility, unsigned char nonvis,
+                                 bool is_predefined)
 {
-  this->init_base_constant(name, version, type, binding, visibility, nonvis);
+  this->init_base_constant(name, version, type, binding, visibility, nonvis,
+                          is_predefined);
   this->value_ = value;
   this->symsize_ = symsize;
 }
@@ -1843,7 +1854,8 @@ Symbol_table::do_define_in_output_data(
     return NULL;
 
   sym->init_output_data(name, version, od, value, symsize, type, binding,
-                       visibility, nonvis, offset_is_from_end);
+                       visibility, nonvis, offset_is_from_end,
+                       defined == PREDEFINED);
 
   if (oldsym == NULL)
     {
@@ -1956,7 +1968,8 @@ Symbol_table::do_define_in_output_segment(
     return NULL;
 
   sym->init_output_segment(name, version, os, value, symsize, type, binding,
-                          visibility, nonvis, offset_base);
+                          visibility, nonvis, offset_base,
+                          defined == PREDEFINED);
 
   if (oldsym == NULL)
     {
@@ -2068,7 +2081,7 @@ Symbol_table::do_define_as_constant(
     return NULL;
 
   sym->init_constant(name, version, value, symsize, type, binding, visibility,
-                    nonvis);
+                    nonvis, defined == PREDEFINED);
 
   if (oldsym == NULL)
     {
index 43e3efaf35f453bac6dc1bd3209d9a6bc0364eff..51c31d52d6c5b6cd072c5aad44507f44b19c125e 100644 (file)
@@ -803,6 +803,11 @@ class Symbol
            && !this->is_func());
   }
 
+  // Return true if this symbol was predefined by the linker.
+  bool
+  is_predefined() const
+  { return this->is_predefined_; }
+
  protected:
   // Instances of this class should always be created at a specific
   // size.
@@ -828,7 +833,8 @@ class Symbol
   void
   init_base_output_data(const char* name, const char* version, Output_data*,
                        elfcpp::STT, elfcpp::STB, elfcpp::STV,
-                       unsigned char nonvis, bool offset_is_from_end);
+                       unsigned char nonvis, bool offset_is_from_end,
+                       bool is_predefined);
 
   // Initialize fields for an Output_segment.
   void
@@ -836,13 +842,14 @@ class Symbol
                           Output_segment* os, elfcpp::STT type,
                           elfcpp::STB binding, elfcpp::STV visibility,
                           unsigned char nonvis,
-                          Segment_offset_base offset_base);
+                          Segment_offset_base offset_base,
+                          bool is_predefined);
 
   // Initialize fields for a constant.
   void
   init_base_constant(const char* name, const char* version, elfcpp::STT type,
                     elfcpp::STB binding, elfcpp::STV visibility,
-                    unsigned char nonvis);
+                    unsigned char nonvis, bool is_predefined);
 
   // Initialize fields for an undefined symbol.
   void
@@ -991,6 +998,8 @@ class Symbol
   // True if this symbol was a weak undef resolved by a dynamic def
   // (bit 33).
   bool undef_binding_weak_ : 1;
+  // True if this symbol is a predefined linker symbol (bit 34).
+  bool is_predefined_ : 1;
 };
 
 // The parts of a symbol which are size specific.  Using a template
@@ -1020,20 +1029,20 @@ class Sized_symbol : public Symbol
   init_output_data(const char* name, const char* version, Output_data*,
                   Value_type value, Size_type symsize, elfcpp::STT,
                   elfcpp::STB, elfcpp::STV, unsigned char nonvis,
-                  bool offset_is_from_end);
+                  bool offset_is_from_end, bool is_predefined);
 
   // Initialize fields for an Output_segment.
   void
   init_output_segment(const char* name, const char* version, Output_segment*,
                      Value_type value, Size_type symsize, elfcpp::STT,
                      elfcpp::STB, elfcpp::STV, unsigned char nonvis,
-                     Segment_offset_base offset_base);
+                     Segment_offset_base offset_base, bool is_predefined);
 
   // Initialize fields for a constant.
   void
   init_constant(const char* name, const char* version, Value_type value,
                Size_type symsize, elfcpp::STT, elfcpp::STB, elfcpp::STV,
-               unsigned char nonvis);
+               unsigned char nonvis, bool is_predefined);
 
   // Initialize fields for an undefined symbol.
   void
@@ -1250,6 +1259,9 @@ class Symbol_table
     SCRIPT,
     // Predefined by the linker.
     PREDEFINED,
+    // Defined by the linker during an incremental base link, but not
+    // a predefined symbol (e.g., common, defined in script).
+    INCREMENTAL_BASE,
   };
 
   // The order in which we sort common symbols.
This page took 0.038618 seconds and 4 git commands to generate.