==> liba.c <== const char* sd_get_seats(void) {return "bla bla";} ==> liba.sym <== LIBSYSTEMD_209 { global: sd_get_seats; }; ==> 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 <== LIBSYSTEMD_208 { global: sd_get_seats; }; ==> 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 ./test1 clean: 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.
(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.
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 $@ $< clean: rm -f *.so *.o test1
Created attachment 10970 [details] Test case Attaching test case files as tarball
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.
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=890d155592e66dc01fc4a9affba806c4e9fc36ba 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. gold/ 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.
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.