diff options
author | Rui Ueyama <ruiu@google.com> | 2018-02-16 01:10:51 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2018-02-16 01:10:51 +0000 |
commit | 65b620be8a63c8dee5225562a43c6dfc827394a7 (patch) | |
tree | 94a131817f542bc3ec34f96ad6d452daf92046e7 | |
parent | da9c122203ee41d66979e906cea81c9ddbd1cfdc (diff) | |
download | bcm5719-llvm-65b620be8a63c8dee5225562a43c6dfc827394a7.tar.gz bcm5719-llvm-65b620be8a63c8dee5225562a43c6dfc827394a7.zip |
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
llvm-svn: 325307
-rw-r--r-- | lld/ELF/InputSection.cpp | 36 | ||||
-rw-r--r-- | lld/test/ELF/i386-debug-noabs.test | 2 | ||||
-rw-r--r-- | lld/test/ELF/non-abs-reloc.s | 16 |
3 files changed, 40 insertions, 14 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 6766c00915d..c59b03ba239 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -641,6 +641,14 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { 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(uint8_t *Buf, ArrayRef<RelTy> Rels) { 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; + std::string Msg = getLocation<ELFT>(Offset) + + ": has non-ABS relocation " + toString(Type) + + " against symbol '" + toString(Sym) + "'"; + if (Expr != R_PC) { + error(Msg); + return; + } - error(getLocation<ELFT>(Offset) + ": has non-ABS relocation " + - toString(Type) + " against symbol '" + toString(Sym) + "'"); - 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) diff --git a/lld/test/ELF/i386-debug-noabs.test b/lld/test/ELF/i386-debug-noabs.test index 712d0a59cec..c0eb4d9562d 100644 --- a/lld/test/ELF/i386-debug-noabs.test +++ b/lld/test/ELF/i386-debug-noabs.test @@ -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 diff --git a/lld/test/ELF/non-abs-reloc.s b/lld/test/ELF/non-abs-reloc.s index 454104cca07..875af47fe15 100644 --- a/lld/test/ELF/non-abs-reloc.s +++ b/lld/test/ELF/non-abs-reloc.s @@ -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@gotpcrel +.section .nonalloc + call _start + call _start |