Index: include/llvm/MC/MCExpr.h =================================================================== --- include/llvm/MC/MCExpr.h +++ include/llvm/MC/MCExpr.h @@ -264,6 +264,7 @@ VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_TLSLD, // symbol@tlsld VK_PPC_LOCAL, // symbol@local + VK_PPC_SECURE_PLT, // symbol+32768@plt VK_COFF_IMGREL32, // symbol@imgrel (image-relative) Index: lib/MC/MCExpr.cpp =================================================================== --- lib/MC/MCExpr.cpp +++ lib/MC/MCExpr.cpp @@ -198,6 +198,7 @@ case VK_NTPOFF: return "NTPOFF"; case VK_GOTNTPOFF: return "GOTNTPOFF"; case VK_PLT: return "PLT"; + case VK_PPC_SECURE_PLT: return "PLT"; case VK_TLSGD: return "TLSGD"; case VK_TLSLD: return "TLSLD"; case VK_TLSLDM: return "TLSLDM"; @@ -409,8 +410,11 @@ void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const { if (UseParensForSymbolVariant) OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')'; - else + else { + if (getKind() == VK_PPC_SECURE_PLT) + OS << "+32768"; OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind()); + } } /* *** */ 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,66 @@ // 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()) { + TmpInst.setOpcode(PPC::ADDIS); + const MCExpr *Exp = + MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")), + OutContext); + const MCExpr *PBha = + MCSymbolRefExpr::create(MF->getPICBaseSymbol(), + MCSymbolRefExpr::VK_PPC_HA, + OutContext); + const MCExpr *PBl = + MCSymbolRefExpr::create(MF->getPICBaseSymbol(), + MCSymbolRefExpr::VK_PPC_LO, + OutContext); + 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.getOperand(2) = + MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PBha, OutContext)); + TmpInst.getOperand(0) = PICR; + TmpInst.getOperand(1) = PICR; + EmitToStreamer(*OutStreamer, TmpInst); + + TmpInst.setOpcode(PPC::ADDI); + TmpInst.getOperand(2) = + MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PBl, OutContext)); + TmpInst.getOperand(0) = PICR; + TmpInst.getOperand(1) = PICR; + EmitToStreamer(*OutStreamer, TmpInst); + 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); - TmpInst.setOpcode(PPC::ADD4); - TmpInst.getOperand(0) = PICR; - TmpInst.getOperand(1) = TR; - TmpInst.getOperand(2) = PICR; - EmitToStreamer(*OutStreamer, TmpInst); - return; + // 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 Index: lib/Target/PowerPC/PPCMCInstLower.cpp =================================================================== --- lib/Target/PowerPC/PPCMCInstLower.cpp +++ lib/Target/PowerPC/PPCMCInstLower.cpp @@ -107,8 +107,17 @@ break; } - if (MO.getTargetFlags() == PPCII::MO_PLT) - RefKind = MCSymbolRefExpr::VK_PLT; + if (MO.getTargetFlags() == PPCII::MO_PLT) { + const MachineFunction *MF = MO.getParent()->getParent()->getParent(); + const PPCSubtarget *Subtarget = &(MF->getSubtarget()); + const TargetMachine &TM = Printer.TM; + + // -msecure-plt option works only in PIC mode. + if (Subtarget->isSecurePlt() && TM.isPositionIndependent()) + RefKind = MCSymbolRefExpr::VK_PPC_SECURE_PLT; + else + RefKind = MCSymbolRefExpr::VK_PLT; + } const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); 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,20 @@ +; 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 + +@.str = private unnamed_addr constant [14 x i8] c"\0AHello World\0A\00", align 1 + +define void @foo() { +entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i32 0, i32 0)) + ret void +} + +declare i32 @printf(i8*, ...) + +; CHECK-LABEL: foo: +; SECURE-PLT: addis 30, 30, .LTOC-.L0$pb@ha +; SECURE-PLT: addi 30, 30, .LTOC-.L0$pb@l +; SECURE-PLT: bl printf+32768@PLT +; 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 printf+32768@PLT \ No newline at end of file