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