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.
This commit is contained in:
Cary Coutant
2016-12-22 14:06:24 -08:00
parent 40d7d93ff4
commit c4d5a76223
8 changed files with 220 additions and 97 deletions

View File

@@ -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,