Index: ELF/Arch/X86_64.cpp =================================================================== --- ELF/Arch/X86_64.cpp +++ ELF/Arch/X86_64.cpp @@ -105,6 +105,9 @@ case R_X86_64_REX_GOTPCRELX: case R_X86_64_GOTTPOFF: return R_GOT_PC; + case R_X86_64_GOTPC32: + case R_X86_64_GOTPC64: + return R_GOTONLY_PC_FROM_END; case R_X86_64_NONE: return R_NONE; default: @@ -300,6 +303,7 @@ case R_X86_64_32S: case R_X86_64_TPOFF32: case R_X86_64_GOT32: + case R_X86_64_GOTPC32: case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: @@ -319,6 +323,7 @@ case R_X86_64_PC64: case R_X86_64_SIZE64: case R_X86_64_GOT64: + case R_X86_64_GOTPC64: write64le(Loc, Val); break; default: Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -495,11 +495,22 @@ case R_GOTONLY_PC: return InX::Got->getVA() + A - P; case R_GOTONLY_PC_FROM_END: - return InX::Got->getVA() + A - P + InX::Got->getSize(); + // We define GlobalOffsetTable when there is an undefined reference to _GLOBAL_OFFSET_TABLE_. + // However, relocations like R_X86_64_GOTPC{32,64} (special case of R_X86_64_PC{32,64}, respectively) + // implicitly reference _GLOBAL_OFFSET_TABLE_. + // ElfSym::GlobalOffsetTable is null if _GLOBAL_OFFSET_TABLE_ is not explicitly referenced. + // Use an arbitrary address in this case. + return (ElfSym::GlobalOffsetTable + ? ElfSym::GlobalOffsetTable->getVA() + : InX::Got->getVA() + InX::Got->getSize()) + + A - P; case R_GOTREL: return Sym.getVA(A) - InX::Got->getVA(); case R_GOTREL_FROM_END: - return Sym.getVA(A) - InX::Got->getVA() - InX::Got->getSize(); + // Similar to R_GOTONLY_PC_FROM_END + return Sym.getVA(A) - (ElfSym::GlobalOffsetTable + ? ElfSym::GlobalOffsetTable->getVA() + : InX::Got->getVA() + InX::Got->getSize()); case R_GOT_FROM_END: case R_RELAX_TLS_GD_TO_IE_END: return Sym.getGotOffset() + A - InX::Got->getSize(); Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -347,7 +347,7 @@ if (isRelExprOneOf(E)) return true; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -908,7 +908,8 @@ // references the _GLOBAL_OFFSET_TABLE_ and the Target defines the symbol // relative to the .got.plt section. return Entries.empty() && - !(ElfSym::GlobalOffsetTable && Target->GotBaseSymInGotPlt); + !(Target->GotBaseSymInGotPlt && + (ElfSym::GlobalOffsetTable || InX::Got->HasGotOffRel)); } static StringRef getIgotPltName() { Index: test/ELF/got-i386.s =================================================================== --- test/ELF/got-i386.s +++ test/ELF/got-i386.s @@ -4,13 +4,13 @@ // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s // REQUIRES: x86 -// CHECK: Name: .got +// CHECK: Name: .got ( // CHECK-NEXT: Type: SHT_PROGBITS // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x12000 +// CHECK-NEXT: Address: 0x13000 // CHECK-NEXT: Offset: // CHECK-NEXT: Size: 0 // CHECK-NEXT: Link: @@ -19,7 +19,7 @@ // CHECK: Symbol { // CHECK: Name: bar -// CHECK-NEXT: Value: 0x12000 +// CHECK-NEXT: Value: 0x13000 // CHECK-NEXT: Size: 10 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object @@ -28,7 +28,7 @@ // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: obj -// CHECK-NEXT: Value: 0x1200A +// CHECK-NEXT: Value: 0x1300A // CHECK-NEXT: Size: 10 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object @@ -36,14 +36,17 @@ // CHECK-NEXT: Section: .bss // CHECK-NEXT: } -// 0x12000 - 0 = addr(.got) = 0x12000 -// 0x1200A - 10 = addr(.got) = 0x12000 -// 0x1200A + 5 - 15 = addr(.got) = 0x12000 +// 0x13000 (bar) - 0x12000 (_GLOBAL_OFFSET_TABLE_) = 4096 +// 0x1300A (obj) - 0x12000 = 4106 +// 0x1300A (obj) + 5 - 0x12000 = 4111 // DISASM: Disassembly of section .text: // DISASM-NEXT: _start: -// DISASM-NEXT: 11000: c7 81 00 00 00 00 01 00 00 00 movl $1, (%ecx) -// DISASM-NEXT: 1100a: c7 81 0a 00 00 00 02 00 00 00 movl $2, 10(%ecx) -// DISASM-NEXT: 11014: c7 81 0f 00 00 00 03 00 00 00 movl $3, 15(%ecx) +// DISASM-NEXT: 11000: c7 81 00 10 00 00 01 00 00 00 movl $1, 4096(%ecx) +// DISASM-NEXT: 1100a: c7 81 0a 10 00 00 02 00 00 00 movl $2, 4106(%ecx) +// DISASM-NEXT: 11014: c7 81 0f 10 00 00 03 00 00 00 movl $3, 4111(%ecx) + +.hidden _GLOBAL_OFFSET_TABLE_ +.weak _GLOBAL_OFFSET_TABLE_ .global _start _start: Index: test/ELF/i386-gotoff-shared.s =================================================================== --- test/ELF/i386-gotoff-shared.s +++ test/ELF/i386-gotoff-shared.s @@ -4,20 +4,23 @@ // RUN: llvm-readobj -s %t.so | FileCheck %s // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s +.hidden _GLOBAL_OFFSET_TABLE_ +.weak _GLOBAL_OFFSET_TABLE_ + bar: - movl bar@GOTOFF(%ebx), %eax - mov bar@GOT, %eax + movl bar@GOTOFF(%ebx), %eax + mov bar@GOT, %eax -// CHECK: Name: .got +// CHECK: Name: .got ( // CHECK-NEXT: Type: SHT_PROGBITS // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x2050 -// CHECK-NEXT: Offset: 0x2050 +// CHECK-NEXT: Address: 0x3050 +// CHECK-NEXT: Offset: 0x3050 // CHECK-NEXT: Size: 4 -// 0x1000 - (0x2050 + 4) = -4180 +// 0x1000 (bar) - 0x2000 (_GLOBAL_OFFSET_TABLE_) = -4096 -// DISASM: 1000: {{.*}} movl -4180(%ebx), %eax +// DISASM: 1000: {{.*}} movl -4096(%ebx), %eax Index: test/ELF/i386-gotpc-dynamic.s =================================================================== --- test/ELF/i386-gotpc-dynamic.s +++ test/ELF/i386-gotpc-dynamic.s @@ -4,25 +4,16 @@ # RUN: llvm-readobj -s %t.so | FileCheck %s # RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s -# CHECK: Section { -# CHECK: Index: 7 -# CHECK-NEXT: Name: .got +# CHECK: Name: .got ( # CHECK-NEXT: Type: SHT_PROGBITS # CHECK-NEXT: Flags [ # CHECK-NEXT: SHF_ALLOC # CHECK-NEXT: SHF_WRITE # CHECK-NEXT: ] -# CHECK-NEXT: Address: 0x2030 -# CHECK-NEXT: Offset: -# CHECK-NEXT: Size: -# CHECK-NEXT: Link: -# CHECK-NEXT: Info: -# CHECK-NEXT: AddressAlignment: -# CHECK-NEXT: EntrySize: -# CHECK-NEXT: } +# CHECK-NEXT: Address: 0x3030 -## 0x1000 + 4144 = 0x2030 -# DISASM: 1000: {{.*}} movl $4144, %eax +## 0x3030 (.got) - 0x1000 = 8240 +# DISASM: 1000: {{.*}} movl $8240, %eax .section .foo,"ax",@progbits foo: Index: test/ELF/i386-gotpc.s =================================================================== --- test/ELF/i386-gotpc.s +++ test/ELF/i386-gotpc.s @@ -22,7 +22,7 @@ // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x3030 +// 0x2000 (_GLOBAL_OFFSET_TABLE_) - 0x1000 = 4096 // DISASM: Disassembly of section .text: // DISASM-NEXT: .text: -// DISASM-NEXT: 1000: {{.*}} movl $8240, %eax -// 0x3030 - 0x1000 = 0x2030 +// DISASM-NEXT: 1000: {{.*}} movl $4096, %eax Index: test/ELF/relocation-i686.s =================================================================== --- test/ELF/relocation-i686.s +++ test/ELF/relocation-i686.s @@ -1,6 +1,6 @@ // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o -// RUN: ld.lld -shared %t2.o -o %t2.so +// RUN: ld.lld -shared %t2.o -soname t2.so -o %t2.so // RUN: ld.lld --hash-style=sysv %t %t2.so -o %t2 // RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=ADDR %s // RUN: llvm-objdump -d %t2 | FileCheck %s @@ -67,7 +67,7 @@ // CHECK: Disassembly of section .R_386_GOTPC: // CHECK-NEXT: R_386_GOTPC: -// CHECK-NEXT: 11014: {{.*}} movl $8300, %eax +// CHECK-NEXT: 11014: {{.*}} movl $4076, %eax .section .dynamic_reloc, "ax",@progbits call bar Index: test/ELF/x86-64-reloc-shared.s =================================================================== --- /dev/null +++ test/ELF/x86-64-reloc-shared.s @@ -0,0 +1,17 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: ld.lld %t.o -shared -o %t.so +// RUN: llvm-objdump -d %t.so | FileCheck %s + +// 0x2000 (_GLOBAL_OFFSET_TABLE_) - (0x1000 + 7) = 4089 +// CHECK: R_X86_64_GOTPC32: +// CHECK-NEXT: 1000: {{.*}} leaq 4089(%rip), %rax +.global R_X86_64_GOTPC32 +R_X86_64_GOTPC32: + leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax + +// CHECK: R_X86_64_GOTPC64: +// CHECK-NEXT: 1007: {{.*}} movabsq $4089, %r11 +.global R_X86_64_GOTPC64 +R_X86_64_GOTPC64: + movabsq $_GLOBAL_OFFSET_TABLE_-., %r11