Index: ELF/Arch/PPC64.cpp =================================================================== --- ELF/Arch/PPC64.cpp +++ ELF/Arch/PPC64.cpp @@ -580,8 +580,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 @@ -186,16 +186,28 @@ } if (isRelExprOneOf(Expr)) { - // Local-Dynamic relocs can be relaxed to Local-Exec. + R_TLSLD_HINT, R_TLSLD_GOT_OFF>(Expr)) { if (!Config->Shared) { + // Local-Dynamic relocs can be relaxed to Local-Exec. C.Relocations.push_back( {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type, Offset, Addend, &Sym}); return Target->TlsGdRelaxSkip; } + if (Expr == R_TLSLD_HINT) return 1; + + if (Expr == R_TLSLD_GOT_OFF) { + if (!Sym.isInGot()) { + InX::Got->addEntry(Sym); + InX::Got->Relocations.push_back( + {R_ABS, Target->TlsOffsetRel, Sym.getGotOffset(), 0, &Sym}); + } + C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + return 1; + } + if (InX::Got->addTlsIndex()) InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, InX::Got, InX::Got->getTlsIndexOff(), nullptr); @@ -203,7 +215,6 @@ return 1; } - // Local-Dynamic relocs can be relaxed to Local-Exec. if (Expr == R_ABS && !Config->Shared) { C.Relocations.push_back( {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type, @@ -211,23 +222,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()) { - InX::Got->addEntry(Sym); - uint64_t Off = Sym.getGotOffset(); - InX::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) {