Fix --no-as-needed when shared library is listed twice on the command line.
authorCary Coutant <ccoutant@gmail.com>
Fri, 21 Aug 2015 19:32:33 +0000 (12:32 -0700)
committerCary Coutant <ccoutant@gmail.com>
Wed, 26 Aug 2015 01:39:20 +0000 (18:39 -0700)
When a shared library is listed twice on the command line, the linker
ignores the second mention. If the first mention is in the scope of
an --as-needed option, and the second one is under the scope of a
--no-as-needed option, the --no-as-needed should take effect, but
doesn't.  This patch keeps track of the objects we've already seen,
and updates the --as-needed flag so that if a shared object is ever
seen with --no-as-needed, it will be marked as such.

gold/
PR gold/18859
* object.cc (Input_objects::add_object): Store objects in a map,
indexed by soname; update as-needed flag when necessary.
* object.h (Object::clear_as_needed): New method.
(Input_objects::so_names_): Change from set to map.

gold/ChangeLog
gold/object.cc
gold/object.h

index ebed52b2ee0bbaa9c7bda54439735b0a3a20835c..fdc701553ea2c14735033bba46fb0e8314ca623f 100644 (file)
@@ -1,3 +1,11 @@
+2015-08-25  Cary Coutant  <ccoutant@gmail.com>
+
+       PR gold/18859
+       * object.cc (Input_objects::add_object): Store objects in a map,
+       indexed by soname; update as-needed flag when necessary.
+       * object.h (Object::clear_as_needed): New method.
+       (Input_objects::so_names_): Change from set to map.
+
 2015-08-25  Cary Coutant  <ccoutant@gmail.com>
 
        PR gold/14746
index 316f8d40aacd04d99cb5e5dd41c48f3672f9cdd7..76d4630d16a8cfbe445f421250798c3438aa48e4 100644 (file)
@@ -2973,11 +2973,20 @@ Input_objects::add_object(Object* obj)
       Dynobj* dynobj = static_cast<Dynobj*>(obj);
       const char* soname = dynobj->soname();
 
-      std::pair<Unordered_set<std::string>::iterator, bool> ins =
-       this->sonames_.insert(soname);
+      Unordered_map<std::string, Object*>::value_type val(soname, obj);
+      std::pair<Unordered_map<std::string, Object*>::iterator, bool> ins =
+       this->sonames_.insert(val);
       if (!ins.second)
        {
          // We have already seen a dynamic object with this soname.
+         // If any instances of this object on the command line have
+         // the --no-as-needed flag, make sure the one we keep is
+         // marked so.
+         if (!obj->as_needed())
+           {
+             gold_assert(ins.first->second != NULL);
+             ins.first->second->clear_as_needed();
+           }
          return false;
        }
 
index e8f74ac9bcb4d722f9d6c0d2ab5f7c9e10712b62..f796fb501470e38039c3f535fbd10786da91a02a 100644 (file)
@@ -731,6 +731,11 @@ class Object
   set_as_needed()
   { this->as_needed_ = true; }
 
+  // Clear flag that this object was linked with --as-needed.
+  void
+  clear_as_needed()
+  { this->as_needed_ = false; }
+
   // Return whether this object was linked with --as-needed.
   bool
   as_needed() const
@@ -2836,7 +2841,7 @@ class Input_objects
   // The list of dynamic objects included in the link.
   Dynobj_list dynobj_list_;
   // SONAMEs that we have seen.
-  Unordered_set<std::string> sonames_;
+  Unordered_map<std::string, Object*> sonames_;
   // Manage cross-references if requested.
   Cref* cref_;
 };