Partially taken from Adélie Linux, even-more-secure-plt.patch --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -138,6 +138,10 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { if (isDarwin()) HasLazyResolverStubs = true; + // Force SecurePlt for all 32-bit Linux targets + if (isTargetLinux() && !IsPPC64) + SecurePlt = true; + if (HasSPE && IsPPC64) report_fatal_error( "SPE is only supported for 32-bit targets.\n", false); if (HasSPE && (HasAltivec || HasQPX || HasVSX || HasFPU)) --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -218,6 +218,10 @@ static Reloc::Model getEffectiveRelocModel(const Triple &TT, if (TT.getArch() == Triple::ppc64) return Reloc::PIC_; + // We force SecurePlt on 32-bit ppc linux which requires PIC + if (TT.isOSLinux() && (TT.getArch() == Triple::ppc)) + return Reloc::PIC_; + // Rest are static by default. return Reloc::Static; } --- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -442,13 +442,22 @@ // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must // come at the _end_ of the expression. const MCOperand &Op = MI->getOperand(OpNo); - const MCSymbolRefExpr &refExp = cast(*Op.getExpr()); - O << refExp.getSymbol().getName(); + const MCSymbolRefExpr *RefExp = nullptr; + const MCConstantExpr *ConstExp = nullptr; + if (const MCBinaryExpr *BinExpr = dyn_cast(Op.getExpr())) { + RefExp = cast(BinExpr->getLHS()); + ConstExp = cast(BinExpr->getRHS()); + } else + RefExp = cast(Op.getExpr()); + + O << RefExp->getSymbol().getName(); O << '('; printOperand(MI, OpNo+1, O); O << ')'; - if (refExp.getKind() != MCSymbolRefExpr::VK_None) - O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind()); + if (RefExp->getKind() != MCSymbolRefExpr::VK_None) + O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind()); + if (ConstExp != nullptr) + O << '+' << ConstExp->getValue(); } /// showRegistersWithPercentPrefix - Check if this register name should be --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -487,8 +487,14 @@ if (!Subtarget->isPPC64() && !Subtarget->isDarwin() && isPositionIndependent()) Kind = MCSymbolRefExpr::VK_PLT; - const MCSymbolRefExpr *TlsRef = + const MCExpr *TlsRef = MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext); + + // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI. + if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt()) + TlsRef = MCBinaryExpr::createAdd(TlsRef, + MCConstantExpr::create(32768, OutContext), + OutContext); const MachineOperand &MO = MI->getOperand(2); const GlobalValue *GValue = MO.getGlobal(); MCSymbol *MOSymbol = getSymbol(GValue); --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4054,7 +4054,20 @@ if (trySETCC(N)) return; break; - + // These nodes will be transformed into GETtlsADDR32 node, which + // later becomes BL_TLS __tls_get_addr(sym at tlsgd)@PLT + case PPCISD::ADDI_TLSLD_L_ADDR: + case PPCISD::ADDI_TLSGD_L_ADDR: { + const Module *Mod = MF->getFunction().getParent(); + if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 || + !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() || + Mod->getPICLevel() == PICLevel::SmallPIC) + break; + // Attach global base pointer on GETtlsADDR32 node in order to + // generate secure plt code for TLS symbols. + getGlobalBaseReg(); + } + break; case PPCISD::CALL: { const Module *M = MF->getFunction().getParent();