diff options
author | Stefan Pintilie <stefanp@ca.ibm.com> | 2021-05-13 09:58:59 -0500 |
---|---|---|
committer | Stefan Pintilie <stefanp@ca.ibm.com> | 2021-05-13 12:54:44 -0500 |
commit | 54310fc176fde539b15f3cc95d4a3555df446ff6 (patch) | |
tree | c2bc626c83352d8ec76d422683500aa1c705aec6 /llvm/lib | |
parent | 50e0b2985e43baf61617c9734df71e949113f911 (diff) | |
download | llvm-54310fc176fde539b15f3cc95d4a3555df446ff6.zip llvm-54310fc176fde539b15f3cc95d4a3555df446ff6.tar.gz llvm-54310fc176fde539b15f3cc95d4a3555df446ff6.tar.bz2 |
[PowerPC] Add ROP Protection to prologue and epilogue
Added hashst to the prologue and hashchk to the epilogue.
The hash for the prologue and epilogue must always be stored as the first
element in the local variable space on the stack.
Reviewed By: nemanjai, #powerpc
Differential Revision: https://reviews.llvm.org/D99377
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | 56 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h | 10 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCRegisterInfo.h | 4 |
5 files changed, 81 insertions, 8 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp index 0bebfc3..ab07edc 100644 --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -642,6 +642,8 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF, bool HasFP = hasFP(MF); bool HasBP = RegInfo->hasBasePointer(MF); bool HasRedZone = isPPC64 || !isSVR4ABI; + bool HasROPProtect = Subtarget.hasROPProtect(); + bool HasPrivileged = Subtarget.hasPrivileged(); Register SPReg = isPPC64 ? PPC::X1 : PPC::R1; Register BPReg = RegInfo->getBaseRegister(MF); @@ -672,6 +674,8 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF, const MCInstrDesc &MoveFromCondRegInst = TII.get(isPPC64 ? PPC::MFCR8 : PPC::MFCR); const MCInstrDesc &StoreWordInst = TII.get(isPPC64 ? PPC::STW8 : PPC::STW); + const MCInstrDesc &HashST = + TII.get(HasPrivileged ? PPC::HASHSTP : PPC::HASHST); // Regarding this assert: Even though LR is saved in the caller's frame (i.e., // LROffset is positive), that slot is callee-owned. Because PPC32 SVR4 has no @@ -833,11 +837,34 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF, .addReg(SPReg); } - if (MustSaveLR) + // Generate the instruction to store the LR. In the case where ROP protection + // is required the register holding the LR should not be killed as it will be + // used by the hash store instruction. + if (MustSaveLR) { BuildMI(MBB, StackUpdateLoc, dl, StoreInst) - .addReg(ScratchReg, getKillRegState(true)) - .addImm(LROffset) - .addReg(SPReg); + .addReg(ScratchReg, getKillRegState(!HasROPProtect)) + .addImm(LROffset) + .addReg(SPReg); + + // Add the ROP protection Hash Store instruction. + // NOTE: This is technically a violation of the ABI. The hash can be saved + // up to 512 bytes into the Protected Zone. This can be outside of the + // initial 288 byte volatile program storage region in the Protected Zone. + // However, this restriction will be removed in an upcoming revision of the + // ABI. + if (HasROPProtect) { + const int SaveIndex = FI->getROPProtectionHashSaveIndex(); + const int ImmOffset = MFI.getObjectOffset(SaveIndex); + assert((ImmOffset <= -8 && ImmOffset >= -512) && + "ROP hash save offset out of range."); + assert(((ImmOffset & 0x7) == 0) && + "ROP hash save offset must be 8 byte aligned."); + BuildMI(MBB, StackUpdateLoc, dl, HashST) + .addReg(ScratchReg, getKillRegState(true)) + .addImm(ImmOffset) + .addReg(SPReg); + } + } if (MustSaveCR && !(SingleScratchReg && MustSaveLR)) { @@ -1528,6 +1555,8 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, bool HasFP = hasFP(MF); bool HasBP = RegInfo->hasBasePointer(MF); bool HasRedZone = Subtarget.isPPC64() || !Subtarget.isSVR4ABI(); + bool HasROPProtect = Subtarget.hasROPProtect(); + bool HasPrivileged = Subtarget.hasPrivileged(); Register SPReg = isPPC64 ? PPC::X1 : PPC::R1; Register BPReg = RegInfo->getBaseRegister(MF); @@ -1552,6 +1581,8 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, : PPC::LWZ); const MCInstrDesc& MoveToCRInst = TII.get( isPPC64 ? PPC::MTOCRF8 : PPC::MTOCRF); + const MCInstrDesc &HashChk = + TII.get(HasPrivileged ? PPC::HASHCHKP : PPC::HASHCHK); int LROffset = getReturnSaveOffset(); int FPOffset = 0; @@ -1820,8 +1851,23 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, dl, MoveToCRInst, MustSaveCRs[i]) .addReg(TempReg, getKillRegState(i == e-1)); - if (MustSaveLR) + if (MustSaveLR) { + // If ROP protection is required, an extra instruction is added to compute a + // hash and then compare it to the hash stored in the prologue. + if (HasROPProtect) { + const int SaveIndex = FI->getROPProtectionHashSaveIndex(); + const int ImmOffset = MFI.getObjectOffset(SaveIndex); + assert((ImmOffset <= -8 && ImmOffset >= -512) && + "ROP hash check location offset out of range."); + assert(((ImmOffset & 0x7) == 0) && + "ROP hash check location offset must be 8 byte aligned."); + BuildMI(MBB, StackUpdateLoc, dl, HashChk) + .addReg(ScratchReg) + .addImm(ImmOffset) + .addReg(SPReg); + } BuildMI(MBB, StackUpdateLoc, dl, MTLRInst).addReg(ScratchReg); + } // Callee pop calling convention. Pop parameter/linkage area. Used for tail // call optimization diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 65ebafd..66b8e7e 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -152,6 +152,15 @@ namespace { GlobalBaseReg = 0; Subtarget = &MF.getSubtarget<PPCSubtarget>(); PPCLowering = Subtarget->getTargetLowering(); + if (Subtarget->hasROPProtect()) { + // Create a place on the stack for the ROP Protection Hash. + // The ROP Protection Hash will always be 8 bytes and aligned to 8 + // bytes. + MachineFrameInfo &MFI = MF.getFrameInfo(); + PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); + const int Result = MFI.CreateStackObject(8, Align(8), false); + FI->setROPProtectionHashSaveIndex(Result); + } SelectionDAGISel::runOnMachineFunction(MF); return true; diff --git a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h index 4b73b36..6a2de53 100644 --- a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h +++ b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h @@ -49,6 +49,9 @@ private: /// Frame index where the old PIC base pointer is stored. int PICBasePointerSaveIndex = 0; + /// Frame index where the ROP Protection Hash is stored. + int ROPProtectionHashSaveIndex = 0; + /// MustSaveLR - Indicates whether LR is defined (or clobbered) in the current /// function. This is only valid after the initial scan of the function by /// PEI. @@ -161,6 +164,13 @@ public: int getPICBasePointerSaveIndex() const { return PICBasePointerSaveIndex; } void setPICBasePointerSaveIndex(int Idx) { PICBasePointerSaveIndex = Idx; } + int getROPProtectionHashSaveIndex() const { + return ROPProtectionHashSaveIndex; + } + void setROPProtectionHashSaveIndex(int Idx) { + ROPProtectionHashSaveIndex = Idx; + } + unsigned getMinReservedArea() const { return MinReservedArea; } void setMinReservedArea(unsigned size) { MinReservedArea = size; } diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp index c8c396b..b27728a 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -433,6 +433,16 @@ bool PPCRegisterInfo::requiresFrameIndexScavenging(const MachineFunction &MF) co return false; } +bool PPCRegisterInfo::requiresVirtualBaseRegisters( + const MachineFunction &MF) const { + const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>(); + // Do not use virtual base registers when ROP protection is turned on. + // Virtual base registers break the layout of the local variable space and may + // push the ROP Hash location past the 512 byte range of the ROP store + // instruction. + return !Subtarget.hasROPProtect(); +} + bool PPCRegisterInfo::isCallerPreservedPhysReg(MCRegister PhysReg, const MachineFunction &MF) const { assert(Register::isPhysicalRegister(PhysReg)); diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h index 93f330a..dc29dd7 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h @@ -101,9 +101,7 @@ public: bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; - bool requiresVirtualBaseRegisters(const MachineFunction &MF) const override { - return true; - } + bool requiresVirtualBaseRegisters(const MachineFunction &MF) const override; void lowerDynamicAlloc(MachineBasicBlock::iterator II) const; void lowerDynamicAreaOffset(MachineBasicBlock::iterator II) const; |