https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63842

            Bug ID: 63842
           Summary: x86-64 large PIC model may load the GOT base into the
                    wrong register
           Product: gcc
           Version: 5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: hjl.tools at gmail dot com
                CC: ubizjak at gmail dot com
            Target: x86-64

According to x86-64 psABI, when PLT is more 2GB from GOT, linker must use
large model PLT layout:

PLT0: pushq 8(%r15)   # GOT[1]
      jmpq  *16(%r15) # GOT[2]

That is fpr large PIC mode,  if a function calls another function via PLT,
it must load GOT base into %r15 before making function call. However,
GCC generates:

[hjl@gnu-6 pr17592]$ cat foo.c
#include <stdio.h>

void
foo (void)
{
  printf ("hello\n");
}
[hjl@gnu-6 pr17592]$ make foo.s
gcc -O2  -mcmodel=large -fpic -S foo.c
[hjl@gnu-6 pr17592]$ cat foo.s
    .file    "foo.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string    "hello"
    .text
    .p2align 4,,15
    .globl    foo
    .type    foo, @function
foo:
.LFB11:
    .cfi_startproc
.L2:
    leaq    .L2(%rip), %rcx
    movabsq    $_GLOBAL_OFFSET_TABLE_-.L2, %r11
    movabsq    $.LC0@GOTOFF, %rax
    addq    %r11, %rcx
    leaq    (%rcx,%rax), %rdi
    movabsq    $puts@PLTOFF, %rax
    addq    %rcx, %rax
    jmp    *%rax
    .cfi_endproc
.LFE11:
    .size    foo, .-foo
    .ident    "GCC: (GNU) 4.8.3 20140911 (Red Hat 4.8.3-7)"
    .section    .note.GNU-stack,"",@progbits
[hjl@gnu-6 pr17592]$ 

It works fine as long as large PLT layout isn't used.  But it fails
when large PLT layout is used.  Since puts is called via PLT, GCC
must load GOT base into %r15, instead of %r11.

Reply via email to