This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gold][patch] Factor the should include member to a new function


The attached patch introduces a new function whose only job is to decide if
an archive member should be included in the link given that it defines a
given symbol. There are three possible outcomes

It should be included: This happens if we have an strong undefined reference
to that symbol.

It should not be included: This happens if we have a strong definition of that
symbol already.

We don't know. This happens if we know nothing about that symbol or it is a
weak undefined reference.

There are two reasons for doing this. First it is a small cleanup and saves
us from maintaining a temporary buffer. Second, I am implementing
--start-lib/--end-lib and would like to reuse this logic.

2010-03-02   Rafael Espindola  <espindola@google.com>

	* archive.cc (should_include_member): New.
	(Archive::add_symbols): Use should_include_member.

Cheers,
-- 
Rafael Ãvila de EspÃndola
diff --git a/gold/archive.cc b/gold/archive.cc
index a8b0fc6..e1c2a8a 100644
--- a/gold/archive.cc
+++ b/gold/archive.cc
@@ -602,6 +602,75 @@ Archive::read_symbols(off_t off)
   this->members_[off] = member;
 }
 
+namespace should_include
+{
+enum should_include
+  {
+    NO,
+    YES,
+    UNKNOWN
+  };
+}
+
+static should_include::should_include
+should_include_member(Symbol_table* symtab, const char* sym_name, Symbol** symp,
+                      std::string& why)
+{
+  // In an object file, and therefore in an archive map, an
+  // '@' in the name separates the symbol name from the
+  // version name.  If there are two '@' characters, this is
+  // the default version.
+  const char* ver = strchr(sym_name, '@');
+  bool def = false;
+  if (ver != NULL)
+    {
+      size_t symlen = ver - sym_name;
+      char tmpbuf[symlen + 1];
+      memcpy(tmpbuf, sym_name, symlen);
+      tmpbuf[symlen] = '\0';
+      sym_name = tmpbuf;
+
+      ++ver;
+      if (*ver == '@')
+        {
+          ++ver;
+          def = true;
+        }
+    }
+
+  Symbol* sym = symtab->lookup(sym_name, ver);
+  if (def
+      && ver != NULL
+      && (sym == NULL
+          || !sym->is_undefined()
+          || sym->binding() == elfcpp::STB_WEAK))
+    sym = symtab->lookup(sym_name, NULL);
+
+  *symp = sym;
+
+  if (sym == NULL)
+    {
+      // Check whether the symbol was named in a -u option.
+      if (!parameters->options().is_undefined(sym_name))
+        {
+          return should_include::UNKNOWN;
+        }
+      else
+        {
+          why = "-u ";
+          why += sym_name;
+        }
+    }
+  else if (!sym->is_undefined())
+    {
+      return should_include::NO;
+    }
+  else if (sym->binding() == elfcpp::STB_WEAK)
+    return should_include::UNKNOWN;
+
+  return should_include::YES;
+}
+
 // Select members from the archive and add them to the link.  We walk
 // through the elements in the archive map, and look each one up in
 // the symbol table.  If it exists as a strong undefined symbol, we
@@ -635,8 +704,6 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
   // Track which symbols in the symbol table we've already found to be
   // defined.
 
-  char* tmpbuf = NULL;
-  size_t tmpbuflen = 0;
   bool added_new_object;
   do
     {
@@ -661,82 +728,39 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
 	  const char* sym_name = (this->armap_names_.data()
 				  + this->armap_[i].name_offset);
 
-	  // In an object file, and therefore in an archive map, an
-	  // '@' in the name separates the symbol name from the
-	  // version name.  If there are two '@' characters, this is
-	  // the default version.
-	  const char* ver = strchr(sym_name, '@');
-	  bool def = false;
-	  if (ver != NULL)
-	    {
-	      size_t symlen = ver - sym_name;
-	      if (symlen + 1 > tmpbuflen)
-		{
-		  tmpbuf = static_cast<char*>(realloc(tmpbuf, symlen + 1));
-		  tmpbuflen = symlen + 1;
-		}
-	      memcpy(tmpbuf, sym_name, symlen);
-	      tmpbuf[symlen] = '\0';
-	      sym_name = tmpbuf;
-
-	      ++ver;
-	      if (*ver == '@')
-		{
-		  ++ver;
-		  def = true;
-		}
-	    }
+          Symbol* sym;
+          std::string why;
+          should_include::should_include t = should_include_member(symtab,
+                                                                   sym_name,
+                                                                   &sym,
+                                                                   why);
 
-	  Symbol* sym = symtab->lookup(sym_name, ver);
-	  if (def
-	      && ver != NULL
-	      && (sym == NULL
-		  || !sym->is_undefined()
-		  || sym->binding() == elfcpp::STB_WEAK))
-	    sym = symtab->lookup(sym_name, NULL);
-
-	  if (sym == NULL)
-	    {
-	      // Check whether the symbol was named in a -u option.
-	      if (!parameters->options().is_undefined(sym_name))
-		continue;
-	    }
-	  else if (!sym->is_undefined())
-	    {
+          switch (t)
+            {
+            case should_include::YES:
+              break;
+            case should_include::NO:
               this->armap_checked_[i] = true;
-	      continue;
-	    }
-	  else if (sym->binding() == elfcpp::STB_WEAK)
-	    continue;
+              /* fall through */
+            case should_include::UNKNOWN:
+              continue;
+            }
 
 	  // We want to include this object in the link.
 	  last_seen_offset = this->armap_[i].file_offset;
 	  this->seen_offsets_.insert(last_seen_offset);
           this->armap_checked_[i] = true;
 
-	  std::string why;
-	  if (sym == NULL)
-	    {
-	      why = "-u ";
-	      why += sym_name;
-	    }
 	  if (!this->include_member(symtab, layout, input_objects,
 				    last_seen_offset, mapfile, sym,
 				    why.c_str()))
-	    {
-	      if (tmpbuf != NULL)
-		free(tmpbuf);
-	      return false;
-	    }
+            return false;
 
 	  added_new_object = true;
 	}
     }
   while (added_new_object);
 
-  if (tmpbuf != NULL)
-    free(tmpbuf);
-
   input_objects->archive_stop(this);
 
   return true;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]