diff --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp --- a/lld/MachO/Arch/X86_64.cpp +++ b/lld/MachO/Arch/X86_64.cpp @@ -220,8 +220,15 @@ void X86_64::prepareSymbolRelocation(lld::macho::Symbol *sym, const InputSection *isec, const Reloc &r) { switch (r.type) { - case X86_64_RELOC_GOT_LOAD: - // TODO: implement mov -> lea relaxation for non-dynamic symbols + case X86_64_RELOC_GOT_LOAD: { + if (sym->isWeakDef() || isa(sym)) + in.got->addEntry(sym); + + if (sym->isTlv()) + error("found GOT relocation referencing thread-local variable in " + + toString(isec)); + break; + } case X86_64_RELOC_GOT: { in.got->addEntry(sym); @@ -288,7 +295,15 @@ uint64_t X86_64::resolveSymbolVA(uint8_t *buf, const lld::macho::Symbol &sym, uint8_t type) const { switch (type) { - case X86_64_RELOC_GOT_LOAD: + case X86_64_RELOC_GOT_LOAD: { + if (!sym.isInGot()) { + if (buf[-2] != 0x8b) + error("X86_64_RELOC_GOT_LOAD must be used with movq instructions"); + buf[-2] = 0x8d; + return sym.getVA(); + } + LLVM_FALLTHROUGH; + } case X86_64_RELOC_GOT: return in.got->addr + sym.gotIndex * WordSize; case X86_64_RELOC_BRANCH: { diff --git a/lld/test/MachO/local-got.s b/lld/test/MachO/local-got.s --- a/lld/test/MachO/local-got.s +++ b/lld/test/MachO/local-got.s @@ -37,13 +37,16 @@ movl $0x2000004, %eax # write() syscall mov $1, %rdi # stdout - movq _hello_world@GOTPCREL(%rip), %rsi +## We use pushq/popq here instead of movq in order to avoid relaxation. + pushq _hello_world@GOTPCREL(%rip) + popq %rsi mov $13, %rdx # length of str syscall movl $0x2000004, %eax # write() syscall mov $1, %rdi # stdout - movq _goodbye_world@GOTPCREL(%rip), %rsi + pushq _goodbye_world@GOTPCREL(%rip) + popq %rsi mov $15, %rdx # length of str syscall diff --git a/lld/test/MachO/x86-64-reloc-got-load.s b/lld/test/MachO/x86-64-reloc-got-load.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/x86-64-reloc-got-load.s @@ -0,0 +1,18 @@ +# REQUIRES: x86 + +## Check that we perform relaxation for GOT_LOAD relocations to defined symbols. +## Note: GOT_LOAD relocations to dylib symbols are already tested in dylink.s. + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o +# RUN: lld -flavor darwinnew -o %t %t.o +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s +# CHECK: leaq [[#]](%rip), %rax # {{.*}} <_foo> + +.globl _main, _foo + +_main: + movq _foo@GOTPCREL(%rip), %rax + ret + +_foo: + .space 0