aboutsummaryrefslogtreecommitdiff
path: root/gold/symtab.cc
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2016-12-22 14:06:24 -0800
committerCary Coutant <ccoutant@gmail.com>2016-12-22 16:00:06 -0800
commitc4d5a76223f74930add9014f2a77339eb80b737c (patch)
tree0d2d2c9a9883fd35adf73ee40f18ee8c3268e9d3 /gold/symtab.cc
parent40d7d93ff412f4c34cde3daa04890d5cd2e0d9c9 (diff)
downloadfsf-binutils-gdb-c4d5a76223f74930add9014f2a77339eb80b737c.zip
fsf-binutils-gdb-c4d5a76223f74930add9014f2a77339eb80b737c.tar.gz
fsf-binutils-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.cc42
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,