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

             Bug #: 13249
           Summary: gold creates incorrect RELATIVE dynamic relocation for
                    local IFUNC GOT entries
           Product: binutils
           Version: 2.23 (HEAD)
            Status: NEW
          Severity: normal
          Priority: P2
         Component: gold
        AssignedTo: i...@airs.com
        ReportedBy: ccout...@google.com
                CC: ccout...@google.com
    Classification: Unclassified


The ifuncmain7pie test fails when built with optimization turned off. It turns
out that optimization doesn't make the bug go away, it just hides it. When
compiling main() in ifuncmain7.c with optimization, the assignment p = foo()
returns a pointer to foo_ifunc() instead of the PLT stub, but the optimizer has
determined that the call (*p)() always goes to foo, so it makes the call
directly to the PLT stub, and it works:

Dump of assembler code for function main:
   0x00000000000006f0 <+0>:    push   %rbp
   0x00000000000006f1 <+1>:    push   %rbx
   0x00000000000006f2 <+2>:    sub    $0x8,%rsp
   0x00000000000006f6 <+6>:    callq  0x6e0 <get_foo>
   0x00000000000006fb <+11>:    cmp    0x18de(%rip),%rax        # 0x1fe0
   0x0000000000000702 <+18>:    mov    %rax,%rbx
   0x0000000000000705 <+21>:    jne    0x753 <main+99>
   0x0000000000000707 <+23>:    callq  0x5a0 <abort@plt+16>

The callq to abort@plt+16 jumps straight to the PLT stub. With unoptimized
code, we have this:

Dump of assembler code for function main:
   0x00000000000006f1 <+0>:    push   %rbp
   0x00000000000006f2 <+1>:    mov    %rsp,%rbp
   0x00000000000006f5 <+4>:    sub    $0x10,%rsp
   0x00000000000006f9 <+8>:    callq  0x6e4 <get_foo>
   0x00000000000006fe <+13>:    mov    %rax,-0x8(%rbp)
   0x0000000000000702 <+17>:    mov    0x18d7(%rip),%rax        # 0x1fe0
   0x0000000000000709 <+24>:    cmp    %rax,-0x8(%rbp)
   0x000000000000070d <+28>:    je     0x714 <main+35>
   0x000000000000070f <+30>:    callq  0x590 <abort@plt>
   0x0000000000000714 <+35>:    mov    -0x8(%rbp),%rax
   0x0000000000000718 <+39>:    callq  *%rax

Here, the call is jumping via the pointer returned by the call to get_foo. In
both cases, get_foo is actually returning the wrong pointer, and that's because
the RELATIVE relocation for the GOT entry at 0x1fe0 has the wrong addend:

    Offset             Info             Type               Symbol's Value 
Symbol's Name + Addend
0000000000001fe0  0000000000000008 R_X86_64_RELATIVE                           
   00000000000006c5

The initialized value of the GOT entry is 0x05a0, which is the address of the
PLT stub for the IFUNC symbol:

Hex dump of section '.got':
  0x00001fb0 90070000 00000000 a0070000 00000000 ................
  0x00001fc0 f1060000 00000000 00000000 00000000 ................
  0x00001fd0 00000000 00000000 00000000 00000000 ................
  0x00001fe0 a0050000 00000000                   ........

But once the program starts, the dynamic linker applies the dynamic relocation,
using the wrong addend, and it ends up pointing to the relocated value of
0x6c5, which is actually the entry point to the routine foo_ifunc().

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.

_______________________________________________
bug-binutils mailing list
bug-binutils@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-binutils

Reply via email to