aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2013-03-20 00:25:28 +0000
committerAlan Modra <amodra@gmail.com>2013-03-20 00:25:28 +0000
commit32e2b61d0baceacdd0ae791adc12bf829499be96 (patch)
tree4575643f5e20face4fa00293ef4251cef3abee57
parente5e21fa801ffcbe8204f8287bb968bcf4af6b43d (diff)
downloadgdb-32e2b61d0baceacdd0ae791adc12bf829499be96.zip
gdb-32e2b61d0baceacdd0ae791adc12bf829499be96.tar.gz
gdb-32e2b61d0baceacdd0ae791adc12bf829499be96.tar.bz2
* 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.
-rw-r--r--gold/ChangeLog7
-rw-r--r--gold/symtab.cc41
-rw-r--r--gold/symtab.h4
3 files changed, 45 insertions, 7 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index ee6b268..8c3b1a2 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 1fad11e..17a0f55 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -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);
diff --git a/gold/symtab.h b/gold/symtab.h
index 040be95..689d99f 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -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.