summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lib/CodeGen')
-rw-r--r--gnu/llvm/lib/CodeGen/CMakeLists.txt1
-rw-r--r--gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp40
-rw-r--r--gnu/llvm/lib/CodeGen/ReturnProtectorPass.cpp61
-rw-r--r--gnu/llvm/lib/CodeGen/TargetPassConfig.cpp2
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());