[GOLD] --as-needed change wrt undefined weak symbols

Alan Modra amodra@gmail.com
Wed Mar 20 00:26:00 GMT 2013


On Tue, Mar 19, 2013 at 01:41:31PM -0700, Ian Lance Taylor wrote:
> On Mon, Mar 18, 2013 at 7:34 PM, Alan Modra <amodra@gmail.com> wrote:
> > On Mon, Mar 18, 2013 at 08:15:55AM -0700, Ian Lance Taylor wrote:
> >>  We can build a
> >> temporary vector of symbols with version != NULL for which that
> >> condition is not true, and then walk that vector in the second loop.
> >> There won't be many entries in it.
> >
> > Well, OK, but I wonder whether it is really worth doing?  Sometimes
> > having two small loops is much better than having one large one.
> 
> Yes, but there are executables here with tens of thousands of dynamic
> symbols, none of which are weak.
> 
> >         * symtab.h (Symbol::override_version): Make public.
> >         * 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.
> 
> This is OK.

When compiling with a different gcc and options (previously I used
-fno-inline), I hit
...symtab.cc:2426: undefined reference to `gold::Symbol::override_version(char const*)'

So I'm committing this slightly different patch.

	* 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.

Index: gold/symtab.h
===================================================================
RCS file: /cvs/src/src/gold/symtab.h,v
retrieving revision 1.129
diff -u -p -r1.129 symtab.h
--- gold/symtab.h	10 Mar 2013 23:08:18 -0000	1.129
+++ gold/symtab.h	19 Mar 2013 22:33:39 -0000
@@ -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.
Index: gold/symtab.cc
===================================================================
RCS file: /cvs/src/src/gold/symtab.cc,v
retrieving revision 1.169
diff -u -p -r1.169 symtab.cc
--- gold/symtab.cc	10 Mar 2013 23:08:18 -0000	1.169
+++ gold/symtab.cc	19 Mar 2013 22:33:40 -0000
@@ -2368,6 +2368,8 @@ Symbol_table::set_dynsym_indexes(unsigne
 				 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(unsigne
 	  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);


-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list