diff options
author | Cary Coutant <ccoutant@gmail.com> | 2016-12-22 14:06:24 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2016-12-22 16:00:06 -0800 |
commit | c4d5a76223f74930add9014f2a77339eb80b737c (patch) | |
tree | 0d2d2c9a9883fd35adf73ee40f18ee8c3268e9d3 /gold/symtab.cc | |
parent | 40d7d93ff412f4c34cde3daa04890d5cd2e0d9c9 (diff) | |
download | gdb-c4d5a76223f74930add9014f2a77339eb80b737c.zip gdb-c4d5a76223f74930add9014f2a77339eb80b737c.tar.gz gdb-c4d5a76223f74930add9014f2a77339eb80b737c.tar.bz2 |
Fix placement of forced local symbols in the dynamic symbol table.
Gold was not placing forced-local symbols (e.g., hidden visibility)
at the front of the dynamic symbol table, or including them in the
count of local symbols recorded in the .dynsym section's sh_info field.
gold/
* layout.cc (Layout::finalize): Track count of forced-local symbols
in .dynsym.
(Layout::create_symtab_sections): Add local_dynamic_count parameter;
use that instead of sh_info value.
(Layout::create_dynamic_symtab): Add pforced_local_dynamic_count
parameter; pass it to Symtab::set_dynsym_indexes(). Include forced
locals in sh_info value. Pass index of first real global to
Dynobj::create_gnu_hash_table() and Dynobj::create_elf_hash_table().
* layout.h (Layout::create_symtab_sections): Add local_dynamic_count
parameter.
(Layout::create_dynamic_symtab): Add pforced_local_dynamic_count
parameter.
* symtab.cc (Symbol_table::set_dynsym_indexes): Add pforced_local_count
parameter. Process forced-local symbols first and return the count.
(Symbol_table::finalize): Update comments.
* symtab.h (Symbol_table::set_dynsym_indexes): Add pforced_local_count
parameter.
(Symbol_table::first_dynamic_global_index_): Update comment.
(Symbol_table::dynamic_count_): Update comment.
* testsuite/Makefile.am (ifuncmod1.sh): New test case.
* testsuite/Makefile.in: Regenerate.
* testsuite/ifuncmod1.sh: New shell script.
Diffstat (limited to 'gold/symtab.cc')
-rw-r--r-- | gold/symtab.cc | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc index d97fbdd..32c97fb 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -2473,18 +2473,42 @@ Symbol_table::add_undefined_symbol_from_command_line(const char* name) } // Set the dynamic symbol indexes. INDEX is the index of the first -// global dynamic symbol. Pointers to the symbols are stored into the -// vector SYMS. The names are added to DYNPOOL. This returns an -// updated dynamic symbol index. +// global dynamic symbol. Pointers to the global symbols are stored +// into the vector SYMS. The names are added to DYNPOOL. +// This returns an updated dynamic symbol index. unsigned int Symbol_table::set_dynsym_indexes(unsigned int index, + unsigned int* pforced_local_count, std::vector<Symbol*>* syms, Stringpool* dynpool, Versions* versions) { std::vector<Symbol*> as_needed_sym; + // First process all the symbols which have been forced to be local, + // as they must appear before all global symbols. + unsigned int forced_local_count = 0; + for (Forced_locals::iterator p = this->forced_locals_.begin(); + p != this->forced_locals_.end(); + ++p) + { + Symbol* sym = *p; + gold_assert(sym->is_forced_local()); + if (sym->has_dynsym_index()) + continue; + if (!sym->should_add_dynsym_entry(this)) + sym->set_dynsym_index(-1U); + else + { + sym->set_dynsym_index(index); + ++index; + ++forced_local_count; + dynpool->add(sym->name(), false, NULL); + } + } + *pforced_local_count = forced_local_count; + // Allow a target to set dynsym indexes. if (parameters->target().has_custom_set_dynsym_indexes()) { @@ -2494,6 +2518,8 @@ Symbol_table::set_dynsym_indexes(unsigned int index, ++p) { Symbol* sym = p->second; + if (sym->is_forced_local()) + continue; if (!sym->should_add_dynsym_entry(this)) sym->set_dynsym_index(-1U); else @@ -2510,6 +2536,9 @@ Symbol_table::set_dynsym_indexes(unsigned int index, { Symbol* sym = p->second; + if (sym->is_forced_local()) + continue; + // Note that SYM may already have a dynamic symbol index, since // some symbols appear more than once in the symbol table, with // and without a version. @@ -2581,7 +2610,12 @@ Symbol_table::set_dynsym_indexes(unsigned int index, // Set the final values for all the symbols. The index of the first // global symbol in the output file is *PLOCAL_SYMCOUNT. Record the // file offset OFF. Add their names to POOL. Return the new file -// offset. Update *PLOCAL_SYMCOUNT if necessary. +// offset. Update *PLOCAL_SYMCOUNT if necessary. DYNOFF and +// DYN_GLOBAL_INDEX refer to the start of the symbols that will be +// written from the global symbol table in Symtab::write_globals(), +// which will include forced-local symbols. DYN_GLOBAL_INDEX is +// not necessarily the same as the sh_info field for the .dynsym +// section, which will point to the first real global symbol. off_t Symbol_table::finalize(off_t off, off_t dynoff, size_t dyn_global_index, |