[PPC32] Support PLT calls for -msecure-plt -fpic
authorFangrui Song <maskray@google.com>
Tue, 25 Jun 2019 15:56:32 +0000 (15:56 +0000)
committerFangrui Song <maskray@google.com>
Tue, 25 Jun 2019 15:56:32 +0000 (15:56 +0000)
Summary:
In Secure PLT ABI, -fpic is similar to -fPIC. The differences are that:

* -fpic stores the address of _GLOBAL_OFFSET_TABLE_ in r30, while -fPIC stores .got2+0x8000.
* -fpic uses an addend of 0 for R_PPC_PLTREL24, while -fPIC uses 0x8000.

Reviewers: hfinkel, jhibbits, joerg, nemanjai, spetrovic

Reviewed By: jhibbits

Subscribers: adalava, kbarton, jsji, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D63563

llvm-svn: 364324

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
llvm/test/CodeGen/PowerPC/ppc32-pic.ll
llvm/test/CodeGen/PowerPC/ppc32-secure-plt-tls2.ll [new file with mode: 0644]

index 464e9331f5d42e667720ba2a3e305f7965834a5d..0d8c848b5edd27e7503b82f6ec4adaa77148ce62 100644 (file)
@@ -461,6 +461,7 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
   StringRef Name = "__tls_get_addr";
   MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol(Name);
   MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
+  const Module *M = MF->getFunction().getParent();
 
   assert(MI->getOperand(0).isReg() &&
          ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||
@@ -478,10 +479,10 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
     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);
+  if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt() &&
+      M->getPICLevel() == PICLevel::BigPIC)
+    TlsRef = MCBinaryExpr::createAdd(
+        TlsRef, MCConstantExpr::create(32768, OutContext), OutContext);
   const MachineOperand &MO = MI->getOperand(2);
   const GlobalValue *GValue = MO.getGlobal();
   MCSymbol *MOSymbol = getSymbol(GValue);
@@ -583,34 +584,30 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
     // 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
+    //       addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha
+    //       addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l
     // Get the offset from the GOT Base Register to the GOT
     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
     if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
       unsigned PICR = TmpInst.getOperand(0).getReg();
-      MCSymbol *LTOCSymbol = OutContext.getOrCreateSymbol(StringRef(".LTOC"));
+      MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
+          M->getPICLevel() == PICLevel::SmallPIC ? "_GLOBAL_OFFSET_TABLE_"
+                                                 : ".LTOC");
       const MCExpr *PB =
-        MCSymbolRefExpr::create(MF->getPICBaseSymbol(),
-                                OutContext);
+          MCSymbolRefExpr::create(MF->getPICBaseSymbol(), OutContext);
 
-      const MCExpr *LTOCDeltaExpr =
-        MCBinaryExpr::createSub(MCSymbolRefExpr::create(LTOCSymbol, OutContext),
-                                PB, OutContext);
+      const MCExpr *DeltaExpr = MCBinaryExpr::createSub(
+          MCSymbolRefExpr::create(BaseSymbol, OutContext), PB, OutContext);
 
-      const MCExpr *LTOCDeltaHi =
-        PPCMCExpr::createHa(LTOCDeltaExpr, false, OutContext);
-      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
-                                   .addReg(PICR)
-                                   .addReg(PICR)
-                                   .addExpr(LTOCDeltaHi));
+      const MCExpr *DeltaHi = PPCMCExpr::createHa(DeltaExpr, false, OutContext);
+      EmitToStreamer(
+          *OutStreamer,
+          MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));
 
-      const MCExpr *LTOCDeltaLo =
-        PPCMCExpr::createLo(LTOCDeltaExpr, false, OutContext);
-      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
-                                   .addReg(PICR)
-                                   .addReg(PICR)
-                                   .addExpr(LTOCDeltaLo));
+      const MCExpr *DeltaLo = PPCMCExpr::createLo(DeltaExpr, false, OutContext);
+      EmitToStreamer(
+          *OutStreamer,
+          MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));
       return;
     } else {
       MCSymbol *PICOffset =
index 5a7dfedd49dd77368704e81710202d29dbd92315..543cac075f550733fdb7cf1d04c5fba38616017f 100644 (file)
@@ -439,7 +439,8 @@ SDNode *PPCDAGToDAGISel::getGlobalBaseReg() {
     if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) == MVT::i32) {
       if (PPCSubTarget->isTargetELF()) {
         GlobalBaseReg = PPC::R30;
-        if (M->getPICLevel() == PICLevel::SmallPIC) {
+        if (!PPCSubTarget->isSecurePlt() &&
+            M->getPICLevel() == PICLevel::SmallPIC) {
           BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MoveGOTtoLR));
           BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg);
           MF->getInfo<PPCFunctionInfo>()->setUsesPICBase(true);
@@ -4395,11 +4396,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
     getGlobalBaseReg();
   } break;
   case PPCISD::CALL: {
-    const Module *M = MF->getFunction().getParent();
-
     if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 ||
-        (!TM.isPositionIndependent() || !PPCSubTarget->isSecurePlt()) ||
-        !PPCSubTarget->isTargetELF() || M->getPICLevel() == PICLevel::SmallPIC)
+        !TM.isPositionIndependent() || !PPCSubTarget->isSecurePlt() ||
+        !PPCSubTarget->isTargetELF())
       break;
 
     SDValue Op = N->getOperand(1);
index 858dc0b2940e53bd311777c9b15410abdab295d5..027e6bd1ba06c1469e84be7a49b649c134c2fd8c 100644 (file)
@@ -110,16 +110,16 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
     RefKind = MCSymbolRefExpr::VK_PLT;
 
   const MachineFunction *MF = MO.getParent()->getParent()->getParent();
+  const Module *M = MF->getFunction().getParent();
   const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>());
   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 -msecure-plt -fPIC, add 32768 to symbol.
   if (Subtarget->isSecurePlt() && TM.isPositionIndependent() &&
+      M->getPICLevel() == PICLevel::BigPIC &&
       MO.getTargetFlags() == PPCII::MO_PLT)
-    Expr = MCBinaryExpr::createAdd(Expr,
-                                   MCConstantExpr::create(32768, Ctx),
-                                   Ctx);
+    Expr =
+        MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx);
 
   if (!MO.isJTI() && MO.getOffset())
     Expr = MCBinaryExpr::createAdd(Expr,
index 79c36b07e4908d19ab45dc5c47ee2b9884278f5e..63a62727de3fabb02a7e076035eb163db285e4f7 100644 (file)
@@ -1,4 +1,7 @@
-; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -relocation-model=pic | FileCheck -check-prefix=SMALL-BSS %s
+; RUN: llc < %s -mtriple=powerpc -relocation-model=pic | \
+; RUN:    FileCheck -check-prefixes=SMALL,SMALL-BSS %s
+; RUN: llc < %s -mtriple=powerpc -relocation-model=pic -mattr=+secure-plt | \
+; RUN:    FileCheck -check-prefixes=SMALL,SMALL-SECUREPLT %s
 @bar = common global i32 0, align 4
 
 declare i32 @call_foo(i32, ...)
@@ -12,13 +15,16 @@ entry:
 
 !llvm.module.flags = !{!0}
 !0 = !{i32 1, !"PIC Level", i32 1}
-; SMALL-BSS-LABEL:foo:
-; SMALL-BSS:         stwu 1, -32(1)
-; SMALL-BSS:         stw 30, 24(1)
-; SMALL-BSS:         bl _GLOBAL_OFFSET_TABLE_@local-4
-; SMALL-BSS:         mflr 30
-; SMALL-BSS-DAG:     stw {{[0-9]+}}, 8(1)
-; SMALL-BSS-DAG:     lwz [[VREG:[0-9]+]], bar@GOT(30)
-; SMALL-BSS-DAG:     lwz {{[0-9]+}}, 0([[VREG]])
-; SMALL-BSS:         bl call_foo@PLT
-; SMALL-BSS:         lwz 30, 24(1)
+; SMALL-LABEL: foo:
+; SMALL:         stwu 1, -32(1)
+; SMALL:         stw 30, 24(1)
+; SMALL-BSS:     bl _GLOBAL_OFFSET_TABLE_@local-4
+; SMALL-SECURE:  bl .L0$pb
+; SMALL:         mflr 30
+; SMALL-SECURE:  addis 30, 30, _GLOBAL_OFFSET_TABLE_-.Lo$pb@ha
+; SMALL-SECURE:  addi 30, 30, _GLOBAL_OFFSET_TABLE_-.Lo$pb@l
+; SMALL-DAG:     stw {{[0-9]+}}, 8(1)
+; SMALL-DAG:     lwz [[VREG:[0-9]+]], bar@GOT(30)
+; SMALL-DAG:     lwz {{[0-9]+}}, 0([[VREG]])
+; SMALL:         bl call_foo@PLT{{$}}
+; SMALL:         lwz 30, 24(1)
diff --git a/llvm/test/CodeGen/PowerPC/ppc32-secure-plt-tls2.ll b/llvm/test/CodeGen/PowerPC/ppc32-secure-plt-tls2.ll
new file mode 100644 (file)
index 0000000..38ebf99
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: llc < %s -mtriple=powerpc -mattr=+secure-plt -relocation-model=pic | FileCheck -check-prefix=SECURE-PLT-TLS %s
+
+@a = thread_local local_unnamed_addr global i32 6, align 4
+define i32 @main() local_unnamed_addr #0 {
+entry:
+  %0 = load i32, i32* @a, align 4
+  ret i32 %0
+}
+
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 7, !"PIC Level", i32 1}
+
+; SECURE-PLT-TLS:       mflr 30
+; SECURE-PLT-TLS-NEXT:  addis 30, 30, _GLOBAL_OFFSET_TABLE_-.L0$pb@ha
+; SECURE-PLT-TLS-NEXT:  addi 30, 30, _GLOBAL_OFFSET_TABLE_-.L0$pb@l
+; SECURE-PLT-TLS:       addi 3, 30, a@got@tlsgd
+; SECURE-PLT-TLS:       bl __tls_get_addr(a@tlsgd)@PLT{{$}}