* symtab.h (Symbol::clear_version): New function.
authorAlan Modra <amodra@gmail.com>
Wed, 20 Mar 2013 00:25:28 +0000 (00:25 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 20 Mar 2013 00:25:28 +0000 (00:25 +0000)
* symtab.cc (Symbol_table::set_dynsym_indexes): Don't set object
is_needed by weak references.  Clear version for symbols defined
in as-needed objects that are not needed.

gold/ChangeLog
gold/symtab.cc
gold/symtab.h

index ee6b268..8c3b1a2 100644 (file)
@@ -1,3 +1,10 @@
+2013-03-20  Alan Modra  <amodra@gmail.com>
+
+       * symtab.h (Symbol::clear_version): New function.
+       * symtab.cc (Symbol_table::set_dynsym_indexes): Don't set object
+       is_needed by weak references.  Clear version for symbols defined
+       in as-needed objects that are not needed.
+
 2013-03-15  Alan Modra  <amodra@gmail.com>
 
        * powerpc.cc (Target_powerpc::Scan::reloc_needs_plt_for_ifunc): Make
index 1fad11e..17a0f55 100644 (file)
@@ -2368,6 +2368,8 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
                                 Stringpool* dynpool,
                                 Versions* versions)
 {
+  std::vector<Symbol*> as_needed_sym;
+
   for (Symbol_table_type::iterator p = this->table_.begin();
        p != this->table_.end();
        ++p)
@@ -2387,18 +2389,43 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
          syms->push_back(sym);
          dynpool->add(sym->name(), false, NULL);
 
-         // Record any version information.
-          if (sym->version() != NULL)
-            versions->record_version(this, dynpool, sym);
-
          // If the symbol is defined in a dynamic object and is
-         // referenced in a regular object, then mark the dynamic
-         // object as needed.  This is used to implement --as-needed.
-         if (sym->is_from_dynobj() && sym->in_reg())
+         // referenced strongly in a regular object, then mark the
+         // dynamic object as needed.  This is used to implement
+         // --as-needed.
+         if (sym->is_from_dynobj()
+             && sym->in_reg()
+             && !sym->is_undef_binding_weak())
            sym->object()->set_is_needed();
+
+         // Record any version information, except those from
+         // as-needed libraries not seen to be needed.  Note that the
+         // is_needed state for such libraries can change in this loop.
+         if (sym->version() != NULL)
+           {
+             if (!sym->is_from_dynobj()
+                 || !sym->object()->as_needed()
+                 || sym->object()->is_needed())
+               versions->record_version(this, dynpool, sym);
+             else
+               as_needed_sym.push_back(sym);
+           }
        }
     }
 
+  // Process version information for symbols from as-needed libraries.
+  for (std::vector<Symbol*>::iterator p = as_needed_sym.begin();
+       p != as_needed_sym.end();
+       ++p)
+    {
+      Symbol* sym = *p;
+
+      if (sym->object()->is_needed())
+       versions->record_version(this, dynpool, sym);
+      else
+       sym->clear_version();
+    }
+
   // Finish up the versions.  In some cases this may add new dynamic
   // symbols.
   index = versions->finalize(this, index, syms);
index 040be95..689d99f 100644 (file)
@@ -121,6 +121,10 @@ class Symbol
   version() const
   { return this->version_; }
 
+  void
+  clear_version()
+  { this->version_ = NULL; }
+
   // Return whether this version is the default for this symbol name
   // (eg, "foo@@V2" is a default version; "foo@V1" is not).  Only
   // meaningful for versioned symbols.