Index: lld/ELF/Relocations.cpp =================================================================== --- lld/ELF/Relocations.cpp +++ lld/ELF/Relocations.cpp @@ -1306,8 +1306,25 @@ // Read an addend. int64_t addend = computeAddend(rel, end, sec, expr, sym.isLocal()); - if (config->emachine == EM_PPC64) { + // Subtract 2 to get the previous iterator because we have already done ++i + // above. + const RelTy &prevRel = *(i - 2); + RelType prevType = prevRel.getType(config->isMips64EL); + // When computing the address of a TLS symbol for the General Dynamic + // and Local Dynamic models a call is made to __tls_get_addr. This function + // requires two relocations on it. The first is for the symbol marked with + // R_PPC64_TLSGD or R_PPC64_TLSLD. The second is for the function call + // itself and is marked with R_PPC64_REL24 or R_PPC64_REL24_NOTOC. + // The following code checks that the TLSGD/LD relocations are not missing. + if (((type == R_PPC64_REL24 || type == R_PPC64_REL24_NOTOC) && + sym.getName() == "__tls_get_addr") && + (prevRel.r_offset != rel.r_offset || + (prevType != R_PPC64_TLSGD && prevType != R_PPC64_TLSLD))) + error("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. Index: lld/test/ELF/ppc64-error-missing-tlsgdld.s =================================================================== --- /dev/null +++ lld/test/ELF/ppc64-error-missing-tlsgdld.s @@ -0,0 +1,23 @@ +# REQUIRES ppc + +# RUN: not ld.lld --shared %p/Inputs/GeneralDynamicMissingTLSGD.o -o %t +# RUN: not ld.lld --shared %p/Inputs/LocalDynamicMissingTLSLD.o -o %t +# RUN: not ld.lld --shared %p/Inputs/GeneralDynamicMissingTLSGD_NOTOC.o -o %t +# RUN: not ld.lld --shared %p/Inputs/LocalDynamicMissingTLSLD_NOTOC.o -o %t + +## Make sure that lld produces the correct error when a call to __tls_get_addr +## does not have a corresponding R_PPC64_TLSGD/R_PPC64_TLSLD relocation. +## This file uses pre-built object files because clang cannot produce object +## files with this error at this time. + +CHECK: error: Call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation. +CHECK-NEXT: defined in ./Inputs/GeneralDynamicMissingTLSGD.o + +CHECK: error: Call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation. +CHECK-NEXT: defined in ./Inputs/LocalDynamicMissingTLSLD.o + +CHECK: error: Call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation. +CHECK-NEXT: defined in ./Inputs/GeneralDynamicMissingTLSGD_NOTOC.o + +CHECK: error: Call to __tls_get_addr is missing a R_PPC64_TLSGD/R_PPC64_TLSLD relocation. +CHECK-NEXT: defined in ./Inputs/LocalDynamicMissingTLSLD_NOTOC.o