[ELF] Don't error on R_PPC64_REL24/R_PPC64_REL24_NOTOC referencing __tls_get_addr for missing R_PPC64_TLSGD/R_PPC64_TLSLD

This partially reverts D85994.

In glibc, elf/dl-sym.c calls the raw `__tls_get_addr` by specifying the
tls_index parameter. Such a call does not have a pairing R_PPC64_TLSGD/R_PPC64_TLSLD.
This is legitimate. Since we cannot distinguish the benign case from cases due
to toolchain issues, we have to be permissive.

Acked by Stefan Pintilie
This commit is contained in:
Fangrui Song 2020-10-23 10:37:24 -07:00
parent 2b8fb5185e
commit 9267caebfa
2 changed files with 5 additions and 43 deletions

View File

@ -1319,28 +1319,6 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
int64_t addend = computeAddend<ELFT>(rel, end, sec, expr, sym.isLocal());
if (config->emachine == EM_PPC64) {
// For a call to __tls_get_addr, the instruction needs to be relocated by
// two relocations, R_PPC64_TLSGD/R_PPC64_TLSLD and R_PPC64_REL24[_NOTOC].
// R_PPC64_TLSGD/R_PPC64_TLSLD should precede R_PPC64_REL24[_NOTOC].
if ((type == R_PPC64_REL24 || type == R_PPC64_REL24_NOTOC) &&
sym.getName() == "__tls_get_addr") {
bool err = i - start < 2;
if (!err) {
// Subtract 2 to get the previous iterator because we have already done
// ++i above. This is now safe because we know that i-1 is not the
// start.
const RelTy &prevRel = *(i - 2);
RelType prevType = prevRel.getType(config->isMips64EL);
err = prevRel.r_offset != rel.r_offset ||
(prevType != R_PPC64_TLSGD && prevType != R_PPC64_TLSLD);
}
if (err)
errorOrWarn("call to __tls_get_addr is missing a "
"R_PPC64_TLSGD/R_PPC64_TLSLD relocation" +
getLocation(sec, sym, offset));
}
// We can separate the small code model relocations into 2 categories:
// 1) Those that access the compiler generated .toc sections.
// 2) Those that access the linker allocated got entries.

View File

@ -1,28 +1,12 @@
# REQUIRES: ppc
# RUN: llvm-mc --triple=powerpc64le %s --filetype=obj -o %t1.o
# RUN: llvm-mc --triple=powerpc64 %s --filetype=obj -o %t2.o
# RUN: not ld.lld --shared %t1.o -o /dev/null 2>&1 | FileCheck %s
# RUN: not ld.lld --shared %t2.o -o /dev/null 2>&1 | FileCheck %s
# RUN: ld.lld --shared --fatal-warnings %t1.o -o /dev/null
# RUN: ld.lld --shared --fatal-warnings %t2.o -o /dev/null
# CHECK: ld.lld: error: call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation
# CHECK-NEXT: defined in {{.*}}.o
# CHECK-NEXT: referenced by {{.*}}.o:(.text+0x8)
# CHECK: ld.lld: error: call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation
# CHECK-NEXT: defined in {{.*}}.o
# CHECK-NEXT: referenced by {{.*}}.o:(.text+0x18)
# CHECK: ld.lld: error: call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation
# CHECK-NEXT: defined in {{.*}}.o
# CHECK-NEXT: referenced by {{.*}}.o:(.text+0x28)
# CHECK: ld.lld: error: call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation
# CHECK-NEXT: defined in {{.*}}.o
# CHECK-NEXT: referenced by {{.*}}.o:(.text+0x38)
# CHECK: ld.lld: error: call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation
# CHECK-NEXT: defined in {{.*}}.o
# CHECK-NEXT: referenced by {{.*}}.o:(.text+0x40)
## User code can call __tls_get_addr by specifying the tls_index parameter.
## We need to allow R_PPC64_REL24/R_PPC64_REL24_NOTOC referencing __tls_get_addr
## without a pairing R_PPC64_TLSGD/R_PPC64_TLSLD.
GeneralDynamic:
addis 3, 2, x@got@tlsgd@ha