Index: ELF/Arch/PPC64.cpp =================================================================== --- ELF/Arch/PPC64.cpp +++ ELF/Arch/PPC64.cpp @@ -737,8 +737,13 @@ RelExpr Expr) const { if (Expr == R_RELAX_TLS_GD_TO_IE) return R_RELAX_TLS_GD_TO_IE_GOT_OFF; - if (Expr == R_RELAX_TLS_LD_TO_LE) + + if (Expr == R_RELAX_TLS_LD_TO_LE) { + if (Type == R_PPC64_GOT_DTPREL16_HA || Type == R_PPC64_GOT_DTPREL16_LO_DS || + Type == R_PPC64_GOT_DTPREL16_DS || Type == R_PPC64_GOT_DTPREL16_HI) + return Expr; return R_RELAX_TLS_LD_TO_LE_ABS; + } return Expr; } Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -187,7 +187,7 @@ } if (isRelExprOneOf(Expr)) { + R_TLSLD_HINT, R_TLSLD_GOT_OFF>(Expr)) { // Local-Dynamic relocs can be relaxed to Local-Exec. if (!Config->Shared) { C.Relocations.push_back( @@ -195,8 +195,20 @@ Offset, Addend, &Sym}); return Target->TlsGdRelaxSkip; } + if (Expr == R_TLSLD_HINT) return 1; + + if (Expr == R_TLSLD_GOT_OFF) { + if (!Sym.isInGot()) { + In.Got->addEntry(Sym); + In.Got->Relocations.push_back( + {R_ABS, Target->TlsOffsetRel, Sym.getGotOffset(), 0, &Sym}); + } + C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + return 1; + } + if (In.Got->addTlsIndex()) In.RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got, In.Got->getTlsIndexOff(), nullptr); @@ -212,24 +224,6 @@ return 1; } - // Local-Dynamic sequence where offset of tls variable relative to dynamic - // thread pointer is stored in the got. - if (Expr == R_TLSLD_GOT_OFF) { - // Local-Dynamic relocs can be relaxed to local-exec - if (!Config->Shared) { - C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym}); - return 1; - } - if (!Sym.isInGot()) { - In.Got->addEntry(Sym); - uint64_t Off = Sym.getGotOffset(); - In.Got->Relocations.push_back( - {R_ABS, Target->TlsOffsetRel, Off, 0, &Sym}); - } - C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); - return 1; - } - if (isRelExprOneOf(Expr)) { if (Config->Shared) {