Index: ELF/Arch/X86_64.cpp =================================================================== --- ELF/Arch/X86_64.cpp +++ ELF/Arch/X86_64.cpp @@ -105,6 +105,11 @@ 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_GOTOFF64: + return R_GOTREL_FROM_END; case R_X86_64_NONE: return R_NONE; default: @@ -300,6 +305,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 +325,7 @@ case R_X86_64_PC64: case R_X86_64_SIZE64: case R_X86_64_GOT64: + case R_X86_64_GOTOFF64: write64le(Loc, Val); break; default: Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -479,6 +479,7 @@ static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P, const Symbol &Sym, RelExpr Expr) { + const Defined* GOTBase = ElfSym::GlobalOffsetTable; switch (Expr) { case R_INVALID: return 0; @@ -495,11 +496,11 @@ 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(); + return (GOTBase ? GOTBase->getVA() : 0) + 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(); + return Sym.getVA(A) - (GOTBase ? GOTBase->getVA() : 0); 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,9 +347,9 @@ if (isRelExprOneOf(E)) + R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_GOTREL_FROM_END, + R_PLT_PC, R_TLSGD_PC, R_TLSGD, R_PPC_CALL_PLT, + R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E)) return true; // These never do, except if the entire file is position dependent or if 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,46 +4,33 @@ // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s // REQUIRES: x86 -// CHECK: Name: .got -// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK: Name: .got ( +// CHECK: 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: -// CHECK-NEXT: Info: -// CHECK-NEXT: AddressAlignment: // CHECK: Symbol { -// CHECK: Name: bar -// CHECK-NEXT: Value: 0x12000 -// CHECK-NEXT: Size: 10 -// CHECK-NEXT: Binding: Global -// CHECK-NEXT: Type: Object -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: .bss -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { +// CHECK: Name: bar ( +// CHECK-NEXT: Value: 0x13000 + +// CHECK: Symbol { // CHECK-NEXT: Name: obj -// CHECK-NEXT: Value: 0x1200A -// CHECK-NEXT: Size: 10 -// CHECK-NEXT: Binding: Global -// CHECK-NEXT: Type: Object -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: .bss -// CHECK-NEXT: } +// CHECK-NEXT: Value: 0x1300A -// 0x12000 - 0 = addr(.got) = 0x12000 -// 0x1200A - 10 = addr(.got) = 0x12000 -// 0x1200A + 5 - 15 = addr(.got) = 0x12000 +// 0x13000 (bar) - 0x12000 (_GLOBAL_OFFSET_TABLE_) = 4096 // 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 +// 0x2000 (_GLOBAL_OFFSET_TABLE_) - 0x1000 = -4096 -// DISASM: 1000: {{.*}} movl -4180(%ebx), %eax +// DISASM: 1000: {{.*}} movl -4096(%ebx), %eax Index: test/ELF/x86_64/relocation/shared.s =================================================================== --- /dev/null +++ test/ELF/x86_64/relocation/shared.s @@ -0,0 +1,18 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: ld.lld %t.o -shared -soname t -o %t.so +// RUN: llvm-objdump -d %t.so | FileCheck %s + +// 0x3000 (.dynamic) - 0x2000 (.got.plt) = 4096 +// CHECK: R_X86_64_GOTOFF64: +// CHECK-NEXT: 1000:{{.*}}movabsq $4096, %rax +.global R_X86_64_GOTOFF64 +R_X86_64_GOTOFF64: + movabsq $_DYNAMIC@GOTOFF, %rax + +// 0x100a + 7 (instruction length) + 4079 = 0x2000 (.got.plt) +// CHECK: R_X86_64_GOTPC32: +// CHECK-NEXT: 100a:{{.*}}leaq 4079(%rip), %rax +.global R_X86_64_GOTPC32 +R_X86_64_GOTPC32: + leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax