[hjl@gnu-6 lto]$ cat test.c extern int x; void foobar (void) { x--; } [hjl@gnu-6 lto]$ cat test-weak.c #include <stdio.h> int x; __attribute__((weak)) void foobar (void) { x++; } int main (void) { foobar (); if (x == -1) printf ("OK\n"); return 0; } [hjl@gnu-6 lto]$ make gcc -flto -O2 -c -o test-weak.o test-weak.c gcc -flto -O2 -nostdlib -r -o test-intermediate.o test-weak.o readelf -sW test-intermediate.o | grep foobar 10: 0000000000000000 8 FUNC GLOBAL DEFAULT 1 foobar gcc -flto -O2 -c -o test.o test.c gcc -flto -O2 test-intermediate.o test.o -o prog test.o (symbol from plugin): In function `foobar': (.text+0x0): multiple definition of `foobar' test-intermediate.o:(.text+0x0): first defined here /tmp/cciS2u59.ltrans0.ltrans.o: In function `foobar': <artificial>:(.text+0x0): multiple definition of `foobar' test-intermediate.o:(.text+0x0): first defined here collect2: error: ld returned 1 exit status Makefile:11: recipe for target 'prog' failed make: *** [prog] Error 1 [hjl@gnu-6 lto]$
It was caused by r210592.
This may be a linker bug if it tells GCC that a weak symbol is prevailing with "ld -r".
We have enum ld_plugin_symbol_resolution { LDPR_UNKNOWN = 0, /* Symbol is still undefined at this point. */ LDPR_UNDEF, /* This is the prevailing definition of the symbol, with references from regular object code. */ LDPR_PREVAILING_DEF, /* This is the prevailing definition of the symbol, with no references from regular objects. It is only referenced from IR code. */ LDPR_PREVAILING_DEF_IRONLY, /* This definition was pre-empted by a definition in a regular object file. */ LDPR_PREEMPTED_REG, /* This definition was pre-empted by a definition in another IR file. */ LDPR_PREEMPTED_IR, /* This symbol was resolved by a definition in another IR file. */ LDPR_RESOLVED_IR, /* This symbol was resolved by a definition in a regular object linked into the main executable. */ LDPR_RESOLVED_EXEC, /* This symbol was resolved by a definition in a shared object. */ LDPR_RESOLVED_DYN, /* This is the prevailing definition of the symbol, with no references from regular objects. It is only referenced from IR code, but the symbol is exported and may be referenced from a dynamic object (not seen at link time). */ LDPR_PREVAILING_DEF_IRONLY_EXP }; None of them is applicable to a weakdef with "ld -r".
It is wrong to clear DECL_WEAK: DECL_WEAK (next->decl) = false;
> None of them is applicable to a weakdef with "ld -r". Yep, GCC simply assumes that incremental linking is not going to happen and it makes strong assumptions about visibility in static&PIC binaries. To support incremental linking we need a way to pass this information to GCC. Either by extra codes or by informing the plugin that linking is incremental. See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64860 Honza
(In reply to Jan Hubicka from comment #5) > > None of them is applicable to a weakdef with "ld -r". > Yep, GCC simply assumes that incremental linking is not going to happen and > it makes strong assumptions > about visibility in static&PIC binaries. > To support incremental linking we need a way to pass this information to > GCC. Either by extra codes or > by informing the plugin that linking is incremental. > See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64860 > > Honza Linker passes this /* The type of output file being generated by the linker. */ enum ld_plugin_output_file_type { LDPO_REL, LDPO_EXEC, LDPO_DYN, LDPO_PIE }; to GCC plug-in. But this information is never used by GCC plug-in.
I thought we do nothing in an incremental link but concat the LTO input sections? That's why we put that $ID suffix on the section names. So maybe with plugin auto-loading (and thus slim objects?) the LTO plugin shouldn't claim any files with LDPO_REL mode.
There are two incremental link implementations: 1) HJ's binutils will concat the sections, 2) mainline binutils will invoke GCC via plugin and produce .o file with final assembly. The correct implementation IMO is 3) invoke GCC via plugin and produce the merge LTO file (i.e. cut the process before WPA optimization starts and stream out everything again). 3) would be only way to also support fat LTO files. Sadly we do not have plugin API interface for 2) or 3). 2) would be relatively easy - we only need to make GCC know it does incremental linking and assume that every symbol can be bound externally. I did not find way how to get this situation detected from the plugin/wrapper though and I am not sure how useful it is in practice given that it won't give you whole program optimization.
Aha, missed HJ's comment. If we have the info on type of file, this ought to be relatively easy to fix. I will look into it.
Author: hubicka Date: Wed Nov 25 23:05:07 2015 New Revision: 230915 URL: https://gcc.gnu.org/viewcvs?rev=230915&root=gcc&view=rev Log: PR lto/67548 * lto-plugin.c (linker_output, linker_output_set): New statics. (all_symbols_read_handler): Add -flinker-output option. (onload): Record linker_output info. * ipa-visibility.c (cgraph_externally_visible_p, varpool_node::externally_visible_p): When doing incremental linking, hidden symbols may be still used later. (update_visibility_by_resolution_info): Do not drop weak during incremental link. (function_and_variable_visibility): Fix formating. * flag-types.h (lto_linker_output): Declare. * common.opt 9flag_incremental_link): New flag. * lto-lang.c (lto_post_options): Process flag_lto_linker_output. * lang.opt (lto_linker_output): New enum. (flinker_output): New flag. Modified: trunk/gcc/ChangeLog trunk/gcc/common.opt trunk/gcc/flag-types.h trunk/gcc/ipa-visibility.c trunk/gcc/lto/ChangeLog trunk/gcc/lto/lang.opt trunk/gcc/lto/lto-lang.c trunk/lto-plugin/ChangeLog trunk/lto-plugin/lto-plugin.c
*** Bug 64860 has been marked as a duplicate of this bug. ***
Fixed on trunk so far
GCC 5.3 is being released, adjusting target milestone.
Author: belagod Date: Wed Dec 16 22:33:51 2015 New Revision: 231724 URL: https://gcc.gnu.org/viewcvs?rev=231724&root=gcc&view=rev Log: Backport from Mainline PR lto/67548 * lto-plugin.c (linker_output, linker_output_set): New statics. (all_symbols_read_handler): Add -flinker-output option. (onload): Record linker_output info. * ipa-visibility.c (cgraph_externally_visible_p, varpool_node::externally_visible_p): When doing incremental linking, hidden symbols may be still used later. (update_visibility_by_resolution_info): Do not drop weak during incremental link. (function_and_variable_visibility): Fix formating. * flag-types.h (lto_linker_output): Declare. * common.opt 9flag_incremental_link): New flag. * lto-lang.c (lto_post_options): Process flag_lto_linker_output. * lang.opt (lto_linker_output): New enum. (flinker_output): New flag. Added: branches/ARM/embedded-5-branch/gcc/lto/ChangeLog.arm branches/ARM/embedded-5-branch/lto-plugin/ChangeLog.arm Modified: branches/ARM/embedded-5-branch/gcc/ChangeLog.arm branches/ARM/embedded-5-branch/gcc/common.opt branches/ARM/embedded-5-branch/gcc/flag-types.h branches/ARM/embedded-5-branch/gcc/ipa-visibility.c branches/ARM/embedded-5-branch/gcc/lto/lang.opt branches/ARM/embedded-5-branch/gcc/lto/lto-lang.c branches/ARM/embedded-5-branch/lto-plugin/lto-plugin.c
GCC 5.4 is being released, adjusting target milestone.
GCC 5 branch has been closed, should be fixed in GCC 6 and later.
The master branch has been updated by Maciej W. Rozycki <macro@gcc.gnu.org>: https://gcc.gnu.org/g:76a553587f3181605c57801c37b0d3e94ce3aca5 commit r11-5795-g76a553587f3181605c57801c37b0d3e94ce3aca5 Author: Maciej W. Rozycki <macro@linux-mips.org> Date: Sat Dec 5 18:26:27 2020 +0000 VAX: Fix the LTO compiler downgrading code to non-PIC model Fix a testsuite failure: /tmp/ccL65Mmt.s: Assembler messages: /tmp/ccL65Mmt.s:36: Warning: Symbol n used as immediate operand in PIC mode. FAIL: gcc.dg/lto/pr55660 c_lto_pr55660_0.o-c_lto_pr55660_1.o link, -O0 -flto -flto-partition=none -fuse-linker-plugin where non-PIC code is substituted by the LTO compiler at the link stage for what used to be PIC code in the original compilation. This happens because in the de-facto VAX ELF psABI we rely on code being PIC for GOT support in dynamic executables and arrange that by having `-fPIC' passed to the compiler by default by means of a specs recipe. That is however canceled where the LTO wrapper is used, by an internal arrangement in the LTO compiler that clears the PIC flag whenever the `-flinker-output=exec' option has been used. This has been deliberately introduced with commit 1ff9ed6fb282 ("re PR lto/67548 (LTO drops weak binding with "ld -r")")[1]: "In the log of PR67548 HJ actually pointed out that we do have API at linker plugin side which says what type of output is done. This is cool because we can also use it to drop -fpic when building static binary. This is common in Firefox, where some objects are built with -fpic and linked to both binaries and libraries." with this code: case LTO_LINKER_OUTPUT_EXEC: /* Normal executable */ flag_pic = 0; flag_pie = 0; flag_shlib = 0; break; Consequently code like: .L6: addl3 -8(%fp),$n,%r0 pushl %r0 calls $1,foo addl2 %r0,-12(%fp) incl -8(%fp) .L5: is produced by the LTO compiler, where a reference to `n' is used that is invalid in PIC code, because it uses the immediate addressing mode, denoted by the `$' prefix. For that not to happen we must never pass `-flinker-output=exec' to the LTO compiler unless non-PIC code has been explicitly requested. Using `-flinker-output=dyn' except for relocatable output would seem the simplest approach, as it does not fiddle with any of the internal code model settings beyond what the command-line options have arranged and therefore lets them remain the same as with the original compilation, but it breaks as well causing PR lto/69866 to retrigger, as that code seems sensitive to `flag_shlib': lto1: internal compiler error: in add_symbol_to_partition_1, at lto/lto-partition.c:152 0x105be1cb add_symbol_to_partition_1 .../gcc/lto/lto-partition.c:152 0x105be443 add_symbol_to_partition_1 .../gcc/lto/lto-partition.c:194 0x105be80f add_symbol_to_partition .../gcc/lto/lto-partition.c:270 0x105bee6f add_sorted_nodes .../gcc/lto/lto-partition.c:395 0x105c0903 lto_balanced_map(int, int) .../gcc/lto/lto-partition.c:815 0x105aa91f do_whole_program_analysis .../gcc/lto/lto.c:499 0x105aac97 lto_main() .../gcc/lto/lto.c:637 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. lto-wrapper: fatal error: .../gcc/xgcc returned 1 exit status compilation terminated. .../usr/bin/vax-netbsdelf-ld: error: lto-wrapper failed collect2: error: ld returned 1 exit status compiler exited with status 1 FAIL: gcc.dg/lto/pr69866 c_lto_pr69866_0.o-c_lto_pr69866_1.o link, -O0 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) Substitute `-flinker-output=pie' for `-flinker-output=exec' in the specs then unless `-no-pie' has also been used, preserving the original intent of emitting PIC code by default for executables while keeping the linker arrangement unchanged. The LTO compiler uses the `cc1' spec, so keep `cc1plus' unmodified. This makes code like: .L6: movab n,%r0 addl2 -8(%fp),%r0 pushl %r0 calls $1,foo addl2 %r0,-12(%fp) incl -8(%fp) .L5: be produced instead corresponding to the fragment quoted above, which is valid PIC code as it uses the PC-relative addressing mode denoted by the absence of a prefix to `n' (which can be redirected to GOT as required, by changing the addressing mode to PC-relative indirect in the operand specifier). Ideally we would instead default to the PIE model for executables, but that triggers a BFD bug where for a change the LTO wrapper is not used: .../usr/bin/vax-netbsdelf-ld: /tmp/ccV2sWQt.ltrans0.ltrans.o: warning: GOT addend of 3 to `n' does not match previous GOT addend of 0 FAIL: gcc.dg/lto/pr55660 c_lto_pr55660_0.o-c_lto_pr55660_1.o link, -O2 -flto -flto-partition=1to1 -fno-use-linker-plugin which is due to assembly code like: main: .word 0 subl2 $4,%sp movab n,%r0 movab n+3,%r2 clrl %r3 movb $98,%r1 .L4: and consequently object code like: 00000000 <main>: 0: 00 00 .word 0x0000 # Entry mask: < > 2: c2 04 5e subl2 $0x4,sp 5: 9e ef 00 00 movab b <main+0xb>,r0 9: 00 00 50 7: R_VAX_GOT32 n c: 9e ef 00 00 movab 12 <main+0x12>,r2 10: 00 00 52 e: R_VAX_GOT32 n+0x3 13: d4 53 clrf r3 15: 90 8f 62 51 movb $0x62,r1 being produced. This would be problematic for external `n', because we do not support multiple GOT entries for the same symbol referred to with different offsets in a single link unit. In this case however the LTO compiler correctly observes that `n' is defined by the executable and not preemptible and therefore no GOT entry will be made for it. Indeed a valid executable is produced: 00010548 <main>: 10548: 00 00 .word 0x0000 # Entry mask: < > 1054a: c2 04 5e subl2 $0x4,sp 1054d: 9e ef dd 14 movab 11a30 <n>,r0 10551: 00 00 50 10554: 9e ef d9 14 movab 11a33 <__bss_start>,r2 10558: 00 00 52 1055b: d4 53 clrf r3 1055d: 90 8f 62 51 movb $0x62,r1 despite the warning, but it would be rather bad to have users annoyed with this message from BFD, however harmless, especially as it triggers outside LTO compilations as well. Therefore this change is the best we can do until binutils have been fixed. References: [1] Jan Hubicka, "Getting LTO incremental linking work", <https://gcc.gnu.org/ml/gcc-patches/2015-11/msg02986.html> gcc/ * config/vax/elf.h (VAX_CC1_SPEC, VAX_CC1PLUS_SPEC): New macros. * config/vax/netbsd-elf.h (CC1_SPEC): Use VAX_CC1_SPEC rather than VAX_CC1_AND_CC1PLUS_SPEC. (CC1PLUS_SPEC): Use VAX_CC1PLUS_SPEC rather than VAX_CC1_AND_CC1PLUS_SPEC.