Bug 42690 - Undefined reference errors with -flto -fuse-linker-plugin
Summary: Undefined reference errors with -flto -fuse-linker-plugin
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: driver (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: ---
Assignee: Dave Korn
URL: http://gcc.gnu.org/ml/gcc-patches/201...
Keywords: lto, patch
Depends on:
Blocks: 46760
  Show dependency treegraph
 
Reported: 2010-01-11 15:23 UTC by Dmitry Gorbachev
Modified: 2010-12-06 17:54 UTC (History)
8 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2010-11-10 03:59:21


Attachments
testcase (141 bytes, text/plain)
2010-01-11 15:25 UTC, Dmitry Gorbachev
Details
1. Configured w/o --disable-shared, linking with a shared libgcc. (1.10 KB, text/plain)
2010-01-15 11:01 UTC, Dmitry Gorbachev
Details
2. Configured w/o --disable-shared, linking with a static libgcc (with -static). (1.11 KB, text/plain)
2010-01-15 11:02 UTC, Dmitry Gorbachev
Details
3. Configured with --disable-shared, linking with a static libgcc. (1.18 KB, text/plain)
2010-01-15 11:02 UTC, Dmitry Gorbachev
Details
4. Configured with --disable-shared, linking with a static libgcc (with -static). (1.11 KB, text/plain)
2010-01-15 11:02 UTC, Dmitry Gorbachev
Details
Simple patch (394 bytes, patch)
2010-01-18 18:48 UTC, Dmitry Gorbachev
Details | Diff
pass through stdlibs (1.72 KB, patch)
2010-11-10 04:51 UTC, Dave Korn
Details | Diff
Testcase for ld.bfd with Hongjiu Lu's patch (248 bytes, text/plain)
2010-12-04 22:29 UTC, Dmitry Gorbachev
Details
Backtrace from ld.bfd with Hongjiu Lu's patch (440 bytes, text/plain)
2010-12-04 22:31 UTC, Dmitry Gorbachev
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dmitry Gorbachev 2010-01-11 15:23:06 UTC
 
Comment 1 Dmitry Gorbachev 2010-01-11 15:25:11 UTC
Created attachment 19541 [details]
testcase

GCC 4.5.0 20100107.

gcc -flto -fuse-linker-plugin pr42690.c -DBUG
Comment 2 espindola 2010-01-12 16:29:56 UTC
Is the undefined reference to libgcc? Is it being linked statically? When linking libgcc statically the driver has to pass -plugin-opt=-pass-through=/foo/bar/libgcc.a to ld. This is done in gcc.c:

    %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)}	\
    %{static:-plugin-opt=-pass-through=-lc}	\

So, is there a better way to detect that we are linking libgcc statically?
Comment 3 Dmitry Gorbachev 2010-01-14 22:15:09 UTC
> Is the undefined reference to libgcc? Is it being linked statically?

Yes. In both cases (with and without -DBUG), the ld command line is

/usr/local/bin/ld -plugin /usr/local/libexec/gcc/i686-pc-linux-gnu/4.5.0/liblto_plugin.so -plugin-opt=/usr/local/libexec/gcc/i686-pc-linux-gnu/4.5.0/lto-wrapper -plugin-opt=i686-pc-linux-gnu-gcc-4.5.0 -plugin-opt=-flto -plugin-opt=-fuse-linker-plugin -plugin-opt=-mtune=generic --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.0/crtbegin.o -L/usr/local/lib/gcc/i686-pc-linux-gnu/4.5.0 -L/usr/local/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../i686-pc-linux-gnu/lib -L/usr/local/lib/gcc/i686-pc-linux-gnu/4.5.0/../../.. /tmp/ccEIWEH2.o -lgcc -lc -lgcc /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.0/crtend.o /usr/lib/crtn.o

However, this error only happens with -DBUG.
Comment 4 H.J. Lu 2010-01-15 03:41:19 UTC
Works for me:

[hjl@gnu-6 gold-2]$ vi pr42690.c
[hjl@gnu-6 gold-2]$ cat pr42690.c
int f(long long a, long long b)
{
#ifdef BUG
    return (int) (a / b);
#else
    return (int) __divdi3(a, b);
#endif
}

int main(void)
{
    return f(2718281828459045, 543656365691809);
}
[hjl@gnu-6 gold-2]$ /export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc -B./ -B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -B/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/ -flto -fuse-linker-plugin -DBUG pr42690.c
[hjl@gnu-6 gold-2]$ /export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc -v
Using built-in specs.
COLLECT_GCC=/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
Target: x86_64-unknown-linux-gnu
Configured with: /export/gnu/import/git/gcc/configure --enable-languages=c --disable-bootstrap --prefix=/usr/gcc-4.5.0 --with-local-prefix=/usr/local --with-plugin-ld=ld.gold --enable-gold
Thread model: posix
gcc version 4.5.0 20100114 (experimental) (GCC)
[hjl@gnu-6 gold-2]$
Comment 5 espindola 2010-01-15 03:54:53 UTC
Note that
-plugin-opt=-pass-through=/foo/bar/libgcc.a
is missing in the linker invocation.

That is the problem. When BUG is not defined, the undefined reference is visible early on. You can check that with

GNUTARGET=plugin nm --prugin ..../libltoplugin.so foo.o

If BUG is defined the plugin will not see a call since it will only created by codegen. That is why the driver asks the linker to take a second look at some libraries by passing the pass-through option.

We have to figure out a better way to detected in gcc.c that libgcc (and/or libc) will be linked statically.

H.J.Lu: You are probably linking with a shared libgcc, no?
Comment 6 H.J. Lu 2010-01-15 04:26:20 UTC
I got

[hjl@gnu-6 gold-2]$ /export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc -B./ -B/export/build/gnu/gcc/build-x86_64-linux/gcc/ -B/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/ -flto -fuse-linker-plugin -DBUG pr42690.c -v
Reading specs from /export/build/gnu/gcc/build-x86_64-linux/gcc/specs
COLLECT_GCC=/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
COLLECT_LTO_WRAPPER=/export/build/gnu/gcc/build-x86_64-linux/gcc/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /export/gnu/import/git/gcc/configure --enable-languages=c --disable-bootstrap --prefix=/usr/gcc-4.5.0 --with-local-prefix=/usr/local --with-plugin-ld=ld.gold --enable-gold
Thread model: posix
gcc version 4.5.0 20100114 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-B./' '-B/export/build/gnu/gcc/build-x86_64-linux/gcc/' '-B/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/' '-flto' '-fuse-linker-plugin' '-DBUG' '-v' '-mtune=generic'
 /export/build/gnu/gcc/build-x86_64-linux/gcc/cc1 -quiet -v -iprefix /export/build/gnu/gcc/build-x86_64-linux/gcc/../lib/gcc/x86_64-unknown-linux-gnu/4.5.0/ -isystem /export/build/gnu/gcc/build-x86_64-linux/gcc/include -isystem /export/build/gnu/gcc/build-x86_64-linux/gcc/include-fixed -DBUG pr42690.c -quiet -dumpbase pr42690.c -mtune=generic -auxbase pr42690 -version -flto -fuse-linker-plugin -o /tmp/ccgwrI0o.s
GNU C (GCC) version 4.5.0 20100114 (experimental) (x86_64-unknown-linux-gnu)
        compiled by GNU C version 4.4.2 20091222 (Red Hat 4.4.2-20), GMP version 4.3.1, MPFR version 2.4.2, MPC version 0.8
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
ignoring nonexistent directory "/export/build/gnu/gcc/build-x86_64-linux/gcc/../lib/gcc/x86_64-unknown-linux-gnu/4.5.0/include"
ignoring nonexistent directory "/export/build/gnu/gcc/build-x86_64-linux/gcc/../lib/gcc/x86_64-unknown-linux-gnu/4.5.0/include-fixed"
ignoring nonexistent directory "/export/build/gnu/gcc/build-x86_64-linux/gcc/../lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../x86_64-unknown-linux-gnu/include"
ignoring nonexistent directory "/export/build/gnu/gcc/build-x86_64-linux/gcc/../lib/gcc/../../include"
ignoring nonexistent directory "/export/build/gnu/gcc/build-x86_64-linux/gcc/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/4.5.0/include"
ignoring nonexistent directory "/export/build/gnu/gcc/build-x86_64-linux/gcc/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/4.5.0/include-fixed"
ignoring nonexistent directory "/export/build/gnu/gcc/build-x86_64-linux/gcc/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../x86_64-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /export/build/gnu/gcc/build-x86_64-linux/gcc/include
 /export/build/gnu/gcc/build-x86_64-linux/gcc/include-fixed
 /usr/local/include
 /usr/include
End of search list.
GNU C (GCC) version 4.5.0 20100114 (experimental) (x86_64-unknown-linux-gnu)
        compiled by GNU C version 4.4.2 20091222 (Red Hat 4.4.2-20), GMP version 4.3.1, MPFR version 2.4.2, MPC version 0.8
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: f1a6981d8022db97daab7f58c757004b
COLLECT_GCC_OPTIONS='-B./' '-B/export/build/gnu/gcc/build-x86_64-linux/gcc/' '-B/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/' '-flto' '-fuse-linker-plugin' '-DBUG' '-v' '-mtune=generic'
 /export/build/gnu/gcc/build-x86_64-linux/gcc/as -V -Qy -o /tmp/cckKXRh8.o /tmp/ccgwrI0o.s
GNU assembler version 2.20.51.0.5 (x86_64-unknown-linux-gnu) using BFD version (Linux/GNU Binutils) 2.20.51.0.5.20100115
COMPILER_PATH=./:/export/build/gnu/gcc/build-x86_64-linux/gcc/:/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/
LIBRARY_PATH=./:/export/build/gnu/gcc/build-x86_64-linux/gcc/:/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/:/lib/../lib64/:/usr/lib/../lib64/:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-B./' '-B/export/build/gnu/gcc/build-x86_64-linux/gcc/' '-B/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/' '-flto' '-fuse-linker-plugin' '-DBUG' '-v' '-mtune=generic'
 /export/build/gnu/gcc/build-x86_64-linux/gcc/collect2 -plugin /export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/liblto_plugin.so -plugin-opt=/export/build/gnu/gcc/build-x86_64-linux/gcc/lto-wrapper -plugin-opt=/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc -plugin-opt=-flto -plugin-opt=-fuse-linker-plugin -plugin-opt=-mtune=generic -plugin-opt=-v -flto --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/../lib64/crt1.o /usr/lib/../lib64/crti.o /export/build/gnu/gcc/build-x86_64-linux/gcc/crtbegin.o -L. -L/export/build/gnu/gcc/build-x86_64-linux/gcc -L/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/cckKXRh8.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /export/build/gnu/gcc/build-x86_64-linux/gcc/crtend.o /usr/lib/../lib64/crtn.o
collect2 version 4.5.0 20100114 (experimental) (x86-64 Linux/ELF)
/export/build/gnu/gcc/build-x86_64-linux/gcc/collect-ld -plugin /export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/liblto_plugin.so -plugin-opt=/export/build/gnu/gcc/build-x86_64-linux/gcc/lto-wrapper -plugin-opt=/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc -plugin-opt=-flto -plugin-opt=-fuse-linker-plugin -plugin-opt=-mtune=generic -plugin-opt=-v --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/../lib64/crt1.o /usr/lib/../lib64/crti.o /export/build/gnu/gcc/build-x86_64-linux/gcc/crtbegin.o -L. -L/export/build/gnu/gcc/build-x86_64-linux/gcc -L/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/cckKXRh8.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /export/build/gnu/gcc/build-x86_64-linux/gcc/crtend.o /usr/lib/../lib64/crtn.o
/export/build/gnu/gcc/build-x86_64-linux/gcc/lto-wrapper /export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc -flto -fuse-linker-plugin -mtune=generic -v -fresolution /tmp/cc2aKmVt /tmp/cckKXRh8.o
Reading specs from /export/build/gnu/gcc/build-x86_64-linux/gcc/specs
COLLECT_GCC=/export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
COLLECT_LTO_WRAPPER=/export/build/gnu/gcc/build-x86_64-linux/gcc/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /export/gnu/import/git/gcc/configure --enable-languages=c --disable-bootstrap --prefix=/usr/gcc-4.5.0 --with-local-prefix=/usr/local --with-plugin-ld=ld.gold --enable-gold
Thread model: posix
gcc version 4.5.0 20100114 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-combine' '-c' '-o' '/tmp/cc8GpHku.lto.o' '-fuse-linker-plugin' '-mtune=generic' '-v' '-fresolution'
 /export/build/gnu/gcc/build-x86_64-linux/gcc/lto1 -quiet -dumpbase cc2aKmVt -mtune=generic -auxbase-strip /tmp/cc8GpHku.lto.o -version -fuse-linker-plugin -fresolution @/tmp/ccgaL3ou -o /tmp/ccAe5LKd.s
GNU GIMPLE (GCC) version 4.5.0 20100114 (experimental) (x86_64-unknown-linux-gnu)
        compiled by GNU C version 4.4.2 20091222 (Red Hat 4.4.2-20), GMP version 4.3.1, MPFR version 2.4.2, MPC version 0.8
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
GNU GIMPLE (GCC) version 4.5.0 20100114 (experimental) (x86_64-unknown-linux-gnu)
        compiled by GNU C version 4.4.2 20091222 (Red Hat 4.4.2-20), GMP version 4.3.1, MPFR version 2.4.2, MPC version 0.8
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
COLLECT_GCC_OPTIONS='-combine' '-c' '-o' '/tmp/cc8GpHku.lto.o' '-fuse-linker-plugin' '-mtune=generic' '-v' '-fresolution'
 /export/build/gnu/gcc/build-x86_64-linux/gcc/as -V -Qy -o /tmp/cc8GpHku.lto.o /tmp/ccAe5LKd.s
GNU assembler version 2.20.51.0.5 (x86_64-unknown-linux-gnu) using BFD version (Linux/GNU Binutils) 2.20.51.0.5.20100115
COMPILER_PATH=./:/export/build/gnu/gcc/build-x86_64-linux/gcc/:/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/
LIBRARY_PATH=/lib/../lib64/../lib64/:/usr/lib/../lib64/../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/lib/../lib64/:/usr/lib/../lib64/:./:/export/build/gnu/gcc/build-x86_64-linux/gcc/:/export/build/gnu/gcc/build-x86_64-linux/gcc/../lto-plugin/.libs/:/lib/../lib64/:/usr/lib/../lib64/:/lib/:/usr/lib/:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-combine' '-c' '-o' '/tmp/cc8GpHku.lto.o' '-fuse-linker-plugin' '-mtune=generic' '-v' '-fresolution'
[hjl@gnu-6 gold-2]$
Comment 7 Dmitry Gorbachev 2010-01-15 11:01:50 UTC
Created attachment 19610 [details]
1. Configured w/o --disable-shared, linking with a shared libgcc.

Output of gcc -v
Comment 8 Dmitry Gorbachev 2010-01-15 11:02:15 UTC
Created attachment 19611 [details]
2. Configured w/o --disable-shared, linking with a static libgcc (with -static).
Comment 9 Dmitry Gorbachev 2010-01-15 11:02:42 UTC
Created attachment 19612 [details]
3. Configured with --disable-shared, linking with a static libgcc.
Comment 10 Dmitry Gorbachev 2010-01-15 11:02:58 UTC
Created attachment 19613 [details]
4. Configured with --disable-shared, linking with a static libgcc (with -static).
Comment 11 Dmitry Gorbachev 2010-01-15 11:03:48 UTC
GCC was configured with --disable-shared option. It seems that the driver does not understand that --disable-shared implies static libgcc
Comment 12 espindola 2010-01-15 15:28:51 UTC
(In reply to comment #11)
> GCC was configured with --disable-shared option. It seems that the driver does
> not understand that --disable-shared implies static libgcc
> 
That is correct. Currently we have

   %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)}     \
    %{static:-plugin-opt=-pass-through=-lc}     \

That is, --pass-through is only used for libgcc if -static or -static-libgcc is given. For libgcc we could probably find out if we are using a static one or not in a more accurate way.

For libc it is harder. The driver doesn't know that libc is static. It just passes -lc to ld.

It might be possible to change what we test for. I think it would be OK to always ask the plugin to pass libgcc and libc to the linker a second time *if they are being used at all*. My understanding is that an unnecessary static library will be ignored and a shared library will have no effect since it was already used anyway. 

To implement this we should always pass -plugin-opt=-pass-through=%(lto_libgcc) and -plugin-opt=-pass-through=-lc to the linker unless something like -nostdlib is used.

What options other than -nostdlib prevent gcc from linking libgcc and libc in the produced binary?
Comment 13 Dmitry Gorbachev 2010-01-16 16:55:50 UTC
(In reply to comment #12)

> What options other than -nostdlib prevent gcc from linking libgcc and
> libc in the produced binary?

I know of -nodefaultlibs.

> To implement this we should always pass -plugin-opt=-pass-through=
> %(lto_libgcc) and -plugin-opt=-pass-through=-lc to the linker unless
> something like -nostdlib is used.

Wouldn't it be better to add %{fuse-linker-plugin: -plugin-opt=-pass-through=...} to LIBGCC_SPEC and to LIB_SPEC?

However, the driver does not really know, whether we link with libgcc and/or libc. Someone can use -nodefaultlibs together with -lc -lgcc and the linker will still fail.
Comment 14 espindola 2010-01-17 05:47:24 UTC
I don't think that in general we can support things like -nodefaultlibs -lc -lgcc. Doing that with static libraries and lto is such an uncommon case that it is probably OK to ask the user to also pass -Wl,-pass-through...

I am not familiar with the driver code, but if we already have SPEC stings that are used only when linking libgcc or libc, that is the perfect place to add %{fuse-linker-plugin: -plugin-opt=-pass-through=...}
Comment 15 Dmitry Gorbachev 2010-01-18 18:48:17 UTC
Created attachment 19649 [details]
Simple patch

It leaves -plugin-opt in LINK_COMMAND_SPEC, but I think it is not quite right, as LIBGCC_SPEC and LIB_SPEC are redefined by many targets (and, for example, choose libc or libc_p depending on -p / -pg / -profile).

GCC r155915 bootstrapped with this patch on i686-pc-linux-gnu with and without --disable-shared option. It seems to work.
Comment 16 Dave Korn 2010-11-10 03:59:21 UTC
Confirmed that this still happens on HEAD.
Comment 17 Dave Korn 2010-11-10 04:51:28 UTC
Created attachment 22362 [details]
pass through stdlibs

(In reply to comment #12)

> It might be possible to change what we test for. I think it would be OK to
> always ask the plugin to pass libgcc and libc to the linker a second time *if
> they are being used at all*. My understanding is that an unnecessary static
> library will be ignored and a shared library will have no effect since it was
> already used anyway. 

I think this is a good approach, and it is even necessary for shared linking when using GNU LD on COFF platforms, I have been testing it for a little while now.

(In reply to comment #14)
> I don't think that in general we can support things like -nodefaultlibs -lc
> -lgcc. Doing that with static libraries and lto is such an uncommon case that
> it is probably OK to ask the user to also pass -Wl,-pass-through...

(In reply to comment #15)

> It leaves -plugin-opt in LINK_COMMAND_SPEC, but I think it is not quite right,
> as LIBGCC_SPEC and LIB_SPEC are redefined by many targets (and, for example,
> choose libc or libc_p depending on -p / -pg / -profile).

This patch uses a spec function to process the redefined versions themselves, as found in the link_gcc_c_sequence spec; it extracts anything that starts with "-l" or ends with ".a" and creates linker plugin pass-through options to match.

I'm running it through a battery of configurations overnight, vs both LD and GOLD, static and non-static, and lto-bootstraps.  If nothing shows up, I'll run it past the gcc-patches list and see what everyone thinks there.
Comment 18 Dave Korn 2010-11-16 15:03:21 UTC
Testing went well, submitting the patch shortly.
Comment 19 Dave Korn 2010-11-16 16:19:39 UTC
Posted.
Comment 20 H.J. Lu 2010-11-20 20:49:56 UTC
If we have to pass libgcc archive in GCC driver, what happens to
random archives on command line? Will LTO ignore them? It sounds
like a bad idea. I think the fix should be in linker, not in GCC
driver.
Comment 21 Dave Korn 2010-11-20 20:52:38 UTC
(In reply to comment #20)
> If we have to pass libgcc archive in GCC driver, what happens to
> random archives on command line? Will LTO ignore them? It sounds
> like a bad idea. I think the fix should be in linker, not in GCC
> driver.

  Link-time optimisations can only generate new undefined references to functions that GCC knows how to optimise as builtins, so I think this can only happen with libgcc and libc references.  In the case of user code and libraries, there should always be undefined references in the LTO symtabs to the required functions.
Comment 22 Jan Hubicka 2010-11-20 21:04:06 UTC
GCC will also auto-generate calls to libgcov at link time. This is one of reason why profiledbootstrap does not work with LTO (yet)
Comment 23 Jan Hubicka 2010-11-20 21:06:50 UTC
BTW I really think both gold and GNU ld will need to do two stage linking (i.e. fully re-link after LTO step).  Other problems involved in this include the fact that we can optimize out some library calls and currently I think the library will be still linked in and the issue with COMDATs.
(i.e. when GCC announce COMDAT function in symbol table and later inline it, it still need to produce out-of-line function body because linker handles is as PREVAIL). Finally -fwhole-program makes lto symtab entries to disappear.
Comment 24 H.J. Lu 2010-11-20 21:14:01 UTC
Can we do

1. GCC calls ld with -r to generate a .o file first.
2. GCC calls ld with the single .o input?
Comment 25 H.J. Lu 2010-11-22 18:02:47 UTC
The current linker plugin scheme may be flawed.  The order of
linking libraries (archive and DSO) is very important. They
have to be placed between crti.o and crtn.o. We may not link
an archive after crtn.o.
Comment 26 H.J. Lu 2010-11-22 18:27:58 UTC
One approach for linker plugin support may be:

1. GCC driver marks crtbegin.o and crtend.o.
2. Linker processes everything between crtbegin.o and crtend.o with GCC
LTO plugin.
3. Linker generates executable with the proper command line and GCC LTO
plugin outputs.
Comment 27 Dave Korn 2010-11-23 19:08:45 UTC
(In reply to comment #25)
> The current linker plugin scheme may be flawed.  The order of
> linking libraries (archive and DSO) is very important. They
> have to be placed between crti.o and crtn.o. We may not link
> an archive after crtn.o.

Sounds like crtn.o should be sent to the link via a further -pass-through option (positioned after the ones that re-scan the libraries) rather than directly on the command-line when the plugin is in use.
Comment 28 Dave Korn 2010-11-23 19:18:46 UTC
Author: davek
Date: Tue Nov 23 19:18:39 2010
New Revision: 167091

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=167091
Log:
	PR driver/42690
	* gcc.c (LINK_COMMAND_SPEC): Remove hard-coded pass-through plugin
	options, replace by call of pass-through-libs spec function to process
	link_gcc_c_sequence spec.
	(lto_libgcc_spec): Delete variable.
	(static_specs[]): Remove related entry.
	(static_spec_functions[]): Add new entry for pass-through-libs.
	(main): Don't generate deleted lto_libgcc_spec.
	(pass_through_libs_spec_func): New function to implement the new
	pass-through-libs spec function.
	* doc/invoke.texi (pass-through-libs): Document new spec function.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/doc/invoke.texi
    trunk/gcc/gcc.c
Comment 29 H.J. Lu 2010-11-23 23:43:55 UTC
Please note that -pass-through is a hack, not a real solution.
See

http://www.sourceware.org/bugzilla/show_bug.cgi?id=12248

for a testcase to show why it doesn't work correctly.
Comment 30 H.J. Lu 2010-11-24 15:07:17 UTC
Goal:  We should preserve the same linker command line order as if there are no IR.
Problem:
	a. LTO may generate extra symbol references which aren't in IR.
	b. It was worked around with -pass-through hack.  But it doesn't preserve the link command line order.

Proposal:
	a. Remove -pass-through hack.
	b. GCC always passes the same command line to linker, with or without LTO.  The only additions for LTO are LTO options.
	c. For linker:
		i. For a .o or DSO file on command line, don't process it.
			1) Present it to LTO:
				a) If it isn't claimed by LTO, send it to LTO as pass-through.
		ii. For an archive or linker script on command line:
			1) Present it to LTO recursively
			2) Send it to LTO as pass-through after it has been processed recursively. 
	d. For LTO:
		i. Send translated files as well as pass-through files to linker in the same order in which they are presented from linker.
Comment 31 Richard Biener 2010-11-25 10:50:34 UTC
*** Bug 46652 has been marked as a duplicate of this bug. ***
Comment 32 H.J. Lu 2010-12-02 17:15:52 UTC
Another testcase:

[hjl@gnu-6 pr12245-6]$ cat y.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int
main (int argc, char **argv)
{
  int d = atoi (argv[1]);
  printf ("%f\n", sin (d));
  return 0;
}
[hjl@gnu-6 pr12245-6]$ make
/usr/gcc-4.6/bin/gcc -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin   -c -o y.o y.c
/usr/gcc-4.6/bin/gcc -static -o foo -O2 -fwhole-program -flto=jobserver -fuse-linker-plugin y.o -lm
/tmp/ccrHdm25.ltrans0.ltrans.o: In function `main':
ccrHdm25.ltrans0.o:(.text.startup+0x19): undefined reference to `sin'
collect2: ld returned 1 exit status
make: *** [foo] Error 1
[hjl@gnu-6 pr12245-6]$
Comment 33 H.J. Lu 2010-12-04 17:37:39 UTC
This bug should be fixed with the 2 stage BFD linker patch:

http://sourceware.org/ml/binutils/2010-12/msg00182.html

No changes to GCC are needed.
Comment 34 Dmitry Gorbachev 2010-12-04 22:29:59 UTC
Created attachment 22633 [details]
Testcase for ld.bfd with Hongjiu Lu's patch

(In reply to comment #33)

Received SIGSEGV on this testcase.
Comment 35 Dmitry Gorbachev 2010-12-04 22:31:01 UTC
Created attachment 22634 [details]
Backtrace from ld.bfd with Hongjiu Lu's patch
Comment 36 H.J. Lu 2010-12-05 00:44:37 UTC
(In reply to comment #34)
> Created attachment 22633 [details]
> Testcase for ld.bfd with Hongjiu Lu's patch
> 
> (In reply to comment #33)
> 
> Received SIGSEGV on this testcase.

Please try:

http://sourceware.org/ml/binutils/2010-12/msg00191.html
Comment 37 Dmitry Gorbachev 2010-12-05 12:37:26 UTC
(In reply to comment #36)

It seems to work. Thanks.
Comment 38 Dmitry Gorbachev 2010-12-05 16:48:38 UTC
(In reply to comment #36)

$ touch empty.c
$ gcc -nodefaultlibs -r -flto -fuse-linker-plugin empty.c
/usr/local/bin/ld: BFD (GNU Binutils) 2.21.51.20101204 assertion fail ../../binutils-2.21.51/bfd/elflink.c:9661
/usr/local/bin/ld: BFD (GNU Binutils) 2.21.51.20101204 assertion fail ../../binutils-2.21.51/bfd/elflink.c:7972
[...]
Comment 39 H.J. Lu 2010-12-05 18:23:55 UTC
(In reply to comment #38)
> (In reply to comment #36)
> 
> $ touch empty.c
> $ gcc -nodefaultlibs -r -flto -fuse-linker-plugin empty.c
> /usr/local/bin/ld: BFD (GNU Binutils) 2.21.51.20101204 assertion fail
> ../../binutils-2.21.51/bfd/elflink.c:9661
> /usr/local/bin/ld: BFD (GNU Binutils) 2.21.51.20101204 assertion fail
> ../../binutils-2.21.51/bfd/elflink.c:7972
> [...]

Please try:

http://sourceware.org/ml/binutils/2010-12/msg00197.html
Comment 40 Dave Korn 2010-12-06 17:54:12 UTC
The implicit -static problem is fixed at the gcc end, and the remaining aspects of this problem will be resolved by HJ's patch to binutils (see 'See also' URL).