Bug 16504 - gold: internal error in override_version, at resolve.cc:61 with -flto
Summary: gold: internal error in override_version, at resolve.cc:61 with -flto
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.24
: P2 normal
Target Milestone: ---
Assignee: Cary Coutant
Depends on:
Reported: 2014-01-25 22:14 UTC by Zbigniew Jędrzejewski-Szmek
Modified: 2018-04-24 21:04 UTC (History)
2 users (show)

See Also:
Last reconfirmed:

Test case (923 bytes, application/x-xz)
2018-04-21 16:39 UTC, Bernhard Rosenkränzer

Note You need to log in before you can comment on or make changes to this bug.
Description Zbigniew Jędrzejewski-Szmek 2014-01-25 22:14:41 UTC
==> liba.c <==
const char* sd_get_seats(void) {return "bla bla";}

==> liba.sym <==

==> libb.c <==
void new_sd_get_seats(void);
__asm__(".symver new_sd_get_seats,sd_get_seats@LIBSYSTEMD_209");
static void (*resolve_sd_get_seats(void)) (void) {
        return new_sd_get_seats;
void sd_get_seats(void) __attribute__((ifunc("resolve_sd_get_seats")));

==> libb.sym <==

==> Makefile <==
        $(CC) $(LIBCFLAGS) -o $@ $< -Wl,--version-script=libb.sym -L. -la

test1: test1.c libb.so
        gcc -Wl,-rpath -Wl,. -L. -lb -o $@ $<

run: test1

        rm -f *.so *.o test1

==> test1.c <==
#include <stdio.h>
const char* sd_get_seats(void);

int main(int argc, char **argv) {
        printf("%s\n", sd_get_seats());
        return 0;
$ make
gcc -fPIC -shared -flto -Wl,-fuse-ld=gold -o liba.so liba.c -Wl,--version-script=liba.sym 
gcc -fPIC -shared -flto -Wl,-fuse-ld=gold -o libb.so libb.c -Wl,--version-script=libb.sym -L. -la
/usr/bin/ld.gold: internal error in override_version, at resolve.cc:61
collect2: error: ld returned 1 exit status
make: *** [libb.so] Error 1

ld.bfd seems to work fine.
Comment 1 H.J. Lu 2014-01-26 14:33:44 UTC
(In reply to Zbigniew Jędrzejewski-Szmek from comment #0)

> gcc -fPIC -shared -flto -Wl,-fuse-ld=gold -o liba.so liba.c
> -Wl,--version-script=liba.sym 

Please change your Makefile to use -fuse-ld=gold instead of
-Wl,-fuse-ld=gold, which makes it harder to cut/paste from
collect2 command line to ld.
Comment 2 Bernhard Rosenkränzer 2018-04-21 16:37:32 UTC
Reproduced with gold 2.30 (and with qtwebengine 5.11.0-beta4 as a real world example of this occurring).

The Makefile in the test case is obviously incomplete and should say something more like

all: test1
liba.so: liba.c
        $(CC) $(LIBCFLAGS) -fPIC -shared -flto -fuse-ld=gold -o $@ $< -Wl,--version-script=liba.sym -L.

libb.so: libb.c liba.so
        $(CC) $(LIBCFLAGS) -fPIC -shared -flto -fuse-ld=gold -o $@ $< -Wl,--version-script=libb.sym -L. -la

test1: test1.c libb.so
        gcc -Wl,-rpath -Wl,. -L. -lb -o $@ $<

        rm -f *.so *.o test1
Comment 3 Bernhard Rosenkränzer 2018-04-21 16:39:31 UTC
Created attachment 10970 [details]
Test case

Attaching test case files as tarball
Comment 4 Zbigniew Jędrzejewski-Szmek 2018-04-23 06:59:10 UTC
Bernhard, thanks for fixing the test case. Looks like I pasted only part of the file.

I don't have binutils-2.30 here yet, but I get the same result with binutils-2.29.1-20.fc28.x86_64.
Comment 5 cvs-commit@gcc.gnu.org 2018-04-24 20:58:26 UTC
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>:


commit 890d155592e66dc01fc4a9affba806c4e9fc36ba
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Mon Apr 23 09:27:35 2018 -0700

    Fix internal error caused by conflicting default version definitions.
    	PR gold/16504
    	* dynobj.cc (Versions::symbol_section_contents): Don't set
    	VERSYM_HIDDEN flag for undefined symbols.
    	* symtab.cc (Symbol_table::add_from_object): Don't override default
    	version definition with a different default version.
    	* symtab.h (Symbol::from_dyn): New method.
    	* testsuite/plugin_test.c (struct sym_info): Add ver field.
    	(claim_file_hook): Pass symbol version to plugin API.
    	(parse_readelf_line): Parse symbol version.
    	* testsuite/Makefile.am (ver_test_pr16504): New test case.
    	* testsuite/Makefile.in: Regenerate.
    	* testsuite/ver_test_pr16504.sh: New test script.
    	* testsuite/ver_test_pr16504_a.c: New source file.
    	* testsuite/ver_test_pr16504_a.script: New version script.
    	* testsuite/ver_test_pr16504_b.c: New source file.
    	* testsuite/ver_test_pr16504_b.script: New version script.
Comment 6 Cary Coutant 2018-04-24 21:04:19 UTC
Fixed on master branch.

The provided test case leaves me with a nervous feeling that
neither IFUNCs nor .symver directives are a good idea when
using LTO. For .symver at least, the compiler doesn't see the
real symbol name (it's just an asm pass-thru), so it could be
missing some important linkage information. For example, GCC
doesn't even tell the linker about the reference to
sd_get_seats@LIBSYSTEMD_209 when reading the IR, which could
affect the correctness of its optimizations.

It could theoretically figure out how IFUNCs work by
looking at the resolve function, but I'm not sure it does.