[lld] r325307 - Relax relocation type checking in a non-ALLOC section.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 15 17:10:52 PST 2018


Author: ruiu
Date: Thu Feb 15 17:10:51 2018
New Revision: 325307

URL: http://llvm.org/viewvc/llvm-project?rev=325307&view=rev
Log:
Relax relocation type checking in a non-ALLOC section.

Even though it doesn't make sense, there seems to be multiple programs
in the wild that create PC-relative relocations in non-ALLOC sections.
I believe this is caused by the negligence of GNU linkers to not report
any errors for such relocations.

Currently, lld emits warnings against such relocations and exits.
So, you cannot link any program that contains wrong relocations until
you fix an issue in a program that generates wrong ELF files. It's often
impractical to fix a program because it's not always easy.

This patch relaxes the error checking and emit a warning instead.

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

Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/test/ELF/i386-debug-noabs.test
    lld/trunk/test/ELF/non-abs-reloc.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=325307&r1=325306&r2=325307&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu Feb 15 17:10:51 2018
@@ -641,6 +641,14 @@ void InputSection::relocateNonAlloc(uint
 
   for (const RelTy &Rel : Rels) {
     RelType Type = Rel.getType(Config->IsMips64EL);
+
+    // GCC 8.0 or earlier have a bug that they emit R_386_GOTPC relocations
+    // against _GLOBAL_OFFSET_TABLE_ for .debug_info. The bug has been fixed
+    // in 2017 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82630), but we
+    // need to keep this bug-compatible code for a while.
+    if (Config->EMachine == EM_386 && Type == R_386_GOTPC)
+      continue;
+
     uint64_t Offset = getOffset(Rel.r_offset);
     uint8_t *BufLoc = Buf + Offset;
     int64_t Addend = getAddend<ELFT>(Rel);
@@ -651,17 +659,27 @@ void InputSection::relocateNonAlloc(uint
     RelExpr Expr = Target->getRelExpr(Type, Sym, BufLoc);
     if (Expr == R_NONE)
       continue;
+
     if (Expr != R_ABS) {
-      // GCC 8.0 or earlier have a bug that it emits R_386_GOTPC relocations
-      // against _GLOBAL_OFFSET_TABLE for .debug_info. The bug seems to have
-      // been fixed in 2017: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82630,
-      // but we need to keep this bug-compatible code for a while.
-      if (Config->EMachine == EM_386 && Type == R_386_GOTPC)
-        continue;
-
-      error(getLocation<ELFT>(Offset) + ": has non-ABS relocation " +
-            toString(Type) + " against symbol '" + toString(Sym) + "'");
-      return;
+      std::string Msg = getLocation<ELFT>(Offset) +
+                        ": has non-ABS relocation " + toString(Type) +
+                        " against symbol '" + toString(Sym) + "'";
+      if (Expr != R_PC) {
+        error(Msg);
+        return;
+      }
+
+      // If the control reaches here, we found a PC-relative relocation in a
+      // non-ALLOC section. Since non-ALLOC section is not loaded into memory
+      // at runtime, the notion of PC-relative doesn't make sense here. So,
+      // this is a usage error. However, GNU linkers historically accept such
+      // relocations without any errors and relocate them as if they were at
+      // address 0. For bug-compatibilty, we accept them with warnings. We
+      // know Steel Bank Common Lisp as of 2018 have this bug.
+      warn(Msg);
+      Target->relocateOne(BufLoc, Type,
+                          SignExtend64<Bits>(Sym.getVA(Addend - Offset)));
+      continue;
     }
 
     if (Sym.isTls() && !Out::TlsPhdr)

Modified: lld/trunk/test/ELF/i386-debug-noabs.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/i386-debug-noabs.test?rev=325307&r1=325306&r2=325307&view=diff
==============================================================================
--- lld/trunk/test/ELF/i386-debug-noabs.test (original)
+++ lld/trunk/test/ELF/i386-debug-noabs.test Thu Feb 15 17:10:51 2018
@@ -1,7 +1,7 @@
 # REQUIRES: x86
 
 # RUN: yaml2obj %s -o %t.o
-# RUN: ld.lld %t.o -o %t.exe
+# RUN: ld.lld %t.o -o %t.exe --entry 0 --fatal-warnings
 
 ## This is for https://bugs.llvm.org//show_bug.cgi?id=34852. GCC 8.0 or
 ## earlier have a bug which creates non-absolute R_386_GOTPC relocations

Modified: lld/trunk/test/ELF/non-abs-reloc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/non-abs-reloc.s?rev=325307&r1=325306&r2=325307&view=diff
==============================================================================
--- lld/trunk/test/ELF/non-abs-reloc.s (original)
+++ lld/trunk/test/ELF/non-abs-reloc.s Thu Feb 15 17:10:51 2018
@@ -1,11 +1,19 @@
 // REQUIRES: x86
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-// RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s
-// CHECK: {{.*}}:(.dummy+0x0): has non-ABS relocation R_X86_64_GOTPCREL against symbol 'foo'
+// RUN: ld.lld %t.o -o %t 2>&1 | FileCheck %s
+// CHECK: (.nonalloc+0x1): has non-ABS relocation R_X86_64_PC32 against symbol '_start'
+// CHECK: (.nonalloc+0x6): has non-ABS relocation R_X86_64_PC32 against symbol '_start'
+
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=DISASM %s
+// DISASM:      Disassembly of section .nonalloc:
+// DISASM-NEXT: .nonalloc:
+// DISASM-NEXT: 0: {{.*}}  callq {{.*}} <_start>
+// DISASM-NEXT: 5: {{.*}}  callq {{.*}} <_start>
 
 .globl _start
 _start:
   nop
 
-.section .dummy
-  .long foo at gotpcrel
+.section .nonalloc
+  call _start
+  call _start




More information about the llvm-commits mailing list