[lld] r321400 - [ELF] - Allow using PLT relocations when "-z notext" is given.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 23 01:00:37 PST 2017


Author: grimar
Date: Sat Dec 23 01:00:37 2017
New Revision: 321400

URL: http://llvm.org/viewvc/llvm-project?rev=321400&view=rev
Log:
[ELF] - Allow using PLT relocations when "-z notext" is given.

This is part of PR35720.

Currently LLD allows dynamic relocations against text when -z notext is given.
Though for non-PIC relocations like R_X86_64_PC32 that does not work,
we produce "relocation R_X86_64_PC32 cannot be used against shared object;"
error because they may overflow in runtime.

Solution implemented is to use PLT for them.

Differential revision: https://reviews.llvm.org/D41541

Added:
    lld/trunk/test/ELF/Inputs/znotext-plt-relocations.s
    lld/trunk/test/ELF/znotext-plt-relocations.s
Modified:
    lld/trunk/ELF/Relocations.cpp

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=321400&r1=321399&r2=321400&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Sat Dec 23 01:00:37 2017
@@ -554,6 +554,35 @@ static void errorOrWarn(const Twine &Msg
     warn(Msg);
 }
 
+// Returns PLT relocation expression.
+//
+// This handles a non PIC program call to function in a shared library. In
+// an ideal world, we could just report an error saying the relocation can
+// overflow at runtime. In the real world with glibc, crt1.o has a
+// R_X86_64_PC32 pointing to libc.so.
+//
+// The general idea on how to handle such cases is to create a PLT entry and
+// use that as the function value.
+//
+// For the static linking part, we just return a plt expr and everything
+// else will use the the PLT entry as the address.
+//
+// The remaining problem is making sure pointer equality still works. We
+// need the help of the dynamic linker for that. We let it know that we have
+// a direct reference to a so symbol by creating an undefined symbol with a
+// non zero st_value. Seeing that, the dynamic linker resolves the symbol to
+// the value of the symbol we created. This is true even for got entries, so
+// pointer equality is maintained. To avoid an infinite loop, the only entry
+// that points to the real function is a dedicated got entry used by the
+// plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
+// R_386_JMP_SLOT, etc).
+static RelExpr getPltExpr(Symbol &Sym, RelExpr Expr, bool &IsConstant) {
+  Sym.NeedsPltAddr = true;
+  Sym.IsPreemptible = false;
+  IsConstant = true;
+  return toPlt(Expr);
+}
+
 template <class ELFT>
 static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
                           InputSectionBase &S, uint64_t RelOff,
@@ -563,10 +592,15 @@ static RelExpr adjustExpr(Symbol &Sym, R
     return Expr;
 
   // Or, if we are allowed to create dynamic relocations against
-  // read-only sections (i.e. unless "-z notext" is given),
+  // read-only sections (i.e. when "-z notext" is given),
   // we can create a dynamic relocation as we want, too.
-  if (!Config->ZText)
+  if (!Config->ZText) {
+    // We use PLT for relocations that may overflow in runtime,
+    // see comment for getPltExpr().
+    if (Sym.isFunc() && !Target->isPicRel(Type))
+      return getPltExpr(Sym, Expr, IsConstant);
     return Expr;
+  }
 
   // If a relocation can be applied at link-time, we don't need to
   // create a dynamic relocation in the first place.
@@ -617,32 +651,8 @@ static RelExpr adjustExpr(Symbol &Sym, R
     return Expr;
   }
 
-  if (Sym.isFunc()) {
-    // This handles a non PIC program call to function in a shared library. In
-    // an ideal world, we could just report an error saying the relocation can
-    // overflow at runtime. In the real world with glibc, crt1.o has a
-    // R_X86_64_PC32 pointing to libc.so.
-    //
-    // The general idea on how to handle such cases is to create a PLT entry and
-    // use that as the function value.
-    //
-    // For the static linking part, we just return a plt expr and everything
-    // else will use the the PLT entry as the address.
-    //
-    // The remaining problem is making sure pointer equality still works. We
-    // need the help of the dynamic linker for that. We let it know that we have
-    // a direct reference to a so symbol by creating an undefined symbol with a
-    // non zero st_value. Seeing that, the dynamic linker resolves the symbol to
-    // the value of the symbol we created. This is true even for got entries, so
-    // pointer equality is maintained. To avoid an infinite loop, the only entry
-    // that points to the real function is a dedicated got entry used by the
-    // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
-    // R_386_JMP_SLOT, etc).
-    Sym.NeedsPltAddr = true;
-    Sym.IsPreemptible = false;
-    IsConstant = true;
-    return toPlt(Expr);
-  }
+  if (Sym.isFunc())
+    return getPltExpr(Sym, Expr, IsConstant);
 
   errorOrWarn("symbol '" + toString(Sym) + "' defined in " +
               toString(Sym.File) + " has no type");

Added: lld/trunk/test/ELF/Inputs/znotext-plt-relocations.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/znotext-plt-relocations.s?rev=321400&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/znotext-plt-relocations.s (added)
+++ lld/trunk/test/ELF/Inputs/znotext-plt-relocations.s Sat Dec 23 01:00:37 2017
@@ -0,0 +1,10 @@
+.text
+.global atexit
+.type atexit, at function
+atexit:
+ nop
+
+.global foo
+.type foo, at function
+foo:
+ nop

Added: lld/trunk/test/ELF/znotext-plt-relocations.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/znotext-plt-relocations.s?rev=321400&view=auto
==============================================================================
--- lld/trunk/test/ELF/znotext-plt-relocations.s (added)
+++ lld/trunk/test/ELF/znotext-plt-relocations.s Sat Dec 23 01:00:37 2017
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/znotext-plt-relocations.s -o %t2.o
+# RUN: ld.lld %t2.o -o %t2.so -shared
+# RUN: ld.lld -z notext %t.o %t2.so -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s
+
+# CHECK:      Relocations [
+# CHECK-NEXT:   Section {{.*}} .rela.dyn {
+# CHECK-NEXT:     R_X86_64_64 foo 0x0
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Section {{.*}} .rela.plt {
+# CHECK-NEXT:     R_X86_64_JUMP_SLOT atexit 0x0
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+
+.text
+_start:
+callq atexit
+.quad foo




More information about the llvm-commits mailing list