Summary: | multiple prevailing defs for unused variable in lto mode | ||
---|---|---|---|
Product: | binutils | Reporter: | Martin Liska <mliska> |
Component: | ld | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED INVALID | ||
Severity: | normal | CC: | dobonachea, hjl.tools, hubicka |
Priority: | P2 | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
See Also: | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86490 | ||
Host: | Target: | ||
Build: | Last reconfirmed: | 2018-07-02 00:00:00 |
Description
Martin Liska
2018-06-28 12:50:06 UTC
Which version of ld are you using? Master branch works for me: hjl@gnu-cfl-1 pr23350]$ make clean rm -f *.o *.so [hjl@gnu-cfl-1 pr23350]$ cat x.c int wrl; int main() { } [hjl@gnu-cfl-1 pr23350]$ cat y.c int wrl; int wrl2; [hjl@gnu-cfl-1 pr23350]$ make /usr/gcc-7.2.1-x32/bin/gcc -flto -O2 -c -o x.o x.c /usr/gcc-7.2.1-x32/bin/gcc -flto -O2 -c -o y.o y.c ar --plugin `/usr/gcc-7.2.1-x32/bin/gcc -print-prog-name=liblto_plugin.so` -rusc liby.a y.o /usr/gcc-7.2.1-x32/bin/gcc -o x x.o liby.a liby.a [hjl@gnu-cfl-1 pr23350]$ (In reply to H.J. Lu from comment #1) > Which version of ld are you using? Master branch works for me: > > hjl@gnu-cfl-1 pr23350]$ make clean > rm -f *.o *.so > [hjl@gnu-cfl-1 pr23350]$ cat x.c > int wrl; > > int main() > { > } > [hjl@gnu-cfl-1 pr23350]$ cat y.c > int wrl; > int wrl2; > [hjl@gnu-cfl-1 pr23350]$ make > /usr/gcc-7.2.1-x32/bin/gcc -flto -O2 -c -o x.o x.c > /usr/gcc-7.2.1-x32/bin/gcc -flto -O2 -c -o y.o y.c > ar --plugin `/usr/gcc-7.2.1-x32/bin/gcc -print-prog-name=liblto_plugin.so` > -rusc liby.a y.o > /usr/gcc-7.2.1-x32/bin/gcc -o x x.o liby.a liby.a > [hjl@gnu-cfl-1 pr23350]$ I've just updated to GNU ld (GNU Binutils; openSUSE Tumbleweed) 2.30.0.20180320-5 and the issue is gone. Thus closing as invalid. So still present, shows here: $ cat main.i int wrl; $ cat lib.i int wrl; void a() {} $ gcc -c -flto main.i && gcc -c -flto lib.i && ar rusc lib.a lib.o $ gcc main.o lib.a lib.a lto1: fatal error: multiple prevailing defs for ‘a’ compilation terminated. lto-wrapper: fatal error: gcc returned 1 exit status compilation terminated. /usr/lib64/gcc/x86_64-suse-linux/8/../../../../x86_64-suse-linux/bin/ld: error: lto-wrapper failed collect2: error: ld returned 1 exit status For: $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib64/gcc/x86_64-suse-linux/8/lto-wrapper OFFLOAD_TARGET_NAMES=hsa:nvptx-none Target: x86_64-suse-linux Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,ada,go --enable-offload-targets=hsa,nvptx-none=/usr/nvptx-none, --without-cuda-driver --enable-checking=release --disable-werror --with-gxx-include-dir=/usr/include/c++/8 --enable-ssp --disable-libssp --disable-libvtv --disable-cet --disable-libcc1 --enable-plugin --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --with-gcc-major-version-only --enable-linker-build-id --enable-linux-futex --enable-gnu-indirect-function --program-suffix=-8 --without-system-libunwind --enable-multilib --with-arch-32=x86-64 --with-tune=generic --build=x86_64-suse-linux --host=x86_64-suse-linux Thread model: posix gcc version 8.1.1 20180614 [gcc-8-branch revision 261584] (SUSE Linux) $ ld --version GNU ld (GNU Binutils; openSUSE Tumbleweed) 2.30.0.20180320-5 Copyright (C) 2018 Free Software Foundation, Inc. This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) a later version. This program has absolutely no warranty. What difference does it make? This is undefined behavior. It doesn't link -fno-lto either. gcc -c main.i && gcc -c lib.i && ar rusc lib.a lib.o gcc main.o lib.a lib.a /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o: in function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status Find an example where the -fno-lto link succeeds. ld is loading the object files in the libraries because it's searching for main. If I add a main() to lib.i it links successfully with -flto - the 2nd load of lib.a sets the duplicate symbol resolutions to PREEMPTED_IR. The error with -flto is only if main is not found - which is also an error in -fno-lto. (In reply to Martin Liska from comment #3) > So still present, shows here: > > $ cat main.i > int wrl; > > $ cat lib.i > int wrl; > void a() {} > > $ gcc -c -flto main.i && gcc -c -flto lib.i && ar rusc lib.a lib.o > $ gcc main.o lib.a lib.a > lto1: fatal error: multiple prevailing defs for ‘a’ > compilation terminated. > lto-wrapper: fatal error: gcc returned 1 exit status > compilation terminated. > /usr/lib64/gcc/x86_64-suse-linux/8/../../../../x86_64-suse-linux/bin/ld: > error: lto-wrapper failed > collect2: error: ld returned 1 exit status > Linker checks lib.a to see if there is a non-COMMON definition for wrl. But linker never includes lib.o in the final link. What makes lto1 believe that lib.o is needed? Sorry for not precise reproducer. I was reducing that from an existing package that normally succeeds w/o LTO. So what about this: $ cat main.i int wrl; int main () { return 0; } $ cat lib.i int wrl; void a() {} $ gcc -c main.i && gcc -c lib.i && ar rusc lib.a lib.o && gcc main.o lib.a lib.a This works fine, however: $ gcc -c -flto main.i && gcc -c -flto lib.i && ar rusc lib.a lib.o && gcc main.o lib.a lib.a -flto --save-temps lto1: fatal error: multiple prevailing defs for ‘a’ compilation terminated. lto-wrapper: fatal error: gcc returned 1 exit status compilation terminated. /usr/lib64/gcc/x86_64-suse-linux/8/../../../../x86_64-suse-linux/bin/ld: error: lto-wrapper failed collect2: error: ld returned 1 exit status $ cat lib.res 3 main.o 2 198 5dfd76773c77e89 PREVAILING_DEF main 202 5dfd76773c77e89 PREVAILING_DEF_IRONLY wrl lib.a@0x92 2 198 e65cc6ac1d79da7a PREVAILING_DEF_IRONLY a 202 e65cc6ac1d79da7a RESOLVED_IR wrl lib.a@0x92 2 198 e65cc6ac1d79da7a PREVAILING_DEF_IRONLY a 202 e65cc6ac1d79da7a RESOLVED_IR wrl Hope it's fine test-case? get_symbols has if (!blhe) { /* The plugin is called to claim symbols in an archive element from plugin_object_p. But those symbols aren't needed to create output. They are defined and referenced only within IR. */ But there is no way to tell LTO plugin to drop this symbol. This is a GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86490 We recently hit what appears to be this same problem with our software. I stumbled upon a workaround, which is to declare one of the tentative definitions as extern. Here's a demonstration applied to the code from comment #6: $ gcc --version gcc (GCC) 9.2.0 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ tail *.c ==> lib.c <== int wrl; extern int a() { return 0; } ==> main.c <== #ifdef WORKAROUND extern int wrl; #else int wrl; #endif int main () { return 0; } $ gcc -c -flto main.c && gcc -c -flto lib.c && gcc-ar rusc lib.a lib.o && gcc -flto main.o lib.a lib.a lto1: fatal error: multiple prevailing defs for 'a' compilation terminated. lto-wrapper: fatal error: gcc returned 1 exit status compilation terminated. /usr/bin/ld: error: lto-wrapper failed collect2: error: ld returned 1 exit status $ gcc -DWORKAROUND -c -flto main.c && gcc -c -flto lib.c && gcc-ar rusc lib.a lib.o && gcc -flto main.o lib.a lib.a In our case we are always providing a common-block definition from inside the library, so the workaround just meant declaring as extern in the library header file which is the declaration client objects see. Probably not applicable to all situations, but good enough to solve our problem. Hope this helps.. |