Index: lib/Target/PowerPC/PPC.td =================================================================== --- lib/Target/PowerPC/PPC.td +++ lib/Target/PowerPC/PPC.td @@ -119,6 +119,8 @@ [FeatureBookE]>; def FeatureE500 : SubtargetFeature<"e500", "IsE500", "true", "Enable E500/E500mc instructions">; +def FeatureSecurePlt : SubtargetFeature<"secure-plt","SecurePlt", "true", + "Enable secure plt mode">; def FeaturePPC4xx : SubtargetFeature<"ppc4xx", "IsPPC4xx", "true", "Enable PPC 4xx instructions">; def FeaturePPC6xx : SubtargetFeature<"ppc6xx", "IsPPC6xx", "true", Index: lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- lib/Target/PowerPC/PPCAsmPrinter.cpp +++ lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -563,33 +563,63 @@ // Transform %rd = UpdateGBR(%rt, %ri) // Into: lwz %rt, .L0$poff - .L0$pb(%ri) // add %rd, %rt, %ri + // or into (if secure plt mode is on): + // addis r30, r30, .LTOC - .L0$pb@ha + // addi r30, r30, .LTOC - .L0$pb@l // Get the offset from the GOT Base Register to the GOT LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin); - MCSymbol *PICOffset = - MF->getInfo()->getPICOffsetSymbol(); - TmpInst.setOpcode(PPC::LWZ); - const MCExpr *Exp = - MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); - const MCExpr *PB = - MCSymbolRefExpr::create(MF->getPICBaseSymbol(), - MCSymbolRefExpr::VK_None, - OutContext); - const MCOperand TR = TmpInst.getOperand(1); - const MCOperand PICR = TmpInst.getOperand(0); + if (Subtarget->isSecurePlt() && isPositionIndependent() ) { + unsigned PICR = TmpInst.getOperand(0).getReg(); + MCSymbol *LTOCSymbol = OutContext.getOrCreateSymbol(StringRef(".LTOC")); + const MCExpr *PB = + MCSymbolRefExpr::create(MF->getPICBaseSymbol(), + OutContext); - // Step 1: lwz %rt, .L$poff - .L$pb(%ri) - TmpInst.getOperand(1) = - MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext)); - TmpInst.getOperand(0) = TR; - TmpInst.getOperand(2) = PICR; - EmitToStreamer(*OutStreamer, TmpInst); + const MCExpr *LTOCDeltaExpr = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(LTOCSymbol, OutContext), + PB, OutContext); - TmpInst.setOpcode(PPC::ADD4); - TmpInst.getOperand(0) = PICR; - TmpInst.getOperand(1) = TR; - TmpInst.getOperand(2) = PICR; - EmitToStreamer(*OutStreamer, TmpInst); - return; + const MCExpr *LTOCDeltaHi = + PPCMCExpr::createHa(LTOCDeltaExpr, false, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS) + .addReg(PICR) + .addReg(PICR) + .addExpr(LTOCDeltaHi)); + + const MCExpr *LTOCDeltaLo = + PPCMCExpr::createLo(LTOCDeltaExpr, false, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI) + .addReg(PICR) + .addReg(PICR) + .addExpr(LTOCDeltaLo)); + return; + } else { + MCSymbol *PICOffset = + MF->getInfo()->getPICOffsetSymbol(); + TmpInst.setOpcode(PPC::LWZ); + const MCExpr *Exp = + MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); + const MCExpr *PB = + MCSymbolRefExpr::create(MF->getPICBaseSymbol(), + MCSymbolRefExpr::VK_None, + OutContext); + const MCOperand TR = TmpInst.getOperand(1); + const MCOperand PICR = TmpInst.getOperand(0); + + // Step 1: lwz %rt, .L$poff - .L$pb(%ri) + TmpInst.getOperand(1) = + MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext)); + TmpInst.getOperand(0) = TR; + TmpInst.getOperand(2) = PICR; + EmitToStreamer(*OutStreamer, TmpInst); + + TmpInst.setOpcode(PPC::ADD4); + TmpInst.getOperand(0) = PICR; + TmpInst.getOperand(1) = TR; + TmpInst.getOperand(2) = PICR; + EmitToStreamer(*OutStreamer, TmpInst); + return; + } } case PPC::LWZtoc: { // Transform %r3 = LWZtoc @min1, %r2 @@ -1233,7 +1263,7 @@ if (!Subtarget->isPPC64()) { const PPCFunctionInfo *PPCFI = MF->getInfo(); - if (PPCFI->usesPICBase()) { + if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) { MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(); MCSymbol *PICBase = MF->getPICBaseSymbol(); OutStreamer->EmitLabel(RelocSymbol); Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -3904,6 +3904,27 @@ return; break; + case PPCISD::CALL: { + const Module *M = MF->getFunction().getParent(); + + if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 || + !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() || + M->getPICLevel() == PICLevel::SmallPIC) + break; + + SDValue Op = N->getOperand(1); + + if (GlobalAddressSDNode *GA = dyn_cast(Op)) { + if (GA->getTargetFlags() == PPCII::MO_PLT) + getGlobalBaseReg(); + } + else if (ExternalSymbolSDNode *ES = dyn_cast(Op)) { + if (ES->getTargetFlags() == PPCII::MO_PLT) + getGlobalBaseReg(); + } + } + break; + case PPCISD::GlobalBaseReg: ReplaceNode(N, getGlobalBaseReg()); return; Index: lib/Target/PowerPC/PPCMCInstLower.cpp =================================================================== --- lib/Target/PowerPC/PPCMCInstLower.cpp +++ lib/Target/PowerPC/PPCMCInstLower.cpp @@ -107,10 +107,20 @@ break; } - if (MO.getTargetFlags() == PPCII::MO_PLT) + if (MO.getTargetFlags() == PPCII::MO_PLT) RefKind = MCSymbolRefExpr::VK_PLT; + const MachineFunction *MF = MO.getParent()->getParent()->getParent(); + const PPCSubtarget *Subtarget = &(MF->getSubtarget()); + const TargetMachine &TM = Printer.TM; const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); + // -msecure-plt option works only in PIC mode. If secure plt mode + // is on add 32768 to symbol. + if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && + MO.getTargetFlags() == PPCII::MO_PLT) + Expr = MCBinaryExpr::createAdd(Expr, + MCConstantExpr::create(32768, Ctx), + Ctx); if (!MO.isJTI() && MO.getOffset()) Expr = MCBinaryExpr::createAdd(Expr, Index: lib/Target/PowerPC/PPCSubtarget.h =================================================================== --- lib/Target/PowerPC/PPCSubtarget.h +++ lib/Target/PowerPC/PPCSubtarget.h @@ -133,6 +133,7 @@ bool HasFloat128; bool IsISA3_0; bool UseLongCalls; + bool SecurePlt; POPCNTDKind HasPOPCNTD; @@ -255,6 +256,7 @@ bool hasOnlyMSYNC() const { return HasOnlyMSYNC; } bool isPPC4xx() const { return IsPPC4xx; } bool isPPC6xx() const { return IsPPC6xx; } + bool isSecurePlt() const {return SecurePlt; } bool isE500() const { return IsE500; } bool isFeatureMFTB() const { return FeatureMFTB; } bool isDeprecatedDST() const { return DeprecatedDST; } Index: test/CodeGen/PowerPC/ppc32-pic-large.ll =================================================================== --- test/CodeGen/PowerPC/ppc32-pic-large.ll +++ test/CodeGen/PowerPC/ppc32-pic-large.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -relocation-model=pic | FileCheck -check-prefix=LARGE-BSS %s +; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -mattr=+secure-plt -relocation-model=pic | FileCheck -check-prefix=LARGE-SECUREPLT %s @bar = common global i32 0, align 4 declare i32 @call_foo(i32, ...) @@ -29,3 +30,6 @@ ; LARGE-BSS: [[VREF]]: ; LARGE-BSS-NEXT: .p2align 2 ; LARGE-BSS-NEXT: .long bar +; LARGE-SECUREPLT: addis 30, 30, .LTOC-.L0$pb@ha +; LARGE-SECUREPLT: addi 30, 30, .LTOC-.L0$pb@l +; LARGE-SECUREPLT: bl call_foo@PLT+32768