[lld] r363059 - [ELF] Make the rule to create relative relocations in a writable section stricter

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 11 05:59:30 PDT 2019


Author: maskray
Date: Tue Jun 11 05:59:30 2019
New Revision: 363059

URL: http://llvm.org/viewvc/llvm-project?rev=363059&view=rev
Log:
[ELF] Make the rule to create relative relocations in a writable section stricter

The current rule is loose: `!Sym.IsPreemptible || Expr == R_GOT`.

When the symbol is non-preemptable, this allows absolute relocation
types with smaller numbers of bits, e.g. R_X86_64_{8,16,32}. They are
disallowed by ld.bfd and gold, e.g.

    ld.bfd: a.o: relocation R_X86_64_8 against `.text' can not be used when making a shared object; recompile with -fPIC

This patch:

a) Add TargetInfo::SymbolicRel to represent relocation types that resolve to a
symbol value (e.g. R_AARCH_ABS64, R_386_32, R_X86_64_64).

  As a side benefit, we currently (ab)use GotRel (R_*_GLOB_DAT) to resolve
  GOT slots that are link-time constants. Since we now use Target->SymbolRel
  to do the job, we can remove R_*_GLOB_DAT from relocateOne() for all targets.
  R_*_GLOB_DAT cannot be used as static relocation types.
b) Change the condition to `!Sym.IsPreemptible && Type != Target->SymbolicRel || Expr == R_GOT`.

Some tests are caught by the improved error checking (ld.bfd/gold also
issue errors on them). Many misuse .long where .quad should be used
instead.

Reviewed By: ruiu

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

Added:
    lld/trunk/test/ELF/x86-64-dyn-rel-error5.s
Modified:
    lld/trunk/ELF/Arch/AArch64.cpp
    lld/trunk/ELF/Arch/AMDGPU.cpp
    lld/trunk/ELF/Arch/ARM.cpp
    lld/trunk/ELF/Arch/Hexagon.cpp
    lld/trunk/ELF/Arch/Mips.cpp
    lld/trunk/ELF/Arch/PPC.cpp
    lld/trunk/ELF/Arch/PPC64.cpp
    lld/trunk/ELF/Arch/SPARCV9.cpp
    lld/trunk/ELF/Arch/X86.cpp
    lld/trunk/ELF/Arch/X86_64.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/test/ELF/linkerscript/visibility.s
    lld/trunk/test/ELF/merge-string-error.s
    lld/trunk/test/ELF/pack-dyn-relocs-loop.s
    lld/trunk/test/ELF/relocation-before-merge-start.s
    lld/trunk/test/ELF/relocation-past-merge-end.s

Modified: lld/trunk/ELF/Arch/AArch64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/AArch64.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/AArch64.cpp (original)
+++ lld/trunk/ELF/Arch/AArch64.cpp Tue Jun 11 05:59:30 2019
@@ -59,6 +59,7 @@ AArch64::AArch64() {
   GotRel = R_AARCH64_GLOB_DAT;
   NoneRel = R_AARCH64_NONE;
   PltRel = R_AARCH64_JUMP_SLOT;
+  SymbolicRel = R_AARCH64_ABS64;
   TlsDescRel = R_AARCH64_TLSDESC;
   TlsGotRel = R_AARCH64_TLS_TPREL64;
   PltEntrySize = 16;
@@ -258,7 +259,6 @@ void AArch64::relocateOne(uint8_t *Loc,
     write32le(Loc, Val);
     break;
   case R_AARCH64_ABS64:
-  case R_AARCH64_GLOB_DAT:
   case R_AARCH64_PREL64:
     write64le(Loc, Val);
     break;

Modified: lld/trunk/ELF/Arch/AMDGPU.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/AMDGPU.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/AMDGPU.cpp (original)
+++ lld/trunk/ELF/Arch/AMDGPU.cpp Tue Jun 11 05:59:30 2019
@@ -35,6 +35,7 @@ AMDGPU::AMDGPU() {
   RelativeRel = R_AMDGPU_RELATIVE64;
   GotRel = R_AMDGPU_ABS64;
   NoneRel = R_AMDGPU_NONE;
+  SymbolicRel = R_AMDGPU_ABS64;
 }
 
 static uint32_t getEFlags(InputFile *File) {

Modified: lld/trunk/ELF/Arch/ARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/ARM.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/ARM.cpp (original)
+++ lld/trunk/ELF/Arch/ARM.cpp Tue Jun 11 05:59:30 2019
@@ -52,6 +52,7 @@ ARM::ARM() {
   GotRel = R_ARM_GLOB_DAT;
   NoneRel = R_ARM_NONE;
   PltRel = R_ARM_JUMP_SLOT;
+  SymbolicRel = R_ARM_ABS32;
   TlsGotRel = R_ARM_TLS_TPOFF32;
   TlsModuleIndexRel = R_ARM_TLS_DTPMOD32;
   TlsOffsetRel = R_ARM_TLS_DTPOFF32;
@@ -377,7 +378,6 @@ void ARM::relocateOne(uint8_t *Loc, RelT
   switch (Type) {
   case R_ARM_ABS32:
   case R_ARM_BASE_PREL:
-  case R_ARM_GLOB_DAT:
   case R_ARM_GOTOFF32:
   case R_ARM_GOT_BREL:
   case R_ARM_GOT_PREL:

Modified: lld/trunk/ELF/Arch/Hexagon.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/Hexagon.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/Hexagon.cpp (original)
+++ lld/trunk/ELF/Arch/Hexagon.cpp Tue Jun 11 05:59:30 2019
@@ -40,6 +40,7 @@ Hexagon::Hexagon() {
   PltRel = R_HEX_JMP_SLOT;
   RelativeRel = R_HEX_RELATIVE;
   GotRel = R_HEX_GLOB_DAT;
+  SymbolicRel = R_HEX_32;
 
   // The zero'th GOT entry is reserved for the address of _DYNAMIC.  The
   // next 3 are reserved for the dynamic loader.

Modified: lld/trunk/ELF/Arch/Mips.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/Mips.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/Mips.cpp (original)
+++ lld/trunk/ELF/Arch/Mips.cpp Tue Jun 11 05:59:30 2019
@@ -59,11 +59,13 @@ template <class ELFT> MIPS<ELFT>::MIPS()
 
   if (ELFT::Is64Bits) {
     RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32;
+    SymbolicRel = R_MIPS_64;
     TlsGotRel = R_MIPS_TLS_TPREL64;
     TlsModuleIndexRel = R_MIPS_TLS_DTPMOD64;
     TlsOffsetRel = R_MIPS_TLS_DTPREL64;
   } else {
     RelativeRel = R_MIPS_REL32;
+    SymbolicRel = R_MIPS_32;
     TlsGotRel = R_MIPS_TLS_TPREL32;
     TlsModuleIndexRel = R_MIPS_TLS_DTPMOD32;
     TlsOffsetRel = R_MIPS_TLS_DTPREL32;

Modified: lld/trunk/ELF/Arch/PPC.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC.cpp (original)
+++ lld/trunk/ELF/Arch/PPC.cpp Tue Jun 11 05:59:30 2019
@@ -135,6 +135,7 @@ PPC::PPC() {
   PltRel = R_PPC_JMP_SLOT;
   RelativeRel = R_PPC_RELATIVE;
   IRelativeRel = R_PPC_IRELATIVE;
+  SymbolicRel = R_PPC_ADDR32;
   GotBaseSymInGotPlt = false;
   GotHeaderEntriesNum = 3;
   GotPltHeaderEntriesNum = 0;
@@ -288,7 +289,6 @@ void PPC::relocateOne(uint8_t *Loc, RelT
     write16(Loc, Val);
     break;
   case R_PPC_ADDR32:
-  case R_PPC_GLOB_DAT:
   case R_PPC_REL32:
     write32(Loc, Val);
     break;

Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Tue Jun 11 05:59:30 2019
@@ -288,6 +288,7 @@ PPC64::PPC64() {
   PltRel = R_PPC64_JMP_SLOT;
   RelativeRel = R_PPC64_RELATIVE;
   IRelativeRel = R_PPC64_IRELATIVE;
+  SymbolicRel = R_PPC64_ADDR64;
   PltEntrySize = 4;
   GotBaseSymInGotPlt = false;
   GotHeaderEntriesNum = 1;

Modified: lld/trunk/ELF/Arch/SPARCV9.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/SPARCV9.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/SPARCV9.cpp (original)
+++ lld/trunk/ELF/Arch/SPARCV9.cpp Tue Jun 11 05:59:30 2019
@@ -37,6 +37,7 @@ SPARCV9::SPARCV9() {
   NoneRel = R_SPARC_NONE;
   PltRel = R_SPARC_JMP_SLOT;
   RelativeRel = R_SPARC_RELATIVE;
+  SymbolicRel = R_SPARC_64;
   PltEntrySize = 32;
   PltHeaderSize = 4 * PltEntrySize;
 
@@ -114,7 +115,6 @@ void SPARCV9::relocateOne(uint8_t *Loc,
     break;
   case R_SPARC_64:
   case R_SPARC_UA64:
-  case R_SPARC_GLOB_DAT:
     // V-xword64
     write64be(Loc, Val);
     break;

Modified: lld/trunk/ELF/Arch/X86.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86.cpp (original)
+++ lld/trunk/ELF/Arch/X86.cpp Tue Jun 11 05:59:30 2019
@@ -52,6 +52,7 @@ X86::X86() {
   PltRel = R_386_JUMP_SLOT;
   IRelativeRel = R_386_IRELATIVE;
   RelativeRel = R_386_RELATIVE;
+  SymbolicRel = R_386_32;
   TlsGotRel = R_386_TLS_TPOFF;
   TlsModuleIndexRel = R_386_TLS_DTPMOD32;
   TlsOffsetRel = R_386_TLS_DTPOFF32;
@@ -291,7 +292,6 @@ void X86::relocateOne(uint8_t *Loc, RelT
     write16le(Loc, Val);
     break;
   case R_386_32:
-  case R_386_GLOB_DAT:
   case R_386_GOT32:
   case R_386_GOT32X:
   case R_386_GOTOFF:

Modified: lld/trunk/ELF/Arch/X86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86_64.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86_64.cpp (original)
+++ lld/trunk/ELF/Arch/X86_64.cpp Tue Jun 11 05:59:30 2019
@@ -55,6 +55,7 @@ X86_64::X86_64() {
   PltRel = R_X86_64_JUMP_SLOT;
   RelativeRel = R_X86_64_RELATIVE;
   IRelativeRel = R_X86_64_IRELATIVE;
+  SymbolicRel = R_X86_64_64;
   TlsDescRel = R_X86_64_TLSDESC;
   TlsGotRel = R_X86_64_TPOFF64;
   TlsModuleIndexRel = R_X86_64_DTPMOD64;
@@ -387,7 +388,6 @@ void X86_64::relocateOne(uint8_t *Loc, R
     break;
   case R_X86_64_64:
   case R_X86_64_DTPOFF64:
-  case R_X86_64_GLOB_DAT:
   case R_X86_64_PC64:
   case R_X86_64_SIZE64:
   case R_X86_64_GOT64:

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Tue Jun 11 05:59:30 2019
@@ -861,19 +861,19 @@ static void addGotEntry(Symbol &Sym) {
   bool IsLinkTimeConstant =
       !Sym.IsPreemptible && (!Config->Pic || isAbsolute(Sym));
   if (IsLinkTimeConstant) {
-    In.Got->Relocations.push_back({Expr, Target->GotRel, Off, 0, &Sym});
+    In.Got->Relocations.push_back({Expr, Target->SymbolicRel, Off, 0, &Sym});
     return;
   }
 
   // Otherwise, we emit a dynamic relocation to .rel[a].dyn so that
   // the GOT slot will be fixed at load-time.
   if (!Sym.isTls() && !Sym.IsPreemptible && Config->Pic && !isAbsolute(Sym)) {
-    addRelativeReloc(In.Got, Off, &Sym, 0, R_ABS, Target->GotRel);
+    addRelativeReloc(In.Got, Off, &Sym, 0, R_ABS, Target->SymbolicRel);
     return;
   }
-  Main->RelaDyn->addReloc(Sym.isTls() ? Target->TlsGotRel : Target->GotRel,
-                          In.Got, Off, &Sym, 0,
-                          Sym.IsPreemptible ? R_ADDEND : R_ABS, Target->GotRel);
+  Main->RelaDyn->addReloc(
+      Sym.isTls() ? Target->TlsGotRel : Target->GotRel, In.Got, Off, &Sym, 0,
+      Sym.IsPreemptible ? R_ADDEND : R_ABS, Target->SymbolicRel);
 }
 
 // Return true if we can define a symbol in the executable that
@@ -919,10 +919,10 @@ static void processRelocAux(InputSection
   }
   bool CanWrite = (Sec.Flags & SHF_WRITE) || !Config->ZText;
   if (CanWrite) {
-    // R_GOT refers to a position in the got, even if the symbol is preemptible.
-    bool IsPreemptibleValue = Sym.IsPreemptible && Expr != R_GOT;
-
-    if (!IsPreemptibleValue) {
+    if ((!Sym.IsPreemptible && Type == Target->SymbolicRel) || Expr == R_GOT) {
+      // If this is a symbolic relocation to a non-preemptable symbol, or an
+      // R_GOT, its address is its link-time value plus load address. Represent
+      // it with a relative relocation.
       addRelativeReloc(&Sec, Offset, &Sym, Addend, Expr, Type);
       return;
     } else if (RelType Rel = Target->getDynRel(Type)) {
@@ -967,11 +967,18 @@ static void processRelocAux(InputSection
     return;
   }
 
-  // Copy relocations are only possible if we are creating an executable.
-  if (Config->Shared) {
-    errorOrWarn("relocation " + toString(Type) +
-                " cannot be used against symbol " + toString(Sym) +
-                "; recompile with -fPIC" + getLocation(Sec, Sym, Offset));
+  // 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;
   }
 

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Tue Jun 11 05:59:30 2019
@@ -95,6 +95,7 @@ public:
   RelType PltRel;
   RelType RelativeRel;
   RelType IRelativeRel;
+  RelType SymbolicRel;
   RelType TlsDescRel;
   RelType TlsGotRel;
   RelType TlsModuleIndexRel;

Modified: lld/trunk/test/ELF/linkerscript/visibility.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/visibility.s?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/visibility.s (original)
+++ lld/trunk/test/ELF/linkerscript/visibility.s Tue Jun 11 05:59:30 2019
@@ -19,4 +19,4 @@
 
         .data
         .hidden foo
-        .long foo
+        .quad foo

Modified: lld/trunk/test/ELF/merge-string-error.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/merge-string-error.s?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/test/ELF/merge-string-error.s (original)
+++ lld/trunk/test/ELF/merge-string-error.s Tue Jun 11 05:59:30 2019
@@ -6,6 +6,6 @@
 	.asciz	"abc"
 
         .data
-        .long .rodata.str1.1 + 4
+        .quad .rodata.str1.1 + 4
 
 // CHECK: merge-string-error.s.tmp.o:(.rodata.str1.1): offset is outside the section

Modified: lld/trunk/test/ELF/pack-dyn-relocs-loop.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/pack-dyn-relocs-loop.s?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/test/ELF/pack-dyn-relocs-loop.s (original)
+++ lld/trunk/test/ELF/pack-dyn-relocs-loop.s Tue Jun 11 05:59:30 2019
@@ -46,7 +46,7 @@
 // CHECK-NEXT:    ]
 // CHECK-NEXT:    Address: 0x10004
 // CHECK-NEXT:    Offset: 0x10004
-// CHECK-NEXT:    Size: 12
+// CHECK-NEXT:    Size: 24
 
 
 .data
@@ -54,9 +54,9 @@
 
 .section foo,"aw"
 foof:
-.long foof
-.long bar-53
-.long bar
+.quad foof
+.quad bar-53
+.quad bar
 
 .section x,"a"
 .zero 65036

Modified: lld/trunk/test/ELF/relocation-before-merge-start.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocation-before-merge-start.s?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/test/ELF/relocation-before-merge-start.s (original)
+++ lld/trunk/test/ELF/relocation-before-merge-start.s Tue Jun 11 05:59:30 2019
@@ -4,6 +4,6 @@
 // CHECK: relocation-before-merge-start.s.tmp.o:(.foo): offset is outside the section
 
 .data
-.long .foo - 1
+.quad .foo - 1
 .section	.foo,"aM", at progbits,4
 .quad 0

Modified: lld/trunk/test/ELF/relocation-past-merge-end.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocation-past-merge-end.s?rev=363059&r1=363058&r2=363059&view=diff
==============================================================================
--- lld/trunk/test/ELF/relocation-past-merge-end.s (original)
+++ lld/trunk/test/ELF/relocation-past-merge-end.s Tue Jun 11 05:59:30 2019
@@ -4,6 +4,6 @@
 // CHECK: relocation-past-merge-end.s.tmp.o:(.foo): offset is outside the section
 
 .data
-.long .foo + 10
+.quad .foo + 10
 .section	.foo,"aM", at progbits,4
 .quad 0

Added: 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=363059&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-dyn-rel-error5.s (added)
+++ lld/trunk/test/ELF/x86-64-dyn-rel-error5.s Tue Jun 11 05:59:30 2019
@@ -0,0 +1,26 @@
+# 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
+
+## Check we don't create dynamic relocations in a writable section,
+## if the number of bits is smaller than the wordsize.
+
+.globl hidden
+.hidden hidden
+local:
+hidden:
+
+# CHECK: error: relocation R_X86_64_8 cannot be used against local symbol; recompile with -fPIC
+# CHECK-NEXT: >>> defined in {{.*}}.o
+# 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
+
+.data
+.byte local     # R_X86_64_8
+.short local    # R_X86_64_16
+.long local     # R_X86_64_32
+
+.long hidden    # R_X86_64_32




More information about the llvm-commits mailing list