Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -996,56 +996,31 @@ } } - 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) for absolute or relative + // relocations. + if (!config->shared && (expr == R_ABS || isRelExpr(expr)) && + !sym.isUndefined() && (sym.isFunc() || sym.isObject())) { + if (!canDefineSymbolInExecutable(sym)) { + error("cannot preempt symbol: " + toString(sym) + + getLocation(sec, sym, offset)); + return; + } - if (sym.isObject()) { - // Produce a copy relocation. - if (auto *ss = dyn_cast(&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(*ss); + if (sym.isObject()) { + // Produce a copy relocation. + if (auto *ss = dyn_cast(&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(*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 @@ -1088,6 +1063,28 @@ return; } + 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)); + return; + } + + if (config->isPic) { + 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)); } Index: test/ELF/copy-errors.s =================================================================== --- test/ELF/copy-errors.s +++ test/ELF/copy-errors.s @@ -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: symbol 'bar' has no type // 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: symbol 'bar' has no type +// 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) Index: test/ELF/copy-rel-pie-error.s =================================================================== --- test/ELF/copy-rel-pie-error.s +++ /dev/null @@ -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 Index: test/ELF/copy-rel-pie2.s =================================================================== --- /dev/null +++ test/ELF/copy-rel-pie2.s @@ -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 Index: test/ELF/typed-undef.s =================================================================== --- test/ELF/typed-undef.s +++ test/ELF/typed-undef.s @@ -3,7 +3,9 @@ # We used to crash on this, check that we don't # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -# RUN: ld.lld %t.o -o /dev/null -pie --unresolved-symbols=ignore-all +# RUN: not ld.lld %t.o -o /dev/null -pie --unresolved-symbols=ignore-all 2>&1 | FileCheck %s + +# CHECK: error: relocation R_X86_64_PC64 cannot be used against symbol foo; recompile with -fPIC .global _start _start: