diff options
Diffstat (limited to 'binutils-2.22/gold/symtab.cc')
-rw-r--r-- | binutils-2.22/gold/symtab.cc | 115 |
1 files changed, 82 insertions, 33 deletions
diff --git a/binutils-2.22/gold/symtab.cc b/binutils-2.22/gold/symtab.cc index ff1b5caa..fd81e8bd 100644 --- a/binutils-2.22/gold/symtab.cc +++ b/binutils-2.22/gold/symtab.cc @@ -363,14 +363,23 @@ Symbol::should_add_dynsym_entry(Symbol_table* symtab) const return false; } + // If the symbol was forced dynamic in a --dynamic-list file + // or an --export-dynamic-symbol option, add it. + if (!this->is_from_dynobj() + && (parameters->options().in_dynamic_list(this->name()) + || parameters->options().is_export_dynamic_symbol(this->name()))) + { + if (!this->is_forced_local()) + return true; + gold_warning(_("Cannot export local symbol '%s'"), + this->demangled_name().c_str()); + return false; + } + // If the symbol was forced local in a version script, do not add it. if (this->is_forced_local()) return false; - // If the symbol was forced dynamic in a --dynamic-list file, add it. - if (parameters->options().in_dynamic_list(this->name())) - return true; - // If dynamic-list-data was specified, add any STT_OBJECT. if (parameters->options().dynamic_list_data() && !this->is_from_dynobj() @@ -551,8 +560,8 @@ Symbol_table::is_section_folded(Object* obj, unsigned int shndx) const && this->icf_->is_section_folded(obj, shndx)); } -// For symbols that have been listed with -u option, add them to the -// work list to avoid gc'ing them. +// For symbols that have been listed with a -u or --export-dynamic-symbol +// option, add them to the work list to avoid gc'ing them. void Symbol_table::gc_mark_undef_symbols(Layout* layout) @@ -579,6 +588,28 @@ Symbol_table::gc_mark_undef_symbols(Layout* layout) } } + for (options::String_set::const_iterator p = + parameters->options().export_dynamic_symbol_begin(); + p != parameters->options().export_dynamic_symbol_end(); + ++p) + { + const char* name = p->c_str(); + Symbol* sym = this->lookup(name); + gold_assert(sym != NULL); + if (sym->source() == Symbol::FROM_OBJECT + && !sym->object()->is_dynamic()) + { + Relobj* obj = static_cast<Relobj*>(sym->object()); + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + if (is_ordinary) + { + gold_assert(this->gc_ != NULL); + this->gc_->worklist().push(Section_id(obj, shndx)); + } + } + } + for (Script_options::referenced_const_iterator p = layout->script_options()->referenced_begin(); p != layout->script_options()->referenced_end(); @@ -602,20 +633,16 @@ Symbol_table::gc_mark_undef_symbols(Layout* layout) } void -Symbol_table::gc_mark_symbol_for_shlib(Symbol* sym) +Symbol_table::gc_mark_symbol(Symbol* sym) { - if (!sym->is_from_dynobj() - && sym->is_externally_visible()) + // Add the object and section to the work list. + Relobj* obj = static_cast<Relobj*>(sym->object()); + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + if (is_ordinary && shndx != elfcpp::SHN_UNDEF) { - //Add the object and section to the work list. - Relobj* obj = static_cast<Relobj*>(sym->object()); - bool is_ordinary; - unsigned int shndx = sym->shndx(&is_ordinary); - if (is_ordinary && shndx != elfcpp::SHN_UNDEF) - { - gold_assert(this->gc_!= NULL); - this->gc_->worklist().push(Section_id(obj, shndx)); - } + gold_assert(this->gc_!= NULL); + this->gc_->worklist().push(Section_id(obj, shndx)); } } @@ -626,16 +653,7 @@ Symbol_table::gc_mark_dyn_syms(Symbol* sym) { if (sym->in_dyn() && sym->source() == Symbol::FROM_OBJECT && !sym->object()->is_dynamic()) - { - Relobj* obj = static_cast<Relobj*>(sym->object()); - bool is_ordinary; - unsigned int shndx = sym->shndx(&is_ordinary); - if (is_ordinary && shndx != elfcpp::SHN_UNDEF) - { - gold_assert(this->gc_ != NULL); - this->gc_->worklist().push(Section_id(obj, shndx)); - } - } + this->gc_mark_symbol(sym); } // Make TO a symbol which forwards to FROM. @@ -1143,6 +1161,14 @@ Symbol_table::add_from_relobj( bool is_default_version = false; bool is_forced_local = false; + // FIXME: For incremental links, we don't store version information, + // so we need to ignore version symbols for now. + if (parameters->incremental_update() && ver != NULL) + { + namelen = ver - name; + ver = NULL; + } + if (ver != NULL) { // The symbol name is of the form foo@VERSION or foo@@VERSION @@ -1243,11 +1269,16 @@ Symbol_table::add_from_relobj( if (is_forced_local) this->force_local(res); - // If building a shared library using garbage collection, do not - // treat externally visible symbols as garbage. - if (parameters->options().gc_sections() - && parameters->options().shared()) - this->gc_mark_symbol_for_shlib(res); + // Do not treat this symbol as garbage if this symbol will be + // exported to the dynamic symbol table. This is true when + // building a shared library or using --export-dynamic and + // the symbol is externally visible. + if (parameters->options().gc_sections() + && res->is_externally_visible() + && !res->is_from_dynobj() + && (parameters->options().shared() + || parameters->options().export_dynamic())) + this->gc_mark_symbol(res); if (is_defined_in_discarded_section) res->set_is_defined_in_discarded_section(); @@ -1346,6 +1377,11 @@ Symbol_table::add_from_dynobj( return; } + // FIXME: For incremental links, we don't store version information, + // so we need to ignore version symbols for now. + if (parameters->incremental_update()) + versym = NULL; + if (versym != NULL && versym_size / 2 < count) { dynobj->error(_("too few symbol versions")); @@ -1646,6 +1682,7 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion, bool* resolve_oldsym) { *resolve_oldsym = false; + *poldsym = NULL; // If the caller didn't give us a version, see if we get one from // the version script. @@ -2286,6 +2323,12 @@ Symbol_table::do_add_undefined_symbols_from_command_line(Layout* layout) ++p) this->add_undefined_symbol_from_command_line<size>(p->c_str()); + for (options::String_set::const_iterator p = + parameters->options().export_dynamic_symbol_begin(); + p != parameters->options().export_dynamic_symbol_end(); + ++p) + this->add_undefined_symbol_from_command_line<size>(p->c_str()); + for (Script_options::referenced_const_iterator p = layout->script_options()->referenced_begin(); p != layout->script_options()->referenced_end(); @@ -2809,6 +2852,12 @@ Symbol_table::sized_write_globals(const Stringpool* sympool, typename elfcpp::Elf_types<size>::Elf_Addr sym_value = sym->value(); typename elfcpp::Elf_types<size>::Elf_Addr dynsym_value = sym_value; elfcpp::STB binding = sym->binding(); + + // If --no-gnu-unique is set, change STB_GNU_UNIQUE to STB_GLOBAL. + if (binding == elfcpp::STB_GNU_UNIQUE + && !parameters->options().gnu_unique()) + binding = elfcpp::STB_GLOBAL; + switch (sym->source()) { case Symbol::FROM_OBJECT: |