The bug is triggered by the --as-needed switch. The problem is in bfd/elflink.c in the function elf_link_add_object_symbols(). When an input file is linked with the ---as-needed in effect, the elf_link_add_object_symbols() function (1) clones the symbol table; (2) adds the new information (3) restores the symbol table if it turns out that the new input is *not* needed. The problem is that on bullet (2) things are modified that aren't restored on bullet (3). The main problem is that elf_link_add_object_symbols() calls the *bed->elf_backend_copy_indirect_symbol() function both directly and in a nested way on some calls of _bfd_elf_merge_symbol(). elf_backend_copy_indirect_symbol is elfNN_ia64_hash_copy_indirect() on ia64 (in /bfd/elfnn-ia64.c). elfNN_ia64_hash_copy_indirect() moves the info about the usage of dynamic symbols from one symbol to another; it is an array of struct elfNN_ia64_link_hash_entry in separately allocated memory. It sets the ->info member of the symbol to NULL and adjusts the ->h member of all dynamic symbols to the target symbol. When elf_link_add_object_symbols() restores the symbol table (3), the ->info member (which was NULL) is set to the former array of dynamic symbols, but the ->h members of the dynmaic symbols point to another symbol. The other symbol is deleted (freed memory); when the implementation walks through the symbols in a later stage, the crash occurs. (The failed assert is just a side effect.) There is another thing which is modified on (2) but isn't restored on (3): The bfd_elf_link_record_dynamic_symbol() function is called, which may add a new string to the string table via _bfd_elf_strtab_add(). Since the string table isn't restored by elf_link_add_object_symbols (3), the result is a failing assert on writing out the string table on a later stage: bfd/elf-strtab.c:273: BFD_ASSERT (tab->array[i]->refcount == 0); ref: http://bugs.debian.org/718047
bisecting back, this started crashing when the fix for PR ld/12549 went in: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=ffa9430db119a35786d64ffa50af9c2c368d210f whether that just uncovered a diff bug though ...
I'm not sure if this is the same bug or not, but I just ran into this today. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=887644
Created attachment 10753 [details] backtrace and stack variables Here is the gdb info I attached to the Debian bug.
Apparently the set of people who care about ia64 and the set of people who know enough to fix this bug are disjoint. So ia64 has never had a working --as-needed. --as-needed was implemented originally in 2004 and working for most targets around 2006. As noted by the original reporter, the problem is that elfNN_ia64_link_hash_entry carries on-the-side data, elfNN_ia64_dyn_sym_info. This on-the-side data can be free'd or modified when adding symbols. So enough state would need to be kept about the original elfNN_ia64_dyn_sym_info for it to be restored. The hook to do these tricks is elf_backend_data.notice_as_needed which will need implementing in the ia64 backend if 2.29 --as-needed is to be fixed. Alternatively, rewrite the generic --as-needed support to check whether a library is needed without modifying symbol state.. The good news is that this problem should disappear with 2.30, since check_relocs (which is where the on-the-side data is created) runs after symbols have been resolved.
This appears to work as of binutils 2.30, but I was wondering if the patch included in https://sourceware.org/bugzilla/show_bug.cgi?id=15904 could have possibly fixed it as well. I will try adding it to 2.29 and see what happens WRT --as-needed.
.