* incremental-dump.cc (dump_incremental_inputs): Print COMDAT groups.
authorCary Coutant <ccoutant@google.com>
Thu, 26 May 2011 18:44:27 +0000 (18:44 +0000)
committerCary Coutant <ccoutant@google.com>
Thu, 26 May 2011 18:44:27 +0000 (18:44 +0000)
* incremental.cc (Incremental_inputs::report_input_section): Fix
comment, indentation.
(Incremental_inputs::report_comdat_group): New function.
(Output_section_incremental_inputs::set_final_data_size): Adjust size
of data for incremental input file entry.
(Output_section_incremental_inputs::write_info_blocks): Write COMDAT
group count, COMDAT group signatures.
(Sized_incr_relobj::do_layout): Record kept COMDAT group info from
an unchanged input file.
* incremental.h (Incremental_object_entry::Incremental_object_entry):
Initialize new data member.
(Incremental_object_entry::add_comdat_group): New function.
(Incremental_object_entry::get_comdat_group_count): New function.
(Incremental_object_entry::get_comdat_signature_key): New function.
(Incremental_object_entry::groups_): New data member.
(Incremental_inputs::report_comdat_group): New function.
(Incremental_input_entry_reader::get_symbol_offset): Adjust size of
data for incremental input file entry.
(Incremental_input_entry_reader::get_comdat_group_count): New function.
(Incremental_input_entry_reader::get_input_section): Adjust size of
data for incremental input file entry.
(Incremental_input_entry_reader::get_global_symbol_reader): Likewise.
(Incremental_input_entry_reader::get_comdat_group_signature): New
function.
* object.cc (Sized_relobj::include_section_group): Report kept
COMDAT groups for incremental links.

gold/ChangeLog
gold/incremental-dump.cc
gold/incremental.cc
gold/incremental.h
gold/object.cc

index 292d301..4e92270 100644 (file)
@@ -1,3 +1,33 @@
+2011-05-26 Cary Coutant  <ccoutant@google.com>
+
+       * incremental-dump.cc (dump_incremental_inputs): Print COMDAT groups.
+       * incremental.cc (Incremental_inputs::report_input_section): Fix
+       comment, indentation.
+       (Incremental_inputs::report_comdat_group): New function.
+       (Output_section_incremental_inputs::set_final_data_size): Adjust size
+       of data for incremental input file entry.
+       (Output_section_incremental_inputs::write_info_blocks): Write COMDAT
+       group count, COMDAT group signatures.
+       (Sized_incr_relobj::do_layout): Record kept COMDAT group info from
+       an unchanged input file.
+       * incremental.h (Incremental_object_entry::Incremental_object_entry):
+       Initialize new data member.
+       (Incremental_object_entry::add_comdat_group): New function.
+       (Incremental_object_entry::get_comdat_group_count): New function.
+       (Incremental_object_entry::get_comdat_signature_key): New function.
+       (Incremental_object_entry::groups_): New data member.
+       (Incremental_inputs::report_comdat_group): New function.
+       (Incremental_input_entry_reader::get_symbol_offset): Adjust size of
+       data for incremental input file entry.
+       (Incremental_input_entry_reader::get_comdat_group_count): New function.
+       (Incremental_input_entry_reader::get_input_section): Adjust size of
+       data for incremental input file entry.
+       (Incremental_input_entry_reader::get_global_symbol_reader): Likewise.
+       (Incremental_input_entry_reader::get_comdat_group_signature): New
+       function.
+       * object.cc (Sized_relobj::include_section_group): Report kept
+       COMDAT groups for incremental links.
+
 2011-05-24  David Meyer  <pdox@google.com>
 
        * dirsearch.cc (Dirsearch::find): Replace n1 and n2 parameters
index a727eb5..fff4637 100644 (file)
@@ -153,6 +153,8 @@ dump_incremental_inputs(const char* argv0, const char* filename,
                 input_file.get_first_dyn_reloc());
          printf("    Dynamic reloc count: %d\n",
                 input_file.get_dyn_reloc_count());
+         printf("    COMDAT group count: %d\n",
+                input_file.get_comdat_group_count());
          break;
        case INCREMENTAL_INPUT_ARCHIVE:
          printf("Archive\n");
@@ -212,6 +214,11 @@ dump_incremental_inputs(const char* argv0, const char* filename,
                 static_cast<long long>(info.sh_size),
                 info.name);
        }
+
+      unsigned int ncomdat = input_file.get_comdat_group_count();
+      for (unsigned int i = 0; i < ncomdat; ++i)
+       printf("    Comdat group: %s\n",
+              input_file.get_comdat_group_signature(i));
     }
 
   // Get a view of the .symtab section.
index a27afee..f4eb22c 100644 (file)
@@ -1028,9 +1028,7 @@ Incremental_inputs::report_object(Object* obj, unsigned int arg_serial,
     }
 }
 
-// Record the input object file OBJ.  If ARCH is not NULL, attach
-// the object file to the archive.  This is called by the
-// Add_symbols task after finding out the type of the file.
+// Record an input section SHNDX from object file OBJ.
 
 void
 Incremental_inputs::report_input_section(Object* obj, unsigned int shndx,
@@ -1039,13 +1037,27 @@ Incremental_inputs::report_input_section(Object* obj, unsigned int shndx,
   Stringpool::Key key = 0;
 
   if (name != NULL)
-      this->strtab_->add(name, true, &key);
+    this->strtab_->add(name, true, &key);
 
   gold_assert(obj == this->current_object_);
   gold_assert(this->current_object_entry_ != NULL);
   this->current_object_entry_->add_input_section(shndx, key, sh_size);
 }
 
+// Record a kept COMDAT group belonging to object file OBJ.
+
+void
+Incremental_inputs::report_comdat_group(Object* obj, const char* name)
+{
+  Stringpool::Key key = 0;
+
+  if (name != NULL)
+    this->strtab_->add(name, true, &key);
+  gold_assert(obj == this->current_object_);
+  gold_assert(this->current_object_entry_ != NULL);
+  this->current_object_entry_->add_comdat_group(key);
+}
+
 // Record that the input argument INPUT is a script SCRIPT.  This is
 // called by read_script after parsing the script and reading the list
 // of inputs added by this script.
@@ -1173,14 +1185,17 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
            gold_assert(entry != NULL);
            (*p)->set_info_offset(info_offset);
            // Input section count, global symbol count, local symbol offset,
-           // local symbol count, first dynamic reloc, dynamic reloc count.
-           info_offset += 24;
+           // local symbol count, first dynamic reloc, dynamic reloc count,
+           // comdat group count.
+           info_offset += 28;
            // Each input section.
            info_offset += (entry->get_input_section_count()
                            * (8 + 2 * sizeof_addr));
            // Each global symbol.
            const Object::Symbols* syms = entry->object()->get_global_symbols();
            info_offset += syms->size() * 20;
+           // Each comdat group.
+           info_offset += entry->get_comdat_group_count() * 4;
          }
          break;
        case INCREMENTAL_INPUT_SHARED_LIBRARY:
@@ -1424,13 +1439,15 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
            unsigned int nlocals = relobj->output_local_symbol_count();
            unsigned int first_dynrel = relobj->first_dyn_reloc();
            unsigned int ndynrel = relobj->dyn_reloc_count();
+           unsigned int ncomdat = entry->get_comdat_group_count();
            Swap32::writeval(pov, nsections);
            Swap32::writeval(pov + 4, nsyms);
            Swap32::writeval(pov + 8, static_cast<unsigned int>(locals_offset));
            Swap32::writeval(pov + 12, nlocals);
            Swap32::writeval(pov + 16, first_dynrel);
            Swap32::writeval(pov + 20, ndynrel);
-           pov += 24;
+           Swap32::writeval(pov + 24, ncomdat);
+           pov += 28;
 
            // Build a temporary array to map input section indexes
            // from the original object file index to the index in the
@@ -1507,6 +1524,17 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
                pov += 20;
              }
 
+           // For each kept COMDAT group, write the group signature.
+           for (unsigned int i = 0; i < ncomdat; i++)
+             {
+               Stringpool::Key key = entry->get_comdat_signature_key(i);
+               off_t name_offset = 0;
+               if (key != 0)
+                 name_offset = strtab->get_offset_from_key(key);
+               Swap32::writeval(pov, name_offset);
+               pov += 4;
+             }
+
            delete[] index_map;
          }
          break;
@@ -1862,6 +1890,20 @@ Sized_relobj_incr<size, big_endian>::do_layout(
       out_sections[i] = os;
       this->section_offsets()[i] = static_cast<Address>(sect.sh_offset);
     }
+
+  // Process the COMDAT groups.
+  unsigned int ncomdat = this->input_reader_.get_comdat_group_count();
+  for (unsigned int i = 0; i < ncomdat; i++)
+    {
+      const char* signature = this->input_reader_.get_comdat_group_signature(i);
+      if (signature == NULL || signature[0] == '\0')
+        this->error(_("COMDAT group has no signature"));
+      bool keep = layout->find_or_add_kept_section(signature, this, i, true,
+                                                  true, NULL);
+      if (!keep)
+        this->error(_("COMDAT group %s included twice in incremental link"),
+                   signature);
+    }
 }
 
 // Layout sections whose layout was deferred while waiting for
index dc8ef33..f1fd1f8 100644 (file)
@@ -325,7 +325,7 @@ class Incremental_object_entry : public Incremental_input_entry
   Incremental_object_entry(Stringpool::Key filename_key, Object* obj,
                           unsigned int arg_serial, Timespec mtime)
     : Incremental_input_entry(filename_key, arg_serial, mtime), obj_(obj),
-      is_member_(false), sections_()
+      is_member_(false), sections_(), groups_()
   { this->sections_.reserve(obj->shnum()); }
 
   // Get the object.
@@ -368,6 +368,21 @@ class Incremental_object_entry : public Incremental_input_entry
   get_input_section_size(unsigned int n) const
   { return this->sections_[n].sh_size_; }
 
+  // Add a kept COMDAT group.
+  void
+  add_comdat_group(Stringpool::Key signature_key)
+  { this->groups_.push_back(signature_key); }
+
+  // Return the number of COMDAT groups.
+  unsigned int
+  get_comdat_group_count() const
+  { return this->groups_.size(); }
+
+  // Return the stringpool key for the signature of the Nth comdat group.
+  Stringpool::Key
+  get_comdat_signature_key(unsigned int n) const
+  { return this->groups_[n]; }
+
  protected:
   virtual Incremental_input_type
   do_type() const
@@ -400,6 +415,9 @@ class Incremental_object_entry : public Incremental_input_entry
     off_t sh_size_;
   };
   std::vector<Input_section> sections_;
+
+  // COMDAT groups.
+  std::vector<Stringpool::Key> groups_;
 };
 
 // Class for recording shared library input files.
@@ -546,6 +564,10 @@ class Incremental_inputs
   report_input_section(Object* obj, unsigned int shndx, const char* name,
                       off_t sh_size);
 
+  // Record a kept COMDAT group belonging to object file OBJ.
+  void
+  report_comdat_group(Object* obj, const char* name);
+
   // Record the info for input script SCRIPT.
   void
   report_script(Script_info* script, unsigned int arg_serial,
@@ -814,7 +836,7 @@ class Incremental_inputs_reader
                  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
 
       unsigned int section_count = this->get_input_section_count();
-      return (this->info_offset_ + 24
+      return (this->info_offset_ + 28
              + section_count * input_section_entry_size
              + symndx * 20);
     }
@@ -869,6 +891,16 @@ class Incremental_inputs_reader
       return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 20);
     }
 
+    // Return the COMDAT group count -- for objects only.
+    unsigned int
+    get_comdat_group_count() const
+    {
+      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
+                 || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
+
+      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 24);
+    }
+
     // Return the object count -- for scripts only.
     unsigned int
     get_object_count() const
@@ -939,7 +971,7 @@ class Incremental_inputs_reader
     {
       Input_section_info info;
       const unsigned char* p = (this->inputs_->p_
-                               + this->info_offset_ + 24
+                               + this->info_offset_ + 28
                                + n * input_section_entry_size);
       unsigned int name_offset = Swap32::readval(p);
       info.name = this->inputs_->get_string(name_offset);
@@ -957,12 +989,27 @@ class Incremental_inputs_reader
                  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
       unsigned int section_count = this->get_input_section_count();
       const unsigned char* p = (this->inputs_->p_
-                               + this->info_offset_ + 24
+                               + this->info_offset_ + 28
                                + section_count * input_section_entry_size
                                + n * 20);
       return Incremental_global_symbol_reader<big_endian>(p);
     }
 
+    // Return the signature of the Nth comdat group -- for objects only.
+    const char*
+    get_comdat_group_signature(unsigned int n) const
+    {
+      unsigned int section_count = this->get_input_section_count();
+      unsigned int symbol_count = this->get_global_symbol_count();
+      const unsigned char* p = (this->inputs_->p_
+                               + this->info_offset_ + 28
+                               + section_count * input_section_entry_size
+                               + symbol_count * 20
+                               + n * 4);
+      unsigned int name_offset = Swap32::readval(p);
+      return this->inputs_->get_string(name_offset);
+    }
+
     // Return the output symbol index for the Nth global symbol -- for shared
     // libraries only.  Sets *IS_DEF to TRUE if the symbol is defined in this
     // input file.
index 1160f0c..b14c85d 100644 (file)
@@ -825,6 +825,13 @@ Sized_relobj_file<size, big_endian>::include_section_group(
       is_comdat = true;
     }
 
+  if (is_comdat && include_group)
+    {
+      Incremental_inputs* incremental_inputs = layout->incremental_inputs();
+      if (incremental_inputs != NULL)
+       incremental_inputs->report_comdat_group(this, signature.c_str());
+    }
+
   size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word);
 
   std::vector<unsigned int> shndxes;