[lld] r343628 - Introduce a flag to warn when ifunc symbols are used with text relocations.

Ali Tamur via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 2 13:30:22 PDT 2018


Author: tamur
Date: Tue Oct  2 13:30:22 2018
New Revision: 343628

URL: http://llvm.org/viewvc/llvm-project?rev=343628&view=rev
Log:
Introduce a flag to warn when ifunc symbols are used with text relocations.

Summary:
This patch adds a new flag, --warn-ifunc-textrel, to work around a glibc bug. When a code with ifunc symbols is used to produce an object file with text relocations, lld always succeeds. However, if that object file is linked using an old version of glibc, the resultant binary just crashes with segmentation fault when it is run (The bug is going to be corrected as of glibc 2.19).

Since there is no way to tell beforehand what library the object file will be linked against in the future, there does not seem to be a fool-proof way for lld to give an error only in cases where the binary will crash. So, with this change (dated 2018-09-25), lld starts to give a warning, contingent on a new command line flag that does not have a gnu counter part. The default value for --warn-ifunc-textrel is false, so lld behaviour will not change unless the user explicitly asks lld to give a warning. Users that link with a glibc library with version 2.19 or newer, or does not use ifunc symbols, or does not generate object files with text relocations do not need to take any action. Other users may consider to start passing warn-ifunc-textrel to lld to get early warnings.

Reviewers: ruiu, espindola

Reviewed By: ruiu

Subscribers: grimar, MaskRay, markj, emaste, arichardson, llvm-commits

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

Added:
    lld/trunk/test/ELF/textrel.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/docs/ld.lld.1

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=343628&r1=343627&r2=343628&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Tue Oct  2 13:30:22 2018
@@ -176,6 +176,7 @@ struct Configuration {
   bool UseAndroidRelrTags = false;
   bool WarnBackrefs;
   bool WarnCommon;
+  bool WarnIfuncTextrel;
   bool WarnMissingEntry;
   bool WarnSymbolOrdering;
   bool WriteAddends;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=343628&r1=343627&r2=343628&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue Oct  2 13:30:22 2018
@@ -857,6 +857,8 @@ void LinkerDriver::readConfigs(opt::Inpu
   Config->WarnBackrefs =
       Args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false);
   Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
+  Config->WarnIfuncTextrel =
+      Args.hasFlag(OPT_warn_ifunc_textrel, OPT_no_warn_ifunc_textrel, false);
   Config->WarnSymbolOrdering =
       Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
   Config->ZCombreloc = getZFlag(Args, "combreloc", "nocombreloc", true);

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=343628&r1=343627&r2=343628&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Tue Oct  2 13:30:22 2018
@@ -352,6 +352,10 @@ defm warn_common: B<"warn-common",
     "Warn about duplicate common symbols",
     "Do not warn about duplicate common symbols (default)">;
 
+defm warn_ifunc_textrel: B<"warn-ifunc-textrel",
+    "Warn about using ifunc symbols with text relocations",
+    "Do not warn about using ifunc symbols with text relocations (default)">;
+
 defm warn_symbol_ordering: B<"warn-symbol-ordering",
     "Warn about problems with the symbol ordering file (default)",
     "Do not warn about problems with the symbol ordering file">;

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=343628&r1=343627&r2=343628&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Tue Oct  2 13:30:22 2018
@@ -50,6 +50,7 @@
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "Thunks.h"
+#include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Memory.h"
 #include "lld/Common/Strings.h"
 #include "llvm/ADT/SmallSet.h"
@@ -979,12 +980,22 @@ static void scanReloc(InputSectionBase &
   // all dynamic symbols that can be resolved within the executable will
   // actually be resolved that way at runtime, because the main exectuable
   // is always at the beginning of a search list. We can leverage that fact.
-  if (Sym.isGnuIFunc())
+  if (Sym.isGnuIFunc()) {
+    if (!Config->ZText && Config->WarnIfuncTextrel) {
+      warn("using ifunc symbols when text relocations are allowed may produce "
+           "a binary that will segfault, if the object file is linked with "
+           "old version of glibc (glibc 2.28 and earlier). If this applies to "
+           "you, consider recompiling the object files without -fPIC and "
+           "without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to "
+           "turn off this warning." +
+           getLocation(Sec, Sym, Offset));
+    }
     Expr = toPlt(Expr);
-  else if (!Sym.IsPreemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym))
+  } else if (!Sym.IsPreemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym)) {
     Expr = Target->adjustRelaxExpr(Type, RelocatedAddr, Expr);
-  else if (!Sym.IsPreemptible)
+  } else if (!Sym.IsPreemptible) {
     Expr = fromPlt(Expr);
+  }
 
   // This relocation does not require got entry, but it is relative to got and
   // needs it to be created. Here we request for that.

Modified: lld/trunk/docs/ld.lld.1
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/ld.lld.1?rev=343628&r1=343627&r2=343628&view=diff
==============================================================================
--- lld/trunk/docs/ld.lld.1 (original)
+++ lld/trunk/docs/ld.lld.1 Tue Oct  2 13:30:22 2018
@@ -446,6 +446,17 @@ This can be used to ensure linker invoca
 traditional Unix-like linkers.
 .It Fl -warn-common
 Warn about duplicate common symbols.
+.It Fl -warn-ifunc-textrel
+Warn about using ifunc symbols in conjunction with text relocations.
+Older versions of glibc library (2.28 and earlier) has a bug that causes
+the segment that includes ifunc symbols to be marked as not executable when
+they are relocated. As a result, although the program compiles and links
+successfully, it gives segmentation fault when the instruction pointer reaches
+an ifunc symbol. Use -warn-ifunc-textrel to let lld give a warning, if the
+code may include ifunc symbols, may do text relocations and be linked with
+an older glibc version. Otherwise, there is no need to use it, as the default
+value does not give a warning. This flag has been introduced in late 2018,
+has no counter part in ld and gold linkers, and may be removed in the future.
 .It Fl -warn-unresolved-symbols
 Report unresolved symbols as warnings.
 .It Fl -whole-archive

Added: lld/trunk/test/ELF/textrel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/textrel.s?rev=343628&view=auto
==============================================================================
--- lld/trunk/test/ELF/textrel.s (added)
+++ lld/trunk/test/ELF/textrel.s Tue Oct  2 13:30:22 2018
@@ -0,0 +1,40 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnu %s -o %t.o
+
+# Without --warn-text-ifunc, lld should run fine:
+# RUN: ld.lld -z notext %t.o -o %t2
+
+# With --warn-text-ifunc, lld should run with warnings:
+# RUN: ld.lld --warn-ifunc-textrel -z notext %t.o -o /dev/null 2>&1 | FileCheck %s
+# CHECK: using ifunc symbols when text relocations are allowed may produce
+# CHECK-SAME: a binary that will segfault, if the object file is linked with
+# CHECK-SAME: old version of glibc (glibc 2.28 and earlier). If this applies to
+# CHECK-SAME: you, consider recompiling the object files without -fPIC and
+# CHECK-SAME: without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to
+# CHECK-SAME: turn off this warning.
+# CHECK: >>> defined in {{.*}}
+# CHECK: >>> referenced by {{.*}}:(.text+0x8)
+
+# Without text relocations, lld should run fine:
+# RUN: ld.lld --fatal-warnings %t.o -o /dev/null
+
+.text
+.globl a_func_impl
+a_func_impl:
+  nop
+
+.globl selector
+.type selector, at function
+selector:
+  movl $a_func_impl, %eax
+  retq
+
+.globl a_func
+.type a_func, at gnu_indirect_function
+.set a_func, selector
+
+.globl _start
+.type _start, at function
+main:
+  callq a_func
+  retq




More information about the llvm-commits mailing list