https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78407
Bug ID: 78407 Summary: LTO breaks separate overriding of symbol aliases Product: gcc Version: 5.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: lto Assignee: unassigned at gcc dot gnu.org Reporter: srk31 at srcf dot ucam.org Target Milestone: --- Created attachment 40073 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40073&action=edit Test case tarball I have a library which tests, in a constructor function, whether another library is overriding one of its symbols. If so, it skips initialization (since the other library is taking care of it). This is necessary because constructors cannot meaningfully be overridden. To do this test, I create a hidden alias of the overridable symbol. This will always point to our copy, even if the global alias gets overridden. int foo = 0; extern int our_foo __attribute__((visibility("hidden"),alias("foo"))); static void (__attribute__((constructor)) init)(void) { if (&our_foo != &foo) { /* skip init */ } else { /* do init */ } } Building this library with LTO works fine on gcc 4.9.3 and earlier. On 5.x and 6.x the address comparison gets wrongly optimised away (tested on 5.2.1 and 6.2.0). In 4.9.x I get: 00000000000006c0 <init>: 6c0: 55 push %rbp 6c1: 48 89 e5 mov %rsp,%rbp 6c4: 48 8d 05 5e 09 20 00 lea 0x20095e(%rip),%rax 6cb: 48 8b 15 06 09 20 00 mov 0x200906(%rip),%rdx 6d2: 48 39 d0 cmp %rdx,%rax 6d5: 74 1a je 6f1 <init+0x31> ... i.e. a cmp instruction, whereas with 5.2.1 there is none. 00000000000006b0 <init>: 6b0: 55 push %rbp 6b1: 48 89 e5 mov %rsp,%rbp 6b4: 48 8d 35 f5 ff ff ff lea -0xb(%rip),%rsi # 6b0 <init> 6bb: 48 8d 3d 17 00 00 00 lea 0x17(%rip),%rdi # 6d9 <_fini+0x9> 6c2: b8 00 00 00 00 mov $0x0,%eax 6c7: e8 c4 fe ff ff callq 590 <printf@plt@@Base> 6cc: 5d pop %rbp 6cd: c3 retq Unless I'm mistaken: for any two ELF symbol aliases, if at least one has global visibility, LTO cannot assume they will remain aliased at run time. Tarball attached. On doing "make run", "lib1" should only claim to initialize itself once, but it happens twice on 5.x+.