Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -993,56 +993,29 @@ } } - 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(&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 @@ -1070,21 +1043,44 @@ // 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(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(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)); } Index: lld/trunk/test/ELF/copy-errors.s =================================================================== --- lld/trunk/test/ELF/copy-errors.s +++ lld/trunk/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: 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) Index: lld/trunk/test/ELF/copy-rel-pie-error.s =================================================================== --- lld/trunk/test/ELF/copy-rel-pie-error.s +++ lld/trunk/test/ELF/copy-rel-pie-error.s @@ -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: lld/trunk/test/ELF/copy-rel-pie2.s =================================================================== --- lld/trunk/test/ELF/copy-rel-pie2.s +++ lld/trunk/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: lld/trunk/test/ELF/got32-i386.s =================================================================== --- lld/trunk/test/ELF/got32-i386.s +++ lld/trunk/test/ELF/got32-i386.s @@ -20,4 +20,4 @@ # 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 Index: lld/trunk/test/ELF/got32x-i386.s =================================================================== --- lld/trunk/test/ELF/got32x-i386.s +++ lld/trunk/test/ELF/got32x-i386.s @@ -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 Index: lld/trunk/test/ELF/x86-64-dyn-rel-error5.s =================================================================== --- lld/trunk/test/ELF/x86-64-dyn-rel-error5.s +++ lld/trunk/test/ELF/x86-64-dyn-rel-error5.s @@ -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 @@ # 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