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/secure-plt.ll =================================================================== --- test/CodeGen/PowerPC/secure-plt.ll +++ test/CodeGen/PowerPC/secure-plt.ll @@ -0,0 +1,46 @@ +; RUN: llc -mtriple=powerpc-unknown-linux-gnu -O2 -mattr=+secure-plt -relocation-model=pic %s -o - | FileCheck %s -check-prefix=SECURE-PLT +; RUN: llc -mtriple=powerpc-unknown-linux-gnu -O2 -relocation-model=pic %s -o - | FileCheck %s -check-prefix=NO-SECURE-PLT + + +; int a; +; int foo1(int a); +; int foo() { +; return bar(); +; } +; int func() { +; return foo1(a); +; } + +@a = common global i32 0, align 4 + +define i32 @foo() #0 { +entry: + %call = call i32 bitcast (i32 (...)* @bar to i32 ()*)() + ret i32 %call +} + +declare i32 @bar(...) #1 + +define i32 @func() #0 { +entry: + %0 = load i32, i32* @a, align 4 + %call = call i32 @foo1(i32 %0) + ret i32 %call +} + +declare i32 @foo1(i32) #1 + +; CHECK-LABEL: foo: +; SECURE-PLT: addis 30, 30, .LTOC-.L0$pb@ha +; SECURE-PLT: addi 30, 30, .LTOC-.L0$pb@l +; SECURE-PLT: bl bar@PLT+32768 +; NO-SECURE-PLT-NOT: addis 30, 30, .LTOC-.L0$pb@ha +; NO-SECURE-PLT-NOT: addi 30, 30, .LTOC-.L0$pb@l +; NO-SECURE-PLT-NOT: bl bar@PLT+32768 +; CHECK-LABEL:func: +; SECURE-PLT: addis 30, 30, .LTOC-.L1$pb@ha +; SECURE-PLT: addi 30, 30, .LTOC-.L1$pb@l +; SECURE-PLT: bl foo1@PLT+32768 +; NO-SECURE-PLT-NOT: addis 30, 30, .LTOC-.L1$pb@ha +; NO-SECURE-PLT-NOT: addi 30, 30, .LTOC-.L1$pb@l +; NO-SECURE-PLT-NOT: bl foo1@PLT+32768 \ No newline at end of file