[lld] r369262 - [ELF] Move (copy relocation/canonical PLT) before error checking

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 19 07:30:12 PDT 2019


Author: maskray
Date: Mon Aug 19 07:30:12 2019
New Revision: 369262

URL: http://llvm.org/viewvc/llvm-project?rev=369262&view=rev
Log:
[ELF] Move (copy relocation/canonical PLT) before error checking

In processRelocAux(), we handle errors before copy relocation/canonical PLT.
This makes error checking a bit complex because we have to check for
conditions that will be allowed by copy relocation/canonical PLT.

Instead, move copy relocation/canonical PLT before error checking. This
simplifies the previous clumsy error checking code

`config->shared || (config->pie && expr == R_ABS && type != target->symbolicRel)`

to the simple `config->isPic`. Some diagnostics can be reported in
different ways. The code motion changes diagnostics for some contrived
test cases:

* copy-rel-pie-error.s -> copy-rel-pie2.s:
  It was rejected before but accepted now. ld.bfd also accepts the case.
* copy-errors.s: "cannot preempt symbol" changes to "symbol 'bar' has no type"
* got32{,x}-i386.s: the suggestion changes from "-fPIC or -Wl,-z,notext" to "-fPIE"
* x86-64-dyn-rel-error5.s: one diagnostic changes for -pie case

Reviewed By: peter.smith

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

Added:
    lld/trunk/test/ELF/copy-rel-pie2.s
Removed:
    lld/trunk/test/ELF/copy-rel-pie-error.s
Modified:
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/test/ELF/copy-errors.s
    lld/trunk/test/ELF/got32-i386.s
    lld/trunk/test/ELF/got32x-i386.s
    lld/trunk/test/ELF/x86-64-dyn-rel-error5.s

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=369262&r1=369261&r2=369262&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Mon Aug 19 07:30:12 2019
@@ -993,56 +993,29 @@ static void processRelocAux(InputSection
     }
   }
 
-  if (!canWrite && (config->isPic && !isRelExpr(expr))) {
-    error(
-        "can't create dynamic relocation " + toString(type) + " against " +
-        (sym.getName().empty() ? "local symbol" : "symbol: " + toString(sym)) +
-        " in readonly segment; recompile object files with -fPIC "
-        "or pass '-Wl,-z,notext' to allow text relocations in the output" +
-        getLocation(sec, sym, offset));
-    return;
-  }
-
-  // Copy relocations (for STT_OBJECT) and canonical PLT (for STT_FUNC) are only
-  // possible in an executable.
-  //
-  // Among R_ABS relocatoin types, symbolicRel has the same size as the word
-  // size. Others have fewer bits and may cause runtime overflow in -pie/-shared
-  // mode. Disallow them.
-  if (config->shared ||
-      (config->pie && expr == R_ABS && type != target->symbolicRel)) {
-    errorOrWarn(
-        "relocation " + toString(type) + " cannot be used against " +
-        (sym.getName().empty() ? "local symbol" : "symbol " + toString(sym)) +
-        "; recompile with -fPIC" + getLocation(sec, sym, offset));
-    return;
-  }
-
-  // If the symbol is undefined we already reported any relevant errors.
-  if (sym.isUndefined())
-    return;
-
-  if (!canDefineSymbolInExecutable(sym)) {
-    error("cannot preempt symbol: " + toString(sym) +
-          getLocation(sec, sym, offset));
-    return;
-  }
+  // When producing an executable, we can perform copy relocations (for
+  // STT_OBJECT) and canonical PLT (for STT_FUNC).
+  if (!config->shared) {
+    if (!canDefineSymbolInExecutable(sym)) {
+      errorOrWarn("cannot preempt symbol: " + toString(sym) +
+                  getLocation(sec, sym, offset));
+      return;
+    }
 
-  if (sym.isObject()) {
-    // Produce a copy relocation.
-    if (auto *ss = dyn_cast<SharedSymbol>(&sym)) {
-      if (!config->zCopyreloc)
-        error("unresolvable relocation " + toString(type) +
-              " against symbol '" + toString(*ss) +
-              "'; recompile with -fPIC or remove '-z nocopyreloc'" +
-              getLocation(sec, sym, offset));
-      addCopyRelSymbol<ELFT>(*ss);
+    if (sym.isObject()) {
+      // Produce a copy relocation.
+      if (auto *ss = dyn_cast<SharedSymbol>(&sym)) {
+        if (!config->zCopyreloc)
+          error("unresolvable relocation " + toString(type) +
+                " against symbol '" + toString(*ss) +
+                "'; recompile with -fPIC or remove '-z nocopyreloc'" +
+                getLocation(sec, sym, offset));
+        addCopyRelSymbol<ELFT>(*ss);
+      }
+      sec.relocations.push_back({expr, type, offset, addend, &sym});
+      return;
     }
-    sec.relocations.push_back({expr, type, offset, addend, &sym});
-    return;
-  }
 
-  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
@@ -1070,21 +1043,44 @@ static void processRelocAux(InputSection
     //   compiled without -fPIE/-fPIC and doesn't maintain ebx.
     // * If a library definition gets preempted to the executable, it will have
     //   the wrong ebx value.
-    if (config->pie && config->emachine == EM_386)
-      errorOrWarn("symbol '" + toString(sym) +
-                  "' cannot be preempted; recompile with -fPIE" +
-                  getLocation(sec, sym, offset));
-    if (!sym.isInPlt())
-      addPltEntry<ELFT>(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
-    if (!sym.isDefined())
-      replaceWithDefined(
-          sym, in.plt,
-          target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0);
-    sym.needsPltAddr = true;
-    sec.relocations.push_back({expr, type, offset, addend, &sym});
+    if (sym.isFunc()) {
+      if (config->pie && config->emachine == EM_386)
+        errorOrWarn("symbol '" + toString(sym) +
+                    "' cannot be preempted; recompile with -fPIE" +
+                    getLocation(sec, sym, offset));
+      if (!sym.isInPlt())
+        addPltEntry<ELFT>(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
+      if (!sym.isDefined())
+        replaceWithDefined(
+            sym, in.plt,
+            target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0);
+      sym.needsPltAddr = true;
+      sec.relocations.push_back({expr, type, offset, addend, &sym});
+      return;
+    }
+  }
+
+  if (config->isPic) {
+    if (!canWrite && !isRelExpr(expr))
+      errorOrWarn(
+          "can't create dynamic relocation " + toString(type) + " against " +
+          (sym.getName().empty() ? "local symbol"
+                                 : "symbol: " + toString(sym)) +
+          " in readonly segment; recompile object files with -fPIC "
+          "or pass '-Wl,-z,notext' to allow text relocations in the output" +
+          getLocation(sec, sym, offset));
+    else
+      errorOrWarn(
+          "relocation " + toString(type) + " cannot be used against " +
+          (sym.getName().empty() ? "local symbol" : "symbol " + toString(sym)) +
+          "; recompile with -fPIC" + getLocation(sec, sym, offset));
     return;
   }
 
+  // If the symbol is undefined we already reported any relevant errors.
+  if (sym.isUndefined())
+    return;
+
   errorOrWarn("symbol '" + toString(sym) + "' has no type" +
               getLocation(sec, sym, offset));
 }

Modified: lld/trunk/test/ELF/copy-errors.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/copy-errors.s?rev=369262&r1=369261&r2=369262&view=diff
==============================================================================
--- lld/trunk/test/ELF/copy-errors.s (original)
+++ lld/trunk/test/ELF/copy-errors.s Mon Aug 19 07:30:12 2019
@@ -4,7 +4,7 @@
 // RUN: ld.lld %t2.o -o %t2.so -shared
 // RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s
 
-// CHECK: cannot preempt symbol: bar
+// CHECK: error: cannot preempt symbol: bar
 // CHECK: >>> defined in {{.*}}.so
 // CHECK: >>> referenced by {{.*}}.o:(.text+0x1)
 
@@ -12,7 +12,10 @@
 // CHECK-NEXT: >>> defined in {{.*}}.so
 // CHECK-NEXT: >>> referenced by {{.*}}.o:(.text+0x6)
 
-// RUN: not ld.lld --noinhibit-exec %t.o %t2.so -o %t 2>&1 | FileCheck %s --check-prefix=NOINHIBIT
+// RUN: ld.lld --noinhibit-exec %t.o %t2.so -o %t 2>&1 | FileCheck %s --check-prefix=NOINHIBIT
+// NOINHIBIT: warning: cannot preempt symbol: bar
+// NOINHIBIT-NEXT: >>> defined in {{.*}}.so
+// NOINHIBIT-NEXT: >>> referenced by {{.*}}.o:(.text+0x1)
 // NOINHIBIT: warning: symbol 'zed' has no type
 // NOINHIBIT-NEXT: >>> defined in {{.*}}.so
 // NOINHIBIT-NEXT: >>> referenced by {{.*}}.o:(.text+0x6)

Removed: lld/trunk/test/ELF/copy-rel-pie-error.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/copy-rel-pie-error.s?rev=369261&view=auto
==============================================================================
--- lld/trunk/test/ELF/copy-rel-pie-error.s (original)
+++ lld/trunk/test/ELF/copy-rel-pie-error.s (removed)
@@ -1,18 +0,0 @@
-// REQUIRES: x86
-// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
-// RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
-// RUN: ld.lld %t2.o -o %t2.so -shared
-// RUN: not ld.lld %t.o %t2.so -o /dev/null -pie 2>&1 | FileCheck %s
-
-// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: bar in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
-// CHECK: >>> defined in {{.*}}.so
-// CHECK: >>> referenced by {{.*}}.o:(.text+0x0)
-
-// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
-// CHECK: >>> defined in {{.*}}.so
-// CHECK: >>> referenced by {{.*}}.o:(.text+0x8)
-
-.global _start
-_start:
-        .quad bar
-        .quad foo

Added: lld/trunk/test/ELF/copy-rel-pie2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/copy-rel-pie2.s?rev=369262&view=auto
==============================================================================
--- lld/trunk/test/ELF/copy-rel-pie2.s (added)
+++ lld/trunk/test/ELF/copy-rel-pie2.s Mon Aug 19 07:30:12 2019
@@ -0,0 +1,13 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t -pie
+// RUN: llvm-readobj -r %t | FileCheck %s
+
+// CHECK: R_X86_64_COPY
+// CHECK: R_X86_64_JUMP_SLOT
+
+.rodata
+.quad bar
+.quad foo

Modified: lld/trunk/test/ELF/got32-i386.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/got32-i386.s?rev=369262&r1=369261&r2=369262&view=diff
==============================================================================
--- lld/trunk/test/ELF/got32-i386.s (original)
+++ lld/trunk/test/ELF/got32-i386.s Mon Aug 19 07:30:12 2019
@@ -20,4 +20,4 @@ _start:
 # CHECK:  .got 00000004 0000000000402000
 
 # RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s --check-prefix=ERR
-# ERR: error: can't create dynamic relocation R_386_GOT32 against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
+# ERR: error: symbol 'foo' cannot be preempted; recompile with -fPIE

Modified: lld/trunk/test/ELF/got32x-i386.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/got32x-i386.s?rev=369262&r1=369261&r2=369262&view=diff
==============================================================================
--- lld/trunk/test/ELF/got32x-i386.s (original)
+++ lld/trunk/test/ELF/got32x-i386.s Mon Aug 19 07:30:12 2019
@@ -43,5 +43,4 @@
 
 # RUN: not ld.lld %S/Inputs/i386-got32x-baseless.elf -o %t1 -pie 2>&1 | \
 # RUN:   FileCheck %s --check-prefix=ERR
-# ERR: error: can't create dynamic relocation R_386_GOT32X against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
-# ERR: error: can't create dynamic relocation R_386_GOT32X against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
+# ERR-COUNT-2: error: symbol 'foo' cannot be preempted; recompile with -fPIE

Modified: lld/trunk/test/ELF/x86-64-dyn-rel-error5.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-dyn-rel-error5.s?rev=369262&r1=369261&r2=369262&view=diff
==============================================================================
--- lld/trunk/test/ELF/x86-64-dyn-rel-error5.s (original)
+++ lld/trunk/test/ELF/x86-64-dyn-rel-error5.s Mon Aug 19 07:30:12 2019
@@ -1,7 +1,7 @@
 # REQUIRES: x86
 # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
-# RUN: not ld.lld -pie %t.o -o /dev/null 2>&1 | FileCheck %s
-# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s
+# RUN: not ld.lld -pie %t.o -o /dev/null 2>&1 | FileCheck --check-prefixes=CHECK,PIE %s
+# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck --check-prefixes=CHECK,SHARED %s
 
 ## Check we don't create dynamic relocations in a writable section,
 ## if the number of bits is smaller than the wordsize.
@@ -16,7 +16,9 @@ hidden:
 # CHECK-NEXT: >>> referenced by {{.*}}.o:(.data+0x0)
 # CHECK: error: relocation R_X86_64_16 cannot be used against local symbol; recompile with -fPIC
 # CHECK: error: relocation R_X86_64_32 cannot be used against local symbol; recompile with -fPIC
-# CHECK: error: relocation R_X86_64_32 cannot be used against symbol hidden; recompile with -fPIC
+
+# PIE: error: cannot preempt symbol: hidden
+# SHARED: error: relocation R_X86_64_32 cannot be used against symbol hidden; recompile with -fPIC
 
 .data
 .byte local     # R_X86_64_8




More information about the llvm-commits mailing list