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.