Fix __bss_start assertion failure in _bfd_elf_fix_symbol_flags
> Building LLVM 6.0 on FreeBSD/powerpc (devel/llvm60 port) the assertion > in the subject trips (displays twice) when linking libLTO.so.1. The > issue has been filed in FreeBSD's bugzilla, at > https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=237068 . It appears > the 'llvm::hashing::detail::get_execution_seed()::seed@@JL_LLVM_6.0' > symbol is being weakly aliased to an indirect symbol > __bss_start@@JL_LLVM_6.0. Since __bss_start@@JL_LLVM_6.0 is an > indirect symbol, it fails the assertion. I haven't looked under a debugger at your testcase but I think I know what is going on here. You have a shared library with a weakly defined llvm::hashing::detail::get_execution_seed()::seed which happens to be at the same location as __bss_start in that library. At the time the linker loads symbols for that library, it sees they are both versioned and thus introduces non-versioned indirect symbols for them. The linker considers the symbols as possibly being aliases, setting up h->u.alias and h->is_weakalias such that __bss_start@@JL_LLVM_6.0 is the definition. No real problem so far, the definition is bfd_link_hash_defined, except that the zero size, no type __bss_start symbol possibly should not be considered an alias in the first place. Later, __bss_start as defined by the linker script is entered into the linker symbol table. This is similar to __bss_start being defined by a regular object file in that ELF symbol resolution rules say that the value of __bss_start in the library is overridden by __bss_start in the executable/library being produced. So to accomplish the override, ld flips __bss_start from being an indirect symbol pointing at __bss_start@@JL_LLVM_6.0 to __bss_start@@JL_LLVM_6.0 being an indirect symbol pointing at __bss_start. That's how we get an unexpected indirect symbol and hit the assert. What should happen I think, is for the def->def_regular code above the assert to run in this case. The symbols are no longer aliases. * elflink.c (_bfd_elf_fix_symbol_flags): If the def for an alias is no longer bfd_link_hash_defined, clear the alias.
This commit is contained in:
parent
03181f1c38
commit
5b9d7a9a64
@ -1,3 +1,8 @@
|
||||
2019-07-15 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elflink.c (_bfd_elf_fix_symbol_flags): If the def for an
|
||||
alias is no longer bfd_link_hash_defined, clear the alias.
|
||||
|
||||
2019-07-13 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elflink.c (_bfd_elf_omit_section_dynsym_default): Don't keep
|
||||
|
@ -2918,8 +2918,16 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
|
||||
|
||||
/* If the real definition is defined by a regular object file,
|
||||
don't do anything special. See the longer description in
|
||||
_bfd_elf_adjust_dynamic_symbol, below. */
|
||||
if (def->def_regular)
|
||||
_bfd_elf_adjust_dynamic_symbol, below. If the def is not
|
||||
bfd_link_hash_defined as it was when put on the alias list
|
||||
then it must have originally been a versioned symbol (for
|
||||
which a non-versioned indirect symbol is created) and later
|
||||
a definition for the non-versioned symbol is found. In that
|
||||
case the indirection is flipped with the versioned symbol
|
||||
becoming an indirect pointing at the non-versioned symbol.
|
||||
Thus, not an alias any more. */
|
||||
if (def->def_regular
|
||||
|| def->root.type != bfd_link_hash_defined)
|
||||
{
|
||||
h = def;
|
||||
while ((h = h->u.alias) != def)
|
||||
@ -2932,7 +2940,6 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
|
||||
BFD_ASSERT (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak);
|
||||
BFD_ASSERT (def->def_dynamic);
|
||||
BFD_ASSERT (def->root.type == bfd_link_hash_defined);
|
||||
(*bed->elf_backend_copy_indirect_symbol) (eif->info, def, h);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user