This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[gold][patch] Factor the should include member to a new function
- From: Rafael Espindola <espindola at google dot com>
- To: Binutils <binutils at sourceware dot org>
- Cc: Ian Lance Taylor <iant at google dot com>
- Date: Tue, 2 Mar 2010 16:18:50 -0500
- Subject: [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;