forked from OSchip/llvm-project
[ELF] Move (copy relocation/canonical PLT) before error checking
In processRelocAux(), we handle errors before copy relocation/canonical PLT. This makes error checking a bit complex because we have to check for conditions that will be allowed by copy relocation/canonical PLT. Instead, move copy relocation/canonical PLT before error checking. This simplifies the previous clumsy error checking code `config->shared || (config->pie && expr == R_ABS && type != target->symbolicRel)` to the simple `config->isPic`. Some diagnostics can be reported in different ways. The code motion changes diagnostics for some contrived test cases: * copy-rel-pie-error.s -> copy-rel-pie2.s: It was rejected before but accepted now. ld.bfd also accepts the case. * copy-errors.s: "cannot preempt symbol" changes to "symbol 'bar' has no type" * got32{,x}-i386.s: the suggestion changes from "-fPIC or -Wl,-z,notext" to "-fPIE" * x86-64-dyn-rel-error5.s: one diagnostic changes for -pie case Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D66007 llvm-svn: 369262
This commit is contained in:
parent
0776da5236
commit
ac0e6c6502
|
@ -993,56 +993,29 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (sym.isObject()) {
|
||||
// Produce a copy relocation.
|
||||
if (auto *ss = dyn_cast<SharedSymbol>(&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<ELFT>(*ss);
|
||||
// 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<SharedSymbol>(&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<ELFT>(*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 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
|
|||
// 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<ELFT>(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<ELFT>(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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -20,4 +20,4 @@ _start:
|
|||
# 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ hidden:
|
|||
# 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
|
||||
|
|
Loading…
Reference in New Issue