Created attachment 5131 [details] A testcase [hjl@gnu-35 pr12245]$ make /export/gnu/import/svn/gcc-test-spec/usr/bin/gcc -m32 -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin -c -o x.o x.c /export/gnu/import/svn/gcc-test-spec/usr/bin/gcc -m32 -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin -c -o y.o y.c /export/gnu/import/svn/gcc-test-spec/usr/bin/gcc -m32 -o foo -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin x.o y.o /tmp/ccVUrOVB.ltrans0.ltrans.o: In function `main': ccVUrOVB.ltrans0.o:(.text+0x2b): undefined reference to `__udivdi3' collect2: ld returned 1 exit status make: *** [foo] Error 1 [hjl@gnu-35 pr12245]$
This bug may generate incorrect binaries. We may need to recheck all archives after all ltrans object files are processed.
This is GCC PR42690, for which I have a patch that's just completed testing.
(In reply to comment #2) > This is GCC PR42690, for which I have a patch that's just completed testing. Why does GOLD work fine? [hjl@gnu-35 pr12245]$ make /export/gnu/import/svn/gcc-test-spec/usr.bfd/bin/gcc -m32 -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin -c -o x.o x.c /export/gnu/import/svn/gcc-test-spec/usr.bfd/bin/gcc -m32 -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin -c -o y.o y.c /export/gnu/import/svn/gcc-test-spec/usr.bfd/bin/gcc -m32 -o foo -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin x.o y.o /tmp/ccEqvHaO.ltrans0.ltrans.o: In function `main': ccEqvHaO.ltrans0.o:(.text+0x2b): undefined reference to `__udivdi3' collect2: ld returned 1 exit status make: *** [foo] Error 1 [hjl@gnu-35 pr12245]$ /export/gnu/import/svn/gcc-test-spec/usr.bfd/bin/gcc -v Using built-in specs. COLLECT_GCC=/export/gnu/import/svn/gcc-test-spec/usr.bfd/bin/gcc COLLECT_LTO_WRAPPER=/export/gnu/import/svn/gcc-test-spec/usr.bfd/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.6.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: /export/gnu/import/git/gcc/configure --enable-clocale=gnu --with-system-zlib --with-demangler-in-ld --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --enable-haifa --prefix=/usr/gcc-4.6.0 --with-local-prefix=/usr/local --with-fpmath=sse --with-plugin-ld=ld Thread model: posix gcc version 4.6.0 20101119 (experimental) (GCC) [hjl@gnu-35 pr12245]$ make clean rm -f *.o foo a.out [hjl@gnu-35 pr12245]$ make /export/gnu/import/svn/gcc-test-spec/usr/bin/gcc -m32 -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin -c -o x.o x.c /export/gnu/import/svn/gcc-test-spec/usr/bin/gcc -m32 -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin -c -o y.o y.c /export/gnu/import/svn/gcc-test-spec/usr/bin/gcc -m32 -o foo -O3 -fwhole-program -flto=jobserver -fuse-linker-plugin x.o y.o ./foo 2147478250 [hjl@gnu-35 pr12245]$ /export/gnu/import/svn/gcc-test-spec/usr/bin/gcc -v Using built-in specs. COLLECT_GCC=/export/gnu/import/svn/gcc-test-spec/usr/bin/gcc COLLECT_LTO_WRAPPER=/export/gnu/import/svn/gcc-test-spec/usr/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.6.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: /export/gnu/import/git/gcc/configure --enable-clocale=gnu --with-system-zlib --with-demangler-in-ld --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --enable-haifa --prefix=/usr/gcc-4.6.0 --with-local-prefix=/usr/local --with-fpmath=sse --with-plugin-ld=ld.gold --enable-gold Thread model: posix gcc version 4.6.0 20101119 (experimental) (GCC) [hjl@gnu-35 pr12245]$
Created attachment 5132 [details] build results with static linking vs gold Even GOLD fails when static linking is in use, as in this LTO-bootstrap run of GCC configured with "--disable-shared --enable-shared=lto-plugin --with-plugin-ld=gold --enable-gold". I am not yet sure what it is exactly that GOLD does differently internally that makes it pick up dynamic library references.
Created attachment 5136 [details] A new testcase -pass-through is a hack, not a real solution. Here is a testcase where __udivdi3 in div.c should override the one in libgcc.a: [hjl@gnu-6 pr12245-2]$ make /export/build/gnu/gcc/release/usr/gcc-4.6.0/bin/gcc -m32 -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin -c -o y.o y.c /export/build/gnu/gcc/release/usr/gcc-4.6.0/bin/gcc -m32 -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin -c -o x.o x.c /export/build/gnu/gcc/release/usr/gcc-4.6.0/bin/gcc -m32 -c -o div.o div.c ar rv libdiv.a div.o r - div.o /export/build/gnu/gcc/release/usr/gcc-4.6.0/bin/gcc -m32 -B./ -o foo -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin y.o x.o libdiv.a ./foo 2145852098 make: *** [all] Aborted [hjl@gnu-6 pr12245-2]$ make clean rm -f *.o foo a.out [hjl@gnu-6 pr12245-2]$ make CFLAGS=-O3 /export/build/gnu/gcc/release/usr/gcc-4.6.0/bin/gcc -m32 -O3 -c -o y.o y.c /export/build/gnu/gcc/release/usr/gcc-4.6.0/bin/gcc -m32 -O3 -c -o x.o x.c /export/build/gnu/gcc/release/usr/gcc-4.6.0/bin/gcc -m32 -O3 -c -o div.o div.c ar rv libdiv.a div.o r - div.o /export/build/gnu/gcc/release/usr/gcc-4.6.0/bin/gcc -m32 -B./ -o foo -O3 y.o x.o libdiv.a ./foo 1 [hjl@gnu-6 pr12245-2]$
Created attachment 5137 [details] A testcase to show linker order LTO plugin should preserve linker order. Otherwise, we will generate incorrect executables.
The patch is posted at http://sourceware.org/ml/binutils/2010-12/msg00207.html
(In reply to comment #6) This testcase shows that 2-stage BFD linker changes the order of linking. ld.hjl takes a definition of __udivdi3 (which is referred to by bar in x.o) from libdiv.a (not from libgcc, not from libc), though libdiv.a appears before x.o on the command line: gcc -B./ -o foo -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin y.o libdiv.a x.o GCC documentation: "[T]he linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded." Can this behavior cause any problems in practice?
(In reply to comment #8) > (In reply to comment #6) > > This testcase shows that 2-stage BFD linker changes the order of linking. > > ld.hjl takes a definition of __udivdi3 (which is referred to by bar in x.o) > from libdiv.a (not from libgcc, not from libc), though libdiv.a appears before > x.o on the command line: > > gcc -B./ -o foo -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin y.o > libdiv.a x.o > When there are "IR-object non-IR-archive IR-object" on command line, LTO makes it equivalent to "IR-object IR-object non-IR-archive".
(In reply to comment #9) > When there are "IR-object non-IR-archive IR-object" on command line, > LTO makes it equivalent to "IR-object IR-object non-IR-archive". It seems this behavior isn't documented. > When there are "IR-object non-IR-archive IR-object" on command line, > LTO makes it equivalent to "IR-object IR-object non-IR-archive". It also happens with IR-archive (though IR is not used: "ld.hjl: LTO IR sections in libdiv.a(div.o) aren't used in stage 2 linking"). Behavior of ld.ian depends on pass-through hack in the driver. With a hack, it takes __udivdi3 from libgcc. Without -pass-through options, it silently uses non-IR part of libdiv.a.
(In reply to comment #10) > (In reply to comment #9) > > When there are "IR-object non-IR-archive IR-object" on command line, > > LTO makes it equivalent to "IR-object IR-object non-IR-archive". > > It seems this behavior isn't documented. > > > When there are "IR-object non-IR-archive IR-object" on command line, > > LTO makes it equivalent to "IR-object IR-object non-IR-archive". > > It also happens with IR-archive (though IR is not used: "ld.hjl: LTO IR > sections in libdiv.a(div.o) aren't used in stage 2 linking"). I can change linker to skip archives between LTO claimed objects in stage 2 linking.
(In reply to comment #10) > (In reply to comment #9) > > When there are "IR-object non-IR-archive IR-object" on command line, > > LTO makes it equivalent to "IR-object IR-object non-IR-archive". > > It seems this behavior isn't documented. It is fixed by commit 5ec86f21a2370249ae49ffb3dc0e438d67a39522 on hjl/lto-mixed branch. > > When there are "IR-object non-IR-archive IR-object" on command line, > > LTO makes it equivalent to "IR-object IR-object non-IR-archive". > > It also happens with IR-archive (though IR is not used: "ld.hjl: LTO IR > sections in libdiv.a(div.o) aren't used in stage 2 linking"). > I will try to change linker to ignore libdiv.a(div.o) in this case.
(In reply to comment #10) > It also happens with IR-archive (though IR is not used: "ld.hjl: LTO IR > sections in libdiv.a(div.o) aren't used in stage 2 linking"). > Fixed by commit baf9b44566e088687f28f9fe476122876c1d2f4d on hjl/lto-mixed branch.
Now `gcc -B./ -o foo -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin x.o libdiv.a y.o' uses __udivdi3 from libgcc. Plain non-LTO link takes it from libdiv.a. Inconsistency, again...
(In reply to comment #14) > Now `gcc -B./ -o foo -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin > x.o > libdiv.a y.o' uses __udivdi3 from libgcc. Plain non-LTO link takes it from > libdiv.a. Inconsistency, again... It is consistent since LTO in x.o doesn't reference __udivdi3 while non-LTO in x.o references __udivdi3.
It looks counterintuitive to me. > LTO in x.o doesn't reference __udivdi3 But a reference to __udivdi3 from bar is generated on LTO step: /tmp/cczLpgd5.ltrans0.ltrans.o: reference to __udivdi3 BTW, behavior of `gcc -B./ -o foo -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin y.o x.o libdiv.a' depends on the presence / absence of IR sections in libdiv.a (links with libgcc / libdiv.a). I think it's a bug.
(In reply to comment #16) > It looks counterintuitive to me. > > > LTO in x.o doesn't reference __udivdi3 > > But a reference to __udivdi3 from bar is generated on LTO step: > /tmp/cczLpgd5.ltrans0.ltrans.o: reference to __udivdi3 This is internal implementation of LTO, which calls __udivdi3 in libgcc. LTO may also choose to inline it. > BTW, behavior of `gcc -B./ -o foo -O2 -fwhole-program -flto=jobserver > -fuse-linker-plugin y.o x.o libdiv.a' depends on the presence / absence of IR > sections in libdiv.a (links with libgcc / libdiv.a). I think it's a bug. This is intentional. Since libdiv.a with IR isn't used by LTO in stage 1 linking, it can't be used in stage 2 either. Otherwise, stage 2 linking may lead to undefined symbols if libdiv uses some external variables, which are defined in some IR inputs and optimized out by LTO since LTO didn't see their references in libdiv.a. I checked some LTO testcases into hjl/lto-mixed branch to verify it.
If ld.hjl behavior is correct, then it should be documented, and other linkers (ld.bfd/ld.dk, ld.gold) should be changed to conform to it; or there can be bugs in programs due to subtle differences in the linking order.
(In reply to comment #18) > If ld.hjl behavior is correct, then it should be documented, and other linkers > (ld.bfd/ld.dk, ld.gold) should be changed to conform to it; or there can be > bugs in programs due to subtle differences in the linking order. I think you should raise this issue in the gcc mailing list.
2.23 works correctly.
It is tracked by "LTO 1" test in ld-plugin.