* dynobj.h (Dynobj::do_dynobj): New function.
authorCary Coutant <ccoutant@google.com>
Tue, 24 May 2011 21:57:28 +0000 (21:57 +0000)
committerCary Coutant <ccoutant@google.com>
Tue, 24 May 2011 21:57:28 +0000 (21:57 +0000)
* incremental-dump.cc (dump_incremental_inputs): Print as_needed
flag and soname for shared objects.
* incremental.cc (Incremental_inputs::report_object): Make
either Incremental_object_entry or Incremental_dynobj_entry; add
soname to string table.
(Incremental_inputs::report_input_section): Add assertion.
(Output_section_incremental_inputs::set_final_data_size): Adjust
type of input file entry for shared libraries; adjust size of
shared library info entry.
(Output_section_incremental_inputs::write_input_files): Write
as_needed flag for shared libraries.
(Output_section_incremental_inputs::write_info_blocks): Adjust type
of input file entry for shared libraries; write soname.
(Sized_incr_dynobj::Sized_incr_dynobj): Read as_needed flag and
soname from incremental info.
* incremental.h (enum Incremental_input_flags): Add
INCREMENTAL_INPUT_AS_NEEDED.
(Incremental_input_entry::Incremental_input_entry): Initialize new
data member.
(Incremental_input_entry::set_as_needed): New function.
(Incremental_input_entry::as_needed): New function.
(Incremental_input_entry::do_dynobj_entry): New function.
(Incremental_input_entry::as_needed_): New data member.
(Incremental_object_entry::Incremental_object_entry): Don't check
for shared library.
(Incremental_object_entry::do_type): Likewise.
(class Incremental_dynobj_entry): New class.
(Incremental_input_entry_reader::as_needed): New function.
(Incremental_input_entry_reader::get_soname): New function.
(Incremental_input_entry_reader::get_global_symbol_count): Rewrite.
(Incremental_input_entry_reader::get_output_symbol_index): Adjust
size of shared library info entry.
* layout.cc (Layout::finish_dynamic_section): Don't test for
incremental link when adding DT_NEEDED entries.
* object.h (Object::Object): Initialize new data member.
(Object::dynobj): New function.
(Object::set_as_needed): New function.
(Object::as_needed): New function.
(Object::do_dynobj): New function.
(Object::as_needed_): New data member.

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

index 2cdc2738c3ed8f238935919fca7c52128ec8af01..67e7e9ae560b837c2938bcc3bff157ce1cce5d04 100644 (file)
@@ -1,3 +1,47 @@
+2011-05-24 Cary Coutant  <ccoutant@google.com>
+
+       * dynobj.h (Dynobj::do_dynobj): New function.
+       * incremental-dump.cc (dump_incremental_inputs): Print as_needed
+       flag and soname for shared objects.
+       * incremental.cc (Incremental_inputs::report_object): Make
+       either Incremental_object_entry or Incremental_dynobj_entry; add
+       soname to string table.
+       (Incremental_inputs::report_input_section): Add assertion.
+       (Output_section_incremental_inputs::set_final_data_size): Adjust
+       type of input file entry for shared libraries; adjust size of
+       shared library info entry.
+       (Output_section_incremental_inputs::write_input_files): Write
+       as_needed flag for shared libraries.
+       (Output_section_incremental_inputs::write_info_blocks): Adjust type
+       of input file entry for shared libraries; write soname.
+       (Sized_incr_dynobj::Sized_incr_dynobj): Read as_needed flag and
+       soname from incremental info.
+       * incremental.h (enum Incremental_input_flags): Add
+       INCREMENTAL_INPUT_AS_NEEDED.
+       (Incremental_input_entry::Incremental_input_entry): Initialize new
+       data member.
+       (Incremental_input_entry::set_as_needed): New function.
+       (Incremental_input_entry::as_needed): New function.
+       (Incremental_input_entry::do_dynobj_entry): New function.
+       (Incremental_input_entry::as_needed_): New data member.
+       (Incremental_object_entry::Incremental_object_entry): Don't check
+       for shared library.
+       (Incremental_object_entry::do_type): Likewise.
+       (class Incremental_dynobj_entry): New class.
+       (Incremental_input_entry_reader::as_needed): New function.
+       (Incremental_input_entry_reader::get_soname): New function.
+       (Incremental_input_entry_reader::get_global_symbol_count): Rewrite.
+       (Incremental_input_entry_reader::get_output_symbol_index): Adjust
+       size of shared library info entry.
+       * layout.cc (Layout::finish_dynamic_section): Don't test for 
+       incremental link when adding DT_NEEDED entries.
+       * object.h (Object::Object): Initialize new data member.
+       (Object::dynobj): New function.
+       (Object::set_as_needed): New function.
+       (Object::as_needed): New function.
+       (Object::do_dynobj): New function.
+       (Object::as_needed_): New data member.
+
 2011-05-24 Cary Coutant  <ccoutant@google.com>
 
        * incremental-dump.cc (dump_incremental_inputs): Print dynamic reloc
index c96ee2c2e374e2568cb31e34192f0ba2360237f1..d26b8a7407594db2484a930453957cf116f8fe74 100644 (file)
@@ -96,6 +96,11 @@ class Dynobj : public Object
                        unsigned char** pphash, unsigned int* phashlen);
 
  protected:
+  // Return a pointer to this object.
+  virtual Dynobj*
+  do_dynobj()
+  { return this; }
+
   // Set the DT_SONAME string.
   void
   set_soname_string(const char* s)
index c1e253038ccba873be04dd203afd74ab9a59bc14..1887db86cac6c30837f3854736bbb8dc193e85a9 100644 (file)
@@ -162,6 +162,10 @@ dump_incremental_inputs(const char* argv0, const char* filename,
          break;
        case INCREMENTAL_INPUT_SHARED_LIBRARY:
          printf("Shared library\n");
+         printf("    As needed: %s\n",
+                input_file.as_needed() ? "true" : "false");
+         printf("    soname: %s\n",
+                input_file.get_soname());
          printf("    Symbol count: %d\n",
                 input_file.get_global_symbol_count());
          break;
index d49c8a5df4e062d66550b4407c56f6cf86814c9a..0a8994078f9029e48be308fc81b1c95fe1d4fcb4 100644 (file)
@@ -975,28 +975,48 @@ Incremental_inputs::report_object(Object* obj, unsigned int arg_serial,
     arg_serial = 0;
 
   this->strtab_->add(obj->name().c_str(), false, &filename_key);
-  Incremental_object_entry* obj_entry =
-      new Incremental_object_entry(filename_key, obj, arg_serial, mtime);
-  if (obj->is_in_system_directory())
-    obj_entry->set_is_in_system_directory();
-  this->inputs_.push_back(obj_entry);
 
-  if (arch != NULL)
+  Incremental_input_entry* input_entry;
+
+  this->current_object_ = obj;
+
+  if (!obj->is_dynamic())
     {
-      Incremental_archive_entry* arch_entry = arch->incremental_info();
-      gold_assert(arch_entry != NULL);
-      arch_entry->add_object(obj_entry);
+      this->current_object_entry_ =
+          new Incremental_object_entry(filename_key, obj, arg_serial, mtime);
+      input_entry = this->current_object_entry_;
+      if (arch != NULL)
+       {
+         Incremental_archive_entry* arch_entry = arch->incremental_info();
+         gold_assert(arch_entry != NULL);
+         arch_entry->add_object(this->current_object_entry_);
+       }
     }
+  else
+    {
+      this->current_object_entry_ = NULL;
+      Stringpool::Key soname_key;
+      Dynobj* dynobj = obj->dynobj();
+      gold_assert(dynobj != NULL);
+      this->strtab_->add(dynobj->soname(), false, &soname_key);
+      input_entry = new Incremental_dynobj_entry(filename_key, soname_key, obj,
+                                                arg_serial, mtime);
+    }
+
+  if (obj->is_in_system_directory())
+    input_entry->set_is_in_system_directory();
+
+  if (obj->as_needed())
+    input_entry->set_as_needed();
+
+  this->inputs_.push_back(input_entry);
 
   if (script_info != NULL)
     {
       Incremental_script_entry* script_entry = script_info->incremental_info();
       gold_assert(script_entry != NULL);
-      script_entry->add_object(obj_entry);
+      script_entry->add_object(input_entry);
     }
-
-  this->current_object_ = obj;
-  this->current_object_entry_ = obj_entry;
 }
 
 // Record the input object file OBJ.  If ARCH is not NULL, attach
@@ -1013,6 +1033,7 @@ Incremental_inputs::report_input_section(Object* obj, unsigned int shndx,
       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);
 }
 
@@ -1155,11 +1176,11 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
          break;
        case INCREMENTAL_INPUT_SHARED_LIBRARY:
          {
-           Incremental_object_entry* entry = (*p)->object_entry();
+           Incremental_dynobj_entry* entry = (*p)->dynobj_entry();
            gold_assert(entry != NULL);
            (*p)->set_info_offset(info_offset);
-           // Global symbol count.
-           info_offset += 4;
+           // Global symbol count, soname index.
+           info_offset += 8;
            // Each global symbol.
            const Object::Symbols* syms = entry->object()->get_global_symbols();
            gold_assert(syms != NULL);
@@ -1321,6 +1342,8 @@ Output_section_incremental_inputs<size, big_endian>::write_input_files(
       unsigned int flags = (*p)->type();
       if ((*p)->is_in_system_directory())
         flags |= INCREMENTAL_INPUT_IN_SYSTEM_DIR;
+      if ((*p)->as_needed())
+        flags |= INCREMENTAL_INPUT_AS_NEEDED;
       Swap32::writeval(pov, filename_offset);
       Swap32::writeval(pov + 4, (*p)->get_info_offset());
       Swap64::writeval(pov + 8, mtime.seconds);
@@ -1483,11 +1506,17 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
          {
            gold_assert(static_cast<unsigned int>(pov - oview)
                        == (*p)->get_info_offset());
-           Incremental_object_entry* entry = (*p)->object_entry();
+           Incremental_dynobj_entry* entry = (*p)->dynobj_entry();
            gold_assert(entry != NULL);
            const Object* obj = entry->object();
            const Object::Symbols* syms = obj->get_global_symbols();
 
+           // Write the soname string table index.
+           section_offset_type soname_offset =
+               strtab->get_offset_from_key(entry->get_soname_key());
+           Swap32::writeval(pov, soname_offset);
+           pov += 4;
+
            // Skip the global symbol count for now.
            unsigned char* orig_pov = pov;
            pov += 4;
@@ -2347,6 +2376,9 @@ Sized_incr_dynobj<size, big_endian>::Sized_incr_dynobj(
 {
   if (this->input_reader_.is_in_system_directory())
     this->set_is_in_system_directory();
+  if (this->input_reader_.as_needed())
+    this->set_as_needed();
+  this->set_soname_string(this->input_reader_.get_soname());
   this->set_shnum(0);
 }
 
index 3935186e5b7f1219a16155123825d6bc9c1fb8e2..dc8ef33e05853dfd0ab03c72757dbf2d8492ed89 100644 (file)
@@ -40,6 +40,7 @@ class Input_argument;
 class Incremental_inputs_checker;
 class Incremental_script_entry;
 class Incremental_object_entry;
+class Incremental_dynobj_entry;
 class Incremental_archive_entry;
 class Incremental_inputs;
 class Incremental_binary;
@@ -63,7 +64,8 @@ enum Incremental_input_type
 
 enum Incremental_input_flags
 {
-  INCREMENTAL_INPUT_IN_SYSTEM_DIR = 0x0800
+  INCREMENTAL_INPUT_IN_SYSTEM_DIR = 0x8000,
+  INCREMENTAL_INPUT_AS_NEEDED = 0x4000
 };
 
 // Create an Incremental_binary object for FILE. Returns NULL is this is not
@@ -80,7 +82,8 @@ class Incremental_input_entry
   Incremental_input_entry(Stringpool::Key filename_key, unsigned int arg_serial,
                          Timespec mtime)
     : filename_key_(filename_key), file_index_(0), offset_(0), info_offset_(0),
-      arg_serial_(arg_serial), mtime_(mtime), is_in_system_directory_(false)
+      arg_serial_(arg_serial), mtime_(mtime), is_in_system_directory_(false),
+      as_needed_(false)
   { }
 
   virtual
@@ -145,6 +148,16 @@ class Incremental_input_entry
   is_in_system_directory() const
   { return this->is_in_system_directory_; }
 
+  // Record that the file was linked with --as-needed.
+  void
+  set_as_needed()
+  { this->as_needed_ = true; }
+
+  // Return TRUE if the file was linked with --as-needed.
+  bool
+  as_needed() const
+  { return this->as_needed_; }
+
   // Return a pointer to the derived Incremental_script_entry object.
   // Return NULL for input entries that are not script files.
   Incremental_script_entry*
@@ -157,6 +170,12 @@ class Incremental_input_entry
   object_entry()
   { return this->do_object_entry(); }
 
+  // Return a pointer to the derived Incremental_dynobj_entry object.
+  // Return NULL for input entries that are not shared object files.
+  Incremental_dynobj_entry*
+  dynobj_entry()
+  { return this->do_dynobj_entry(); }
+
   // Return a pointer to the derived Incremental_archive_entry object.
   // Return NULL for input entries that are not archive files.
   Incremental_archive_entry*
@@ -180,6 +199,12 @@ class Incremental_input_entry
   do_object_entry()
   { return NULL; }
 
+  // Return a pointer to the derived Incremental_dynobj_entry object.
+  // Return NULL for input entries that are not shared object files.
+  virtual Incremental_dynobj_entry*
+  do_dynobj_entry()
+  { return NULL; }
+
   // Return a pointer to the derived Incremental_archive_entry object.
   // Return NULL for input entries that are not archive files.
   virtual Incremental_archive_entry*
@@ -207,6 +232,9 @@ class Incremental_input_entry
 
   // TRUE if the file was found in a system directory.
   bool is_in_system_directory_;
+
+  // TRUE if the file was linked with --as-needed.
+  bool as_needed_;
 };
 
 // Information about a script input that will persist during the whole linker
@@ -298,10 +326,7 @@ class Incremental_object_entry : public Incremental_input_entry
                           unsigned int arg_serial, Timespec mtime)
     : Incremental_input_entry(filename_key, arg_serial, mtime), obj_(obj),
       is_member_(false), sections_()
-  {
-    if (!obj_->is_dynamic())
-      this->sections_.reserve(obj->shnum());
-  }
+  { this->sections_.reserve(obj->shnum()); }
 
   // Get the object.
   Object*
@@ -349,9 +374,7 @@ class Incremental_object_entry : public Incremental_input_entry
   {
     return (this->is_member_
            ? INCREMENTAL_INPUT_ARCHIVE_MEMBER
-           : (this->obj_->is_dynamic()
-              ? INCREMENTAL_INPUT_SHARED_LIBRARY
-              : INCREMENTAL_INPUT_OBJECT));
+           : INCREMENTAL_INPUT_OBJECT);
   }
 
   // Return a pointer to the derived Incremental_object_entry object.
@@ -379,6 +402,46 @@ class Incremental_object_entry : public Incremental_input_entry
   std::vector<Input_section> sections_;
 };
 
+// Class for recording shared library input files.
+
+class Incremental_dynobj_entry : public Incremental_input_entry
+{
+ public:
+  Incremental_dynobj_entry(Stringpool::Key filename_key,
+                          Stringpool::Key soname_key, Object* obj,
+                          unsigned int arg_serial, Timespec mtime)
+    : Incremental_input_entry(filename_key, arg_serial, mtime),
+      soname_key_(soname_key), obj_(obj)
+  { }
+
+  // Get the object.
+  Object*
+  object() const
+  { return this->obj_; }
+
+  // Get the stringpool key for the soname.
+  Stringpool::Key
+  get_soname_key() const
+  { return this->soname_key_; }
+
+ protected:
+  virtual Incremental_input_type
+  do_type() const
+  { return INCREMENTAL_INPUT_SHARED_LIBRARY; }
+
+  // Return a pointer to the derived Incremental_dynobj_entry object.
+  virtual Incremental_dynobj_entry*
+  do_dynobj_entry()
+  { return this; }
+
+ private:
+  // Key of the soname string in the section stringtable.
+  Stringpool::Key soname_key_;
+
+  // The object file itself.
+  Object* obj_;
+};
+
 // Class for recording archive library input files.
 
 class Incremental_archive_entry : public Incremental_input_entry
@@ -718,6 +781,11 @@ class Incremental_inputs_reader
     is_in_system_directory() const
     { return (this->flags_ & INCREMENTAL_INPUT_IN_SYSTEM_DIR) != 0; }
 
+    // Return TRUE if the file was linked with --as-needed.
+    bool
+    as_needed() const
+    { return (this->flags_ & INCREMENTAL_INPUT_AS_NEEDED) != 0; }
+
     // Return the input section count -- for objects only.
     unsigned int
     get_input_section_count() const
@@ -727,6 +795,16 @@ class Incremental_inputs_reader
       return Swap32::readval(this->inputs_->p_ + this->info_offset_);
     }
 
+    // Return the soname -- for shared libraries only.
+    const char*
+    get_soname() const
+    {
+      gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
+      unsigned int offset = Swap32::readval(this->inputs_->p_
+                                           + this->info_offset_);
+      return this->inputs_->get_string(offset);
+    }
+
     // Return the offset of the supplemental info for symbol SYMNDX --
     // for objects only.
     unsigned int
@@ -745,16 +823,10 @@ class Incremental_inputs_reader
     unsigned int
     get_global_symbol_count() const
     {
-      switch (this->type())
-       {
-       case INCREMENTAL_INPUT_OBJECT:
-       case INCREMENTAL_INPUT_ARCHIVE_MEMBER:
-         return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 4);
-       case INCREMENTAL_INPUT_SHARED_LIBRARY:
-         return Swap32::readval(this->inputs_->p_ + this->info_offset_);
-       default:
-         gold_unreachable();
-       }
+      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
+                 || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER
+                 || this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
+      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 4);
     }
 
     // Return the offset of the first local symbol -- for objects only.
@@ -899,7 +971,7 @@ class Incremental_inputs_reader
     {
       gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
       const unsigned char* p = (this->inputs_->p_
-                               + this->info_offset_ + 4
+                               + this->info_offset_ + 8
                                + n * 4);
       unsigned int output_symndx = Swap32::readval(p);
       *is_def = (output_symndx & (1U << 31)) != 0;
index d4b9f18a8fa643437b799ccc4e7eed09f09fe590..356a664d2e2c186f3f23545c69cad532d8e8d7a3 100644 (file)
@@ -3986,9 +3986,7 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
        p != input_objects->dynobj_end();
        ++p)
     {
-      if (!(*p)->is_needed()
-         && !(*p)->is_incremental()
-         && (*p)->input_file()->options().as_needed())
+      if (!(*p)->is_needed() && (*p)->as_needed())
        {
          // This dynamic object was linked with --as-needed, but it
          // is not needed.
index d9be4b52e3e920ebe8370adee6556e182c7dd3f5..1031833de949bf467596d002633c52c176a1c30d 100644 (file)
@@ -332,12 +332,13 @@ class Object
     : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
       is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
       has_no_split_stack_(false), no_export_(false),
-      is_in_system_directory_(false), xindex_(NULL)
+      is_in_system_directory_(false), as_needed_(false), xindex_(NULL)
   {
     if (input_file != NULL)
       {
        input_file->file().add_object();
        this->is_in_system_directory_ = input_file->is_in_system_directory();
+       this->as_needed_ = input_file->options().as_needed();
       }
   }
 
@@ -386,6 +387,12 @@ class Object
   has_no_split_stack() const
   { return this->has_no_split_stack_; }
 
+  // Returns NULL for Objects that are not dynamic objects.  This method
+  // is overridden in the Dynobj class.
+  Dynobj*
+  dynobj()
+  { return this->do_dynobj(); }
+
   // Returns NULL for Objects that are not plugin objects.  This method
   // is overridden in the Pluginobj class.
   Pluginobj*
@@ -688,6 +695,16 @@ class Object
   is_in_system_directory() const
   { return this->is_in_system_directory_; }
 
+  // Set flag that this object was linked with --as-needed.
+  void
+  set_as_needed()
+  { this->as_needed_ = true; }
+
+  // Return whether this object was linked with --as-needed.
+  bool
+  as_needed() const
+  { return this->as_needed_; }
+
   // Return whether we found this object by searching a directory.
   bool
   searched_for() const
@@ -719,6 +736,12 @@ class Object
   { return this->do_get_incremental_reloc_count(symndx); }
 
  protected:
+  // Returns NULL for Objects that are not dynamic objects.  This method
+  // is overridden in the Dynobj class.
+  virtual Dynobj*
+  do_dynobj()
+  { return NULL; }
+
   // Returns NULL for Objects that are not plugin objects.  This method
   // is overridden in the Pluginobj class.
   virtual Pluginobj*
@@ -911,6 +934,8 @@ class Object
   bool no_export_ : 1;
   // True if the object was found in a system directory.
   bool is_in_system_directory_ : 1;
+  // True if the object was linked with --as-needed.
+  bool as_needed_ : 1;
   // Many sections for objects with more than SHN_LORESERVE sections.
   Xindex* xindex_;
 };