From 32e2b61d0baceacdd0ae791adc12bf829499be96 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 20 Mar 2013 00:25:28 +0000 Subject: [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. --- gold/ChangeLog | 7 +++++++ gold/symtab.cc | 41 ++++++++++++++++++++++++++++++++++------- gold/symtab.h | 4 ++++ 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index ee6b2686f78..8c3b1a28875 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,10 @@ +2013-03-20 Alan Modra + + * 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 * powerpc.cc (Target_powerpc::Scan::reloc_needs_plt_for_ifunc): Make diff --git a/gold/symtab.cc b/gold/symtab.cc index 1fad11eaa3c..17a0f55b292 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 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::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 040be954312..689d99f5bf0 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. -- 2.30.2