[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