Bug 15891 - ia64, ld segfault on --as-needed
Summary: ia64, ld segfault on --as-needed
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.24
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-08-26 09:01 UTC by Mathieu Malaterre
Modified: 2022-11-24 11:14 UTC (History)
4 users (show)

See Also:
Host:
Target: ia64-linux-gnu
Build:
Last reconfirmed:


Attachments
backtrace and stack variables (2.68 KB, text/plain)
2018-01-18 17:03 UTC, Jason Duerstock
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mathieu Malaterre 2013-08-26 09:01:53 UTC
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
Comment 1 Mike Frysinger 2015-05-08 04:41:21 UTC
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 ...
Comment 2 Jason Duerstock 2018-01-18 16:56:21 UTC
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
Comment 3 Jason Duerstock 2018-01-18 17:03:29 UTC
Created attachment 10753 [details]
backtrace and stack variables

Here is the gdb info I attached to the Debian bug.
Comment 4 Alan Modra 2018-01-23 10:04:51 UTC
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.
Comment 5 Jason Duerstock 2018-02-21 13:54:21 UTC
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.
Comment 6 Alan Modra 2022-11-24 11:14:59 UTC
.