[lld] 7083363 - [lld-macho] Implement GOT_LOAD relaxation

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 17:44:45 PDT 2020


Author: Jez Ng
Date: 2020-08-27T17:44:17-07:00
New Revision: 7083363c05abe4afd8af8d6bacdd79c9cf10585b

URL: https://github.com/llvm/llvm-project/commit/7083363c05abe4afd8af8d6bacdd79c9cf10585b
DIFF: https://github.com/llvm/llvm-project/commit/7083363c05abe4afd8af8d6bacdd79c9cf10585b.diff

LOG: [lld-macho] Implement GOT_LOAD relaxation

We can have GOT_LOAD relocations that reference `__dso_handle`.
However, our binding opcode encoder doesn't support binding to the DSOHandle
symbol. Instead of adding support for that, I decided it would be cleaner to
implement GOT_LOAD relaxation since `__dso_handle`'s location is always
statically known.

Reviewed By: #lld-macho, smeenai

Differential Revision: https://reviews.llvm.org/D86641

Added: 
    lld/test/MachO/x86-64-reloc-got-load.s

Modified: 
    lld/MachO/Arch/X86_64.cpp
    lld/test/MachO/local-got.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp
index 354a47bf0465..4fc20e377f1f 100644
--- a/lld/MachO/Arch/X86_64.cpp
+++ b/lld/MachO/Arch/X86_64.cpp
@@ -220,8 +220,15 @@ void X86_64::writeStubHelperEntry(uint8_t *buf, const DylibSymbol &sym,
 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<DylibSymbol>(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 @@ void X86_64::prepareSymbolRelocation(lld::macho::Symbol *sym,
 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
index b95c44f6013d..6acd1ca4a72d 100644
--- a/lld/test/MachO/local-got.s
+++ b/lld/test/MachO/local-got.s
@@ -37,13 +37,16 @@ _main:
 
   movl $0x2000004, %eax # write() syscall
   mov $1, %rdi # stdout
-  movq _hello_world at GOTPCREL(%rip), %rsi
+## We use pushq/popq here instead of movq in order to avoid relaxation.
+  pushq _hello_world at GOTPCREL(%rip)
+  popq %rsi
   mov $13, %rdx # length of str
   syscall
 
   movl $0x2000004, %eax # write() syscall
   mov $1, %rdi # stdout
-  movq _goodbye_world at GOTPCREL(%rip), %rsi
+  pushq _goodbye_world at 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
index 000000000000..158936d0b360
--- /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 at GOTPCREL(%rip), %rax
+  ret
+
+_foo:
+  .space 0


        


More information about the llvm-commits mailing list