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+.

Reply via email to