diff options
Diffstat (limited to 'gnu/llvm/lib/CodeGen')
| -rw-r--r-- | gnu/llvm/lib/CodeGen/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp | 40 | ||||
| -rw-r--r-- | gnu/llvm/lib/CodeGen/ReturnProtectorPass.cpp | 61 | ||||
| -rw-r--r-- | gnu/llvm/lib/CodeGen/TargetPassConfig.cpp | 2 |
4 files changed, 102 insertions, 2 deletions
diff --git a/gnu/llvm/lib/CodeGen/CMakeLists.txt b/gnu/llvm/lib/CodeGen/CMakeLists.txt index 865de4f47af..42e91978782 100644 --- a/gnu/llvm/lib/CodeGen/CMakeLists.txt +++ b/gnu/llvm/lib/CodeGen/CMakeLists.txt @@ -120,6 +120,7 @@ add_llvm_library(LLVMCodeGen RegUsageInfoCollector.cpp RegUsageInfoPropagate.cpp ResetMachineFunctionPass.cpp + ReturnProtectorPass.cpp SafeStack.cpp SafeStackColoring.cpp SafeStackLayout.cpp diff --git a/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp index a8d8ad8ac7d..529fa7406a5 100644 --- a/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -175,6 +175,10 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); + // Set Return Protector in the frame + if (F.hasFnAttribute("ret-protector")) + Fn.getFrameInfo().setReturnProtector(true); + RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : nullptr; FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); FrameIndexEliminationScavenging = (RS && !FrameIndexVirtualScavenging) || @@ -209,6 +213,19 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { if (!F.hasFnAttribute(Attribute::Naked)) insertPrologEpilogCode(Fn); + // Add Return Protectors if using them + if (Fn.getFrameInfo().hasReturnProtector()) { + std::vector<MachineBasicBlock *> ReturnBlocks; + bool insertedGuard = false; + for (auto &MBB: Fn) + if (MBB.isReturnBlock()) + ReturnBlocks.push_back(&MBB); + for (MachineBasicBlock *MBB: ReturnBlocks) + insertedGuard |= TFI->insertReturnProtectorEpilogue(Fn, *MBB); + if (insertedGuard) + TFI->insertReturnProtectorPrologue(Fn, Fn.front()); + } + // Replace all MO_FrameIndex operands with physical register references // and actual offsets. // @@ -293,7 +310,8 @@ void PEI::calculateCallFrameInfo(MachineFunction &Fn) { /// Compute the sets of entry and return blocks for saving and restoring /// callee-saved registers, and placing prolog and epilog code. void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) { - const MachineFrameInfo &MFI = Fn.getFrameInfo(); + MachineFrameInfo &MFI = Fn.getFrameInfo(); + const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); // Even when we do not change any CSR, we still want to insert the // prologue and epilogue of the function. @@ -309,7 +327,18 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) { // epilogue. if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock()) RestoreBlocks.push_back(RestoreBlock); - return; + + // If we are adding return protectors ensure we can find a free register + if (MFI.hasReturnProtector() && + !TFI->determineReturnProtectorTempRegister(Fn, SaveBlocks, RestoreBlocks)) { + // Shrinkwrapping will prevent finding a free register + SaveBlocks.clear(); + RestoreBlocks.clear(); + MFI.setSavePoint(nullptr); + MFI.setRestorePoint(nullptr); + } else { + return; + } } // Save refs to entry and return blocks. @@ -320,6 +349,9 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) { if (MBB.isReturnBlock()) RestoreBlocks.push_back(&MBB); } + + if (MFI.hasReturnProtector()) + TFI->determineReturnProtectorTempRegister(Fn, SaveBlocks, RestoreBlocks); } static void assignCalleeSavedSpillSlots(MachineFunction &F, @@ -341,6 +373,10 @@ static void assignCalleeSavedSpillSlots(MachineFunction &F, const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); MachineFrameInfo &MFI = F.getFrameInfo(); + + if (MFI.hasReturnProtectorTempRegister()) + CSI.push_back(CalleeSavedInfo(MFI.getReturnProtectorTempRegister())); + if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) { // If target doesn't implement this, use generic code. diff --git a/gnu/llvm/lib/CodeGen/ReturnProtectorPass.cpp b/gnu/llvm/lib/CodeGen/ReturnProtectorPass.cpp new file mode 100644 index 00000000000..c4f8cb4f1b1 --- /dev/null +++ b/gnu/llvm/lib/CodeGen/ReturnProtectorPass.cpp @@ -0,0 +1,61 @@ +//===- ReturnProtectorPass.cpp - Set up rteurn protectors -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass sets up functions for return protectors. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "return-protector" + +STATISTIC(NumSymbols, "Counts number of cookie symbols added"); + +namespace { + struct ReturnProtector : public FunctionPass { + static char ID; + ReturnProtector() : FunctionPass(ID) {} + + bool runOnFunction(Function &F) override { + if (F.hasFnAttribute("ret-protector")) { + // Create a symbol for the cookie + Module *M = F.getParent(); + std::hash<std::string> hasher; + std::string cookiename = "__retguard_" + std::to_string(hasher((M->getName() + F.getName()).str()) % 4000); + Type *cookietype = Type::getInt8PtrTy(M->getContext()); + GlobalVariable *cookie = dyn_cast_or_null<GlobalVariable>( + M->getOrInsertGlobal(cookiename, cookietype)); + cookie->setInitializer(Constant::getNullValue(cookietype)); + cookie->setLinkage(GlobalVariable::WeakAnyLinkage); + cookie->setVisibility(GlobalValue::HiddenVisibility); + cookie->setSection(".openbsd.randomdata"); + cookie->setExternallyInitialized(true); + F.addFnAttr("ret-protector-cookie", cookiename); + NumSymbols++; + } + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + } + }; +} + +char ReturnProtector::ID = 0; +INITIALIZE_PASS(ReturnProtector, "return-protector", "Return Protector Pass", + false, false) +FunctionPass *llvm::createReturnProtectorPass() { return new ReturnProtector(); } + diff --git a/gnu/llvm/lib/CodeGen/TargetPassConfig.cpp b/gnu/llvm/lib/CodeGen/TargetPassConfig.cpp index 3e6ad3eeef0..04f60eca18b 100644 --- a/gnu/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/gnu/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -688,6 +688,8 @@ void TargetPassConfig::addISelPrepare() { if (requiresCodeGenSCCOrder()) addPass(new DummyCGSCCPass); + addPass(createReturnProtectorPass()); + // Add both the safe stack and the stack protection passes: each of them will // only protect functions that have corresponding attributes. addPass(createSafeStackPass()); |
