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,8 @@ case R_X86_64_PC64: case R_X86_64_SIZE64: case R_X86_64_GOT64: + case R_X86_64_GOTOFF64: + case R_X86_64_GOTPC64: 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,17 @@ 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(); + // FIXME If GlobalOffsetTable is null, use an arbitrary address. + // If we scanned relocations earlier, GlobalOffsetTable could't be null. + return (GOTBase ? GOTBase->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(); + // FIXME Similar to R_GOTONLY_PC_FROM_END + return Sym.getVA(A) - (GOTBase ? GOTBase->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,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/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/relocation/shared.s =================================================================== --- /dev/null +++ test/ELF/x86_64/relocation/shared.s @@ -0,0 +1,24 @@ +// 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 + +// 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 + +// 0x2000 (_GLOBAL_OFFSET_TABLE_) - (0x100a + 7) = 4079 +// 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 + +// CHECK: R_X86_64_GOTPC64: +// CHECK-NEXT: 1011: {{.*}} movabsq $4079, %r11 +.global R_X86_64_GOTPC64 +R_X86_64_GOTPC64: + movabsq $_GLOBAL_OFFSET_TABLE_-., %r11