[ELF] Implement GOTPCREL for defined atoms.
authorMichael J. Spencer <bigcheesegs@gmail.com>
Tue, 5 Feb 2013 19:14:28 +0000 (19:14 +0000)
committerMichael J. Spencer <bigcheesegs@gmail.com>
Tue, 5 Feb 2013 19:14:28 +0000 (19:14 +0000)
llvm-svn: 174426

lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
lld/test/elf/Inputs/gotpcrel.S [moved from lld/test/elf/Inputs/undef-gotpcrel.S with 85% similarity]
lld/test/elf/Inputs/gotpcrel.x86-64 [new file with mode: 0644]
lld/test/elf/Inputs/undef-gotpcrel.x86-64 [deleted file]
lld/test/elf/gotpcrel.test [moved from lld/test/elf/undef-gotpcrel.test with 54% similarity]

index 95011d6..2f53709 100644 (file)
@@ -152,11 +152,8 @@ class GOTPLTPass LLVM_FINAL : public Pass {
       if (da)
         handleGOTTPOFF(ref, *da);
       break;
-    case R_X86_64_GOTPCREL: // GOTPCREL to an undefined weak symbol.
-      // Always convert it to a non-got reference.
-      const_cast<Reference &>(ref).setKind(R_X86_64_PC32);
-      if (isa<const UndefinedAtom>(ref.target()))
-        handleUndefGOTPCREL(ref);
+    case R_X86_64_GOTPCREL:
+      handleGOTPCREL(ref);
       break;
     }
   }
@@ -225,10 +222,29 @@ class GOTPLTPass LLVM_FINAL : public Pass {
     return _null;
   }
 
+  const GOTAtom *getGOT(const DefinedAtom &da) {
+    auto got = _gotMap.find(&da);
+    if (got == _gotMap.end()) {
+      auto g = new (_file._alloc) GOTAtom(_file, ".got");
+      g->addReference(R_X86_64_64, 0, &da, 0);
+#ifndef NDEBUG
+      g->_name = "__got_";
+      g->_name += da.name();
+#endif
+      _gotMap[&da] = g;
+      return g;
+    }
+    return got->second;
+  }
+
   /// \brief Handle a GOTPCREL relocation to an undefined weak atom by using a
   /// null GOT entry.
-  void handleUndefGOTPCREL(const Reference &ref) {
-    const_cast<Reference &>(ref).setTarget(getNullGOT());
+  void handleGOTPCREL(const Reference &ref) {
+    const_cast<Reference &>(ref).setKind(R_X86_64_PC32);
+    if (isa<UndefinedAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getNullGOT());
+    else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getGOT(*da));
   }
 
 public:
similarity index 85%
rename from lld/test/elf/Inputs/undef-gotpcrel.S
rename to lld/test/elf/Inputs/gotpcrel.S
index fd7516e..300675f 100644 (file)
@@ -4,6 +4,7 @@
         .type   main,@function
 main:                                   # @main
         movq  blah@GOTPCREL(%rip), %rax
+        movq  main@GOTPCREL(%rip), %rax
         ret
 
         .weak blah
diff --git a/lld/test/elf/Inputs/gotpcrel.x86-64 b/lld/test/elf/Inputs/gotpcrel.x86-64
new file mode 100644 (file)
index 0000000..f9c61d0
Binary files /dev/null and b/lld/test/elf/Inputs/gotpcrel.x86-64 differ
diff --git a/lld/test/elf/Inputs/undef-gotpcrel.x86-64 b/lld/test/elf/Inputs/undef-gotpcrel.x86-64
deleted file mode 100644 (file)
index e71a9dc..0000000
Binary files a/lld/test/elf/Inputs/undef-gotpcrel.x86-64 and /dev/null differ
similarity index 54%
rename from lld/test/elf/undef-gotpcrel.test
rename to lld/test/elf/gotpcrel.test
index 88e4850..7c0f4e8 100644 (file)
@@ -1,10 +1,17 @@
 RUN: lld -core -target x86_64-linux -output=- -entry=main \
-RUN:   %p/Inputs/undef-gotpcrel.x86-64 -emit-yaml -noinhibit-exec \
+RUN:   %p/Inputs/gotpcrel.x86-64 -emit-yaml -noinhibit-exec \
 RUN: | FileCheck %s -check-prefix=YAML
 
 YAML: name: main
 YAML: kind: R_X86_64_PC32
 YAML: target: [[NULLGOT:[a-zA-Z0-9_]+]]
+YAML: kind: R_X86_64_PC32
+YAML: target: [[MAINGOT:[a-zA-Z0-9_]+]]
 
 YAML: name: [[NULLGOT]]
 YAML: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+YAML-NOT: references:
+
+YAML: name: [[MAINGOT]]
+YAML: kind: R_X86_64_64
+YAML: target: main