summaryrefslogtreecommitdiff
path: root/gnu/llvm
diff options
context:
space:
mode:
authormortimer <mortimer@cvs.openbsd.org>2018-08-12 16:59:32 +0000
committermortimer <mortimer@cvs.openbsd.org>2018-08-12 16:59:32 +0000
commita466ca26e9d453aaeb0c4de1551426d89a376cf9 (patch)
tree7e3f6e14eb7eda982aaefe1136c2e9c2d59cb306 /gnu/llvm
parente34416cdb4ab34920fd178243b0cf8601f7a8b59 (diff)
Refactor retguard to make adding additional arches easier.
Diffstat (limited to 'gnu/llvm')
-rw-r--r--gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h24
-rw-r--r--gnu/llvm/include/llvm/CodeGen/ReturnProtectorLowering.h78
-rw-r--r--gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h19
-rw-r--r--gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp32
-rw-r--r--gnu/llvm/lib/CodeGen/ReturnProtectorLowering.cpp177
-rw-r--r--gnu/llvm/lib/Target/X86/X86FrameLowering.cpp200
-rw-r--r--gnu/llvm/lib/Target/X86/X86FrameLowering.h16
-rw-r--r--gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.cpp118
-rw-r--r--gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.h45
9 files changed, 454 insertions, 255 deletions
diff --git a/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h
index ad18d16ee70..f506dfb4b76 100644
--- a/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -237,10 +237,12 @@ class MachineFrameInfo {
/// The frame index for the stack protector.
int StackProtectorIdx = -1;
- /// The register to use for the return protector temp register
- unsigned ReturnProtectorTempRegister = 0;
- /// Set to true if using return protectors
- bool ReturnProtector = false;
+ struct ReturnProtector {
+ /// The register to use for return protector calculations
+ unsigned Register = 0;
+ /// Set to true if this function needs return protectors
+ bool Needed = false;
+ } RPI;
/// The frame index for the function context. Used for SjLj exceptions.
int FunctionContextIdx = -1;
@@ -319,13 +321,13 @@ public:
void setStackProtectorIndex(int I) { StackProtectorIdx = I; }
bool hasStackProtectorIndex() const { return StackProtectorIdx != -1; }
- /// Return the temporary register for the return protector cookie calculation
- int getReturnProtectorTempRegister() const { return ReturnProtectorTempRegister; }
- void setReturnProtectorTempRegister(unsigned I) { ReturnProtectorTempRegister = I; }
- bool hasReturnProtectorTempRegister() const { return ReturnProtectorTempRegister != 0; }
- /// Return the return protector level
- void setReturnProtector(bool I) { ReturnProtector = I; }
- bool hasReturnProtector() const { return ReturnProtector; }
+ /// Get / Set return protector calculation register
+ unsigned getReturnProtectorRegister() const { return RPI.Register; }
+ void setReturnProtectorRegister(unsigned I) { RPI.Register = I; }
+ bool hasReturnProtectorRegister() const { return RPI.Register != 0; }
+ /// Get / Set if this frame needs a return protector
+ void setReturnProtectorNeeded(bool I) { RPI.Needed = I; }
+ bool getReturnProtectorNeeded() const { return RPI.Needed; }
/// Return the index for the function context object.
/// This object is used for SjLj exceptions.
diff --git a/gnu/llvm/include/llvm/CodeGen/ReturnProtectorLowering.h b/gnu/llvm/include/llvm/CodeGen/ReturnProtectorLowering.h
new file mode 100644
index 00000000000..fb9ef0c908f
--- /dev/null
+++ b/gnu/llvm/include/llvm/CodeGen/ReturnProtectorLowering.h
@@ -0,0 +1,78 @@
+//===-- llvm/CodeGen/ReturnProtectorLowering.h ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A class to insert and lower the return protector instrumentation
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_RETURNPROTECTORLOWERING_H
+#define LLVM_CODEGEN_RETURNPROTECTORLOWERING_H
+
+#include "llvm/ADT/SmallVector.h"
+
+#include <utility>
+#include <vector>
+
+namespace llvm {
+class CalleeSavedInfo;
+class GlobalVariable;
+class MachineBasicBlock;
+class MachineFunction;
+class MachineInstr;
+
+class ReturnProtectorLowering {
+public:
+ /// Subclass interface - subclasses need to implement these functions.
+
+ /// insertReturnProtectorPrologue/Epilogue - insert return protector
+ /// instrumentation in prologue or epilogue.
+ virtual void insertReturnProtectorPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB,
+ GlobalVariable *cookie) const {}
+ virtual void insertReturnProtectorEpilogue(MachineFunction &MF,
+ MachineInstr &MI,
+ GlobalVariable *cookie) const {}
+
+ /// opcodeIsReturn - Reuturn true is the given opcode is a return
+ /// instruction needing return protection, false otherwise.
+ virtual bool opcodeIsReturn(unsigned opcode) const { return false; }
+
+ /// fillTempRegisters - Fill the list of available temp registers we can
+ /// use as a CalculationRegister.
+ virtual void fillTempRegisters(MachineFunction &MF,
+ std::vector<unsigned> &TempRegs) const {}
+
+ /// Generic public interface used by llvm
+
+ /// setupReturnProtector - Checks the function for ROP friendly return
+ /// instructions and sets ReturnProtectorNeeded in the frame if found.
+ virtual void setupReturnProtector(MachineFunction &MF) const;
+
+ /// saveReturnProtectorRegister - Allows the target to save the
+ /// CalculationRegister in the CalleeSavedInfo vector if needed.
+ virtual void
+ saveReturnProtectorRegister(const MachineFunction &MF,
+ std::vector<CalleeSavedInfo> &CSI) const;
+
+ /// determineReturnProtectorTempRegister - Find a register that can be used
+ /// during function prologue / epilogue to store the return protector cookie.
+ /// Returns false if a register is needed but could not be found,
+ /// otherwise returns true.
+ virtual bool determineReturnProtectorRegister(
+ MachineFunction &MF,
+ const SmallVector<MachineBasicBlock *, 4> &SaveBlocks,
+ const SmallVector<MachineBasicBlock *, 4> &RestoreBlocks) const;
+
+ /// insertReturnProtectors - insert return protector instrumentation.
+ virtual void insertReturnProtectors(MachineFunction &MF) const;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h
index e07aaddc076..30c4d01ef48 100644
--- a/gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h
+++ b/gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h
@@ -15,6 +15,7 @@
#define LLVM_CODEGEN_TARGETFRAMELOWERING_H
#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/ReturnProtectorLowering.h"
#include <utility>
#include <vector>
@@ -165,22 +166,8 @@ public:
virtual void emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const = 0;
- /// determineReturnProtectorTempRegister - Find a register that can be used
- /// during function prologue / epilogue to store the return protector cookie
- virtual bool determineReturnProtectorTempRegister(MachineFunction &MF,
- const SmallVector<MachineBasicBlock *, 4> &SaveBlocks,
- const SmallVector<MachineBasicBlock *, 4> &RestoreBlocks) const {
- return false;
- }
-
- /// insertReturnProtectorPrologue/Epilogue - Insert ret-protector code
- virtual void insertReturnProtectorPrologue(MachineFunction &MF,
- MachineBasicBlock &MBB) const
- {}
- virtual bool insertReturnProtectorEpilogue(MachineFunction &MF,
- MachineBasicBlock &MBB) const
- {
- return false;
+ virtual const ReturnProtectorLowering *getReturnProtector() const {
+ return nullptr;
}
/// Replace a StackProbe stub (if any) with the actual probe code inline
diff --git a/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 529fa7406a5..4517c3af031 100644
--- a/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -174,10 +174,10 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) {
const Function &F = Fn.getFunction();
const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo();
const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering();
+ const ReturnProtectorLowering *RPL = TFI->getReturnProtector();
- // Set Return Protector in the frame
- if (F.hasFnAttribute("ret-protector"))
- Fn.getFrameInfo().setReturnProtector(true);
+ if (RPL)
+ RPL->setupReturnProtector(Fn);
RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : nullptr;
FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn);
@@ -214,17 +214,8 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) {
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());
- }
+ if (RPL)
+ RPL->insertReturnProtectors(Fn);
// Replace all MO_FrameIndex operands with physical register references
// and actual offsets.
@@ -312,6 +303,7 @@ void PEI::calculateCallFrameInfo(MachineFunction &Fn) {
void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) {
MachineFrameInfo &MFI = Fn.getFrameInfo();
const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering();
+ const ReturnProtectorLowering *RPL = TFI->getReturnProtector();
// Even when we do not change any CSR, we still want to insert the
// prologue and epilogue of the function.
@@ -329,8 +321,8 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) {
RestoreBlocks.push_back(RestoreBlock);
// If we are adding return protectors ensure we can find a free register
- if (MFI.hasReturnProtector() &&
- !TFI->determineReturnProtectorTempRegister(Fn, SaveBlocks, RestoreBlocks)) {
+ if (RPL &&
+ !RPL->determineReturnProtectorRegister(Fn, SaveBlocks, RestoreBlocks)) {
// Shrinkwrapping will prevent finding a free register
SaveBlocks.clear();
RestoreBlocks.clear();
@@ -350,8 +342,8 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) {
RestoreBlocks.push_back(&MBB);
}
- if (MFI.hasReturnProtector())
- TFI->determineReturnProtectorTempRegister(Fn, SaveBlocks, RestoreBlocks);
+ if (RPL)
+ RPL->determineReturnProtectorRegister(Fn, SaveBlocks, RestoreBlocks);
}
static void assignCalleeSavedSpillSlots(MachineFunction &F,
@@ -374,8 +366,8 @@ 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->getReturnProtector())
+ TFI->getReturnProtector()->saveReturnProtectorRegister(F, CSI);
if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) {
// If target doesn't implement this, use generic code.
diff --git a/gnu/llvm/lib/CodeGen/ReturnProtectorLowering.cpp b/gnu/llvm/lib/CodeGen/ReturnProtectorLowering.cpp
new file mode 100644
index 00000000000..60ad3ede793
--- /dev/null
+++ b/gnu/llvm/lib/CodeGen/ReturnProtectorLowering.cpp
@@ -0,0 +1,177 @@
+//===- ReturnProtectorLowering.cpp - ---------------------------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements common routines for return protector support.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/ReturnProtectorLowering.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/IR/Function.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+
+using namespace llvm;
+
+static void markUsedRegsInSuccessors(MachineBasicBlock &MBB,
+ SmallSet<unsigned, 16> &Used,
+ SmallSet<int, 24> &Visited) {
+ int BBNum = MBB.getNumber();
+ if (Visited.count(BBNum))
+ return;
+
+ // Mark all the registers used
+ for (auto &MBBI : MBB.instrs()) {
+ for (auto &MBBIOp : MBBI.operands()) {
+ if (MBBIOp.isReg())
+ Used.insert(MBBIOp.getReg());
+ }
+ }
+
+ // Mark this MBB as visited
+ Visited.insert(BBNum);
+ // Recurse over all successors
+ for (auto &SuccMBB : MBB.successors())
+ markUsedRegsInSuccessors(*SuccMBB, Used, Visited);
+}
+
+/// setupReturnProtector - Checks the function for ROP friendly return
+/// instructions and sets ReturnProtectorNeeded if found.
+void ReturnProtectorLowering::setupReturnProtector(MachineFunction &MF) const {
+ if (MF.getFunction().hasFnAttribute("ret-protector")) {
+ for (auto &MBB : MF) {
+ for (auto &T : MBB.terminators()) {
+ if (opcodeIsReturn(T.getOpcode())) {
+ MF.getFrameInfo().setReturnProtectorNeeded(true);
+ return;
+ }
+ }
+ }
+ }
+}
+
+/// saveReturnProtectorRegister - Allows the target to save the
+/// ReturnProtectorRegister in the CalleeSavedInfo vector if needed.
+void ReturnProtectorLowering::saveReturnProtectorRegister(
+ const MachineFunction &MF, std::vector<CalleeSavedInfo> &CSI) const {
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ if (!MFI.getReturnProtectorNeeded())
+ return;
+
+ if (!MFI.hasReturnProtectorRegister())
+ llvm_unreachable("Saving unset return protector register");
+
+ CSI.push_back(CalleeSavedInfo(MFI.getReturnProtectorRegister()));
+}
+
+/// determineReturnProtectorTempRegister - Find a register that can be used
+/// during function prologue / epilogue to store the return protector cookie.
+/// Returns false if a register is needed but could not be found,
+/// otherwise returns true.
+bool ReturnProtectorLowering::determineReturnProtectorRegister(
+ MachineFunction &MF, const SmallVector<MachineBasicBlock *, 4> &SaveBlocks,
+ const SmallVector<MachineBasicBlock *, 4> &RestoreBlocks) const {
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ if (!MFI.getReturnProtectorNeeded())
+ return true;
+
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+
+ SmallSet<unsigned, 16> Used;
+ SmallSet<int, 24> Visited;
+
+ // CSR spills happen at the beginning of this block
+ // so we can mark it as visited because anything past it is safe
+ for (auto &SB : SaveBlocks)
+ Visited.insert(SB->getNumber());
+
+ // CSR Restores happen at the end of restore blocks, before any terminators,
+ // so we need to search restores for MBB terminators, and any successor BBs.
+ for (auto &RB : RestoreBlocks) {
+ for (auto &RBI : RB->terminators()) {
+ for (auto &RBIOp : RBI.operands()) {
+ if (RBIOp.isReg())
+ Used.insert(RBIOp.getReg());
+ }
+ }
+ for (auto &SuccMBB : RB->successors())
+ markUsedRegsInSuccessors(*SuccMBB, Used, Visited);
+ }
+
+ // Now we iterate from the front to find code paths that
+ // bypass save blocks and land on return blocks
+ markUsedRegsInSuccessors(MF.front(), Used, Visited);
+
+ // Now we have gathered all the regs used outside the frame save / restore,
+ // so we can see if we have a free reg to use for the retguard cookie.
+ std::vector<unsigned> TempRegs;
+ fillTempRegisters(MF, TempRegs);
+
+ for (unsigned Reg : TempRegs) {
+ bool canUse = true;
+ for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
+ if (Used.count(*AI)) {
+ // Reg is used somewhere, so we cannot use it
+ canUse = false;
+ break;
+ }
+ }
+ if (canUse) {
+ MFI.setReturnProtectorRegister(Reg);
+ break;
+ }
+ }
+
+ return MFI.hasReturnProtectorRegister();
+}
+
+/// insertReturnProtectors - insert return protector instrumentation.
+void ReturnProtectorLowering::insertReturnProtectors(
+ MachineFunction &MF) const {
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ if (!MFI.getReturnProtectorNeeded())
+ return;
+
+ if (!MFI.hasReturnProtectorRegister())
+ llvm_unreachable("Inconsistent return protector state.");
+
+ const Function &Fn = MF.getFunction();
+ const Module *M = Fn.getParent();
+ GlobalVariable *cookie =
+ dyn_cast_or_null<GlobalVariable>(M->getGlobalVariable(
+ Fn.getFnAttribute("ret-protector-cookie").getValueAsString(),
+ Type::getInt8PtrTy(M->getContext())));
+
+ if (!cookie)
+ llvm_unreachable("Function needs return protector but no cookie assigned");
+
+ std::vector<MachineInstr *> returns;
+ for (auto &MBB : MF) {
+ if (MBB.isReturnBlock()) {
+ for (auto &MI : MBB.terminators()) {
+ if (opcodeIsReturn(MI.getOpcode()))
+ returns.push_back(&MI);
+ }
+ }
+ }
+
+ if (returns.empty())
+ return;
+
+ for (auto &MI : returns)
+ insertReturnProtectorEpilogue(MF, *MI, cookie);
+
+ insertReturnProtectorPrologue(MF, MF.front(), cookie);
+}
diff --git a/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp b/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp
index e0a4b31b598..170cd09fb4b 100644
--- a/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -15,6 +15,7 @@
#include "X86InstrBuilder.h"
#include "X86InstrInfo.h"
#include "X86MachineFunctionInfo.h"
+#include "X86ReturnProtectorLowering.h"
#include "X86Subtarget.h"
#include "X86TargetMachine.h"
#include "llvm/ADT/SmallSet.h"
@@ -39,7 +40,7 @@ X86FrameLowering::X86FrameLowering(const X86Subtarget &STI,
unsigned StackAlignOverride)
: TargetFrameLowering(StackGrowsDown, StackAlignOverride,
STI.is64Bit() ? -8 : -4),
- STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {
+ STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()), RPL() {
// Cache a bunch of frame-related predicates for this subtarget.
SlotSize = TRI->getSlotSize();
Is64Bit = STI.is64Bit();
@@ -3060,199 +3061,6 @@ void X86FrameLowering::processFunctionBeforeFrameFinalized(
.addImm(-2);
}
-static void markUsedRegsInSuccessors(MachineBasicBlock &MBB,
- SmallSet<unsigned, 16> &Used,
- SmallSet<int, 24> &Visited) {
- int BBNum = MBB.getNumber();
- if (Visited.count(BBNum))
- return;
-
- // Mark all the registers used
- for (auto &MBBI : MBB.instrs())
- for (auto &MBBIOp : MBBI.operands())
- if (MBBIOp.isReg())
- Used.insert(MBBIOp.getReg());
- // Mark this MBB as visited
- Visited.insert(BBNum);
- // Recurse over all successors
- for (auto &SuccMBB : MBB.successors())
- markUsedRegsInSuccessors(*SuccMBB, Used, Visited);
-}
-
-static inline bool opcodeIsRealReturn(unsigned opcode) {
- switch (opcode) {
- case X86::RET:
- case X86::RETL:
- case X86::RETQ:
- case X86::RETW:
- case X86::RETIL:
- case X86::RETIQ:
- case X86::RETIW:
- case X86::LRETL:
- case X86::LRETQ:
- case X86::LRETW:
- case X86::LRETIL:
- case X86::LRETIQ:
- case X86::LRETIW:
- return true;
- default:
- return false;
- }
-}
-static inline bool needsReturnProtector(MachineFunction &MF) {
- for (auto &MBB : MF)
- for (auto &T : MBB.terminators())
- if (opcodeIsRealReturn(T.getOpcode()))
- return true;
- return false;
-}
-
-bool X86FrameLowering::determineReturnProtectorTempRegister(MachineFunction &MF,
- const SmallVector<MachineBasicBlock *, 4> &SaveBlocks,
- const SmallVector<MachineBasicBlock *, 4> &RestoreBlocks) const {
-
- MachineFrameInfo &MFI = MF.getFrameInfo();
-
- if (!MFI.hasReturnProtector() || !needsReturnProtector(MF))
- return true;
-
- // CSR spills happen at the beginning of this block
- std::vector<unsigned> TempRegs;
- SmallSet<unsigned, 16> Used;
- SmallSet<int, 24> Visited;
- const Function &F = MF.getFunction();
-
- TempRegs = {X86::R11, X86::R10};
- if (!F.isVarArg()) {
- // We can use any of the caller saved unused arg registers
- switch (F.arg_size()) {
- case 0: TempRegs.push_back(X86::RDI);
- case 1: TempRegs.push_back(X86::RSI);
- case 2: // RDX is the 2nd return register
- case 3: TempRegs.push_back(X86::RCX);
- case 4: TempRegs.push_back(X86::R8);
- case 5: TempRegs.push_back(X86::R9);
- default: break;
- }
- }
-
- // so we can mark it as visited because anything past it is safe
- for(auto &SB : SaveBlocks)
- Visited.insert(SB->getNumber());
-
- // CSR Restores happen at the end of restore blocks, before any terminators,
- // so we need to search restores for MBB terminators, and any successor BBs.
- for (auto &RB : RestoreBlocks) {
- for (auto &RBI : RB->terminators())
- for (auto &RBIOp : RBI.operands())
- if (RBIOp.isReg())
- Used.insert(RBIOp.getReg());
- for (auto &SuccMBB : RB->successors())
- markUsedRegsInSuccessors(*SuccMBB, Used, Visited);
- }
-
- // Now we iterate from the front to find code paths that
- // bypass save blocks and land on return blocks
- markUsedRegsInSuccessors(MF.front(), Used, Visited);
-
- // Now we have gathered all the regs used outside the frame save / restore,
- // so we can see if we have a free reg to use for the retguard cookie.
- for (unsigned Reg : TempRegs) {
- bool canUse = true;
- for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
- if (Used.count(*AI)) {
- // Reg is used somewhere, so we cannot use it
- canUse = false;
- break;
- }
- }
- if (canUse) {
- MFI.setReturnProtectorTempRegister(Reg);
- break;
- }
- }
-
- // return whether or not we set a register
- return MFI.hasReturnProtectorTempRegister();
-}
-
-void X86FrameLowering::insertReturnProtectorPrologue(MachineFunction &MF,
- MachineBasicBlock &MBB) const
-{
-
- const MachineFrameInfo &MFI = MF.getFrameInfo();
-
- if (!MFI.hasReturnProtector() || !MFI.hasReturnProtectorTempRegister())
- return;
-
- MachineBasicBlock::instr_iterator MBBI = MBB.instr_begin();
- DebugLoc MBBDL = MBB.findDebugLoc(MBBI);
- const Function &Fn = MF.getFunction();
- const Module *M = Fn.getParent();
- GlobalVariable *cookie;
- unsigned XORRM, MOVRM, SP, REG, IP;
-
- XORRM = X86::XOR64rm;
- MOVRM = X86::MOV64rm;
- SP = X86::RSP;
- REG = MFI.getReturnProtectorTempRegister();
- IP = X86::RIP;
-
- cookie = dyn_cast_or_null<GlobalVariable>(M->getGlobalVariable(
- Fn.getFnAttribute("ret-protector-cookie").getValueAsString(),
- Type::getInt8PtrTy(M->getContext())));
- MBB.addLiveIn(REG);
- BuildMI(MBB, MBBI, MBBDL, TII.get(MOVRM), REG)
- .addReg(IP)
- .addImm(0)
- .addReg(0)
- .addGlobalAddress(cookie)
- .addReg(0);
- addDirectMem(BuildMI(MBB, MBBI, MBBDL, TII.get(XORRM), REG).addReg(REG), SP);
-}
-
-bool X86FrameLowering::insertReturnProtectorEpilogue(MachineFunction &MF,
- MachineBasicBlock &MBB) const
-{
- const MachineFrameInfo &MFI = MF.getFrameInfo();
-
- if (!MFI.hasReturnProtector() || !MFI.hasReturnProtectorTempRegister())
- return false;
-
- const Function &Fn = MF.getFunction();
- const Module *M = Fn.getParent();
- std::vector<MachineInstr *> returns;
- GlobalVariable *cookie;
- unsigned XORRM, CMPRM, SP, REG, IP;
-
- XORRM = X86::XOR64rm;
- CMPRM = X86::CMP64rm;
- SP = X86::RSP;
- REG = MFI.getReturnProtectorTempRegister();
- IP = X86::RIP;
-
- for (auto &MI : MBB.terminators())
- if (opcodeIsRealReturn(MI.getOpcode()))
- returns.push_back(&MI);
-
- if (returns.empty())
- return false;
-
- for (auto &MI : returns) {
- const DebugLoc &DL = MI->getDebugLoc();
- cookie = dyn_cast_or_null<GlobalVariable>(M->getGlobalVariable(
- Fn.getFnAttribute("ret-protector-cookie").getValueAsString(),
- Type::getInt8PtrTy(M->getContext())));
- MBB.addLiveIn(REG);
- addDirectMem(BuildMI(MBB, MI, DL, TII.get(XORRM), REG).addReg(REG), SP);
- BuildMI(MBB, MI, DL, TII.get(CMPRM))
- .addReg(REG)
- .addReg(IP)
- .addImm(0)
- .addReg(0)
- .addGlobalAddress(cookie)
- .addReg(0);
- BuildMI(MBB, MI, DL, TII.get(X86::RETGUARD_JMP_TRAP));
- }
- return true;
+const ReturnProtectorLowering *X86FrameLowering::getReturnProtector() const {
+ return &RPL;
}
diff --git a/gnu/llvm/lib/Target/X86/X86FrameLowering.h b/gnu/llvm/lib/Target/X86/X86FrameLowering.h
index 5938b36dbd7..fb6aa91e29b 100644
--- a/gnu/llvm/lib/Target/X86/X86FrameLowering.h
+++ b/gnu/llvm/lib/Target/X86/X86FrameLowering.h
@@ -14,6 +14,7 @@
#ifndef LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H
#define LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H
+#include "X86ReturnProtectorLowering.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
namespace llvm {
@@ -23,6 +24,7 @@ class MCCFIInstruction;
class X86InstrInfo;
class X86Subtarget;
class X86RegisterInfo;
+class X86ReturnProtectorLowering;
class X86FrameLowering : public TargetFrameLowering {
public:
@@ -33,6 +35,7 @@ public:
const X86Subtarget &STI;
const X86InstrInfo &TII;
const X86RegisterInfo *TRI;
+ const X86ReturnProtectorLowering RPL;
unsigned SlotSize;
@@ -68,18 +71,7 @@ public:
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
- /// determineReturnProtectorTempRegister - find a free register for the
- /// return protector cookie calculation.
- virtual bool determineReturnProtectorTempRegister(MachineFunction &MF,
- const SmallVector<MachineBasicBlock *, 4> &SaveBlocks,
- const SmallVector<MachineBasicBlock *, 4> &RestoreBlocks) const override;
-
-
- /// Insert Return Protector instrumentation prologue / epilogue
- void insertReturnProtectorPrologue(MachineFunction &MF,
- MachineBasicBlock &MBB) const override;
- bool insertReturnProtectorEpilogue(MachineFunction &MF,
- MachineBasicBlock &MBB) const override;
+ const ReturnProtectorLowering *getReturnProtector() const override;
void adjustForSegmentedStacks(MachineFunction &MF,
MachineBasicBlock &PrologueMBB) const override;
diff --git a/gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.cpp b/gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.cpp
new file mode 100644
index 00000000000..c881e2ab6f3
--- /dev/null
+++ b/gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.cpp
@@ -0,0 +1,118 @@
+//===-- X86ReturnProtectorLowering.cpp - ----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the X86 implementation of ReturnProtectorLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86ReturnProtectorLowering.h"
+#include "X86InstrBuilder.h"
+#include "X86InstrInfo.h"
+#include "X86MachineFunctionInfo.h"
+#include "X86Subtarget.h"
+#include "X86TargetMachine.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetOptions.h"
+#include <cstdlib>
+
+using namespace llvm;
+
+void X86ReturnProtectorLowering::insertReturnProtectorPrologue(
+ MachineFunction &MF, MachineBasicBlock &MBB, GlobalVariable *cookie) const {
+
+ MachineBasicBlock::instr_iterator MI = MBB.instr_begin();
+ DebugLoc MBBDL = MBB.findDebugLoc(MI);
+ const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+ unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
+
+ MBB.addLiveIn(REG);
+ BuildMI(MBB, MI, MBBDL, TII->get(X86::MOV64rm), REG)
+ .addReg(X86::RIP)
+ .addImm(0)
+ .addReg(0)
+ .addGlobalAddress(cookie)
+ .addReg(0);
+ addDirectMem(BuildMI(MBB, MI, MBBDL, TII->get(X86::XOR64rm), REG).addReg(REG),
+ X86::RSP);
+}
+
+void X86ReturnProtectorLowering::insertReturnProtectorEpilogue(
+ MachineFunction &MF, MachineInstr &MI, GlobalVariable *cookie) const {
+
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc MBBDL = MI.getDebugLoc();
+ const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+ unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
+
+ MBB.addLiveIn(REG);
+ addDirectMem(BuildMI(MBB, MI, MBBDL, TII->get(X86::XOR64rm), REG).addReg(REG),
+ X86::RSP);
+ BuildMI(MBB, MI, MBBDL, TII->get(X86::CMP64rm))
+ .addReg(REG)
+ .addReg(X86::RIP)
+ .addImm(0)
+ .addReg(0)
+ .addGlobalAddress(cookie)
+ .addReg(0);
+ BuildMI(MBB, MI, MBBDL, TII->get(X86::RETGUARD_JMP_TRAP));
+}
+
+bool X86ReturnProtectorLowering::opcodeIsReturn(unsigned opcode) const {
+ switch (opcode) {
+ case X86::RET:
+ case X86::RETL:
+ case X86::RETQ:
+ case X86::RETW:
+ case X86::RETIL:
+ case X86::RETIQ:
+ case X86::RETIW:
+ case X86::LRETL:
+ case X86::LRETQ:
+ case X86::LRETW:
+ case X86::LRETIL:
+ case X86::LRETIQ:
+ case X86::LRETIW:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void X86ReturnProtectorLowering::fillTempRegisters(
+ MachineFunction &MF, std::vector<unsigned> &TempRegs) const {
+
+ TempRegs.push_back(X86::R11);
+ TempRegs.push_back(X86::R10);
+ const Function &F = MF.getFunction();
+ if (!F.isVarArg()) {
+ // We can use any of the caller saved unused arg registers
+ switch (F.arg_size()) {
+ case 0:
+ TempRegs.push_back(X86::RDI);
+ case 1:
+ TempRegs.push_back(X86::RSI);
+ case 2: // RDX is the 2nd return register
+ case 3:
+ TempRegs.push_back(X86::RCX);
+ case 4:
+ TempRegs.push_back(X86::R8);
+ case 5:
+ TempRegs.push_back(X86::R9);
+ default:
+ break;
+ }
+ }
+}
diff --git a/gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.h b/gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.h
new file mode 100644
index 00000000000..1eb5f123ce8
--- /dev/null
+++ b/gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.h
@@ -0,0 +1,45 @@
+//===-- X86ReturnProtectorLowering.h - ------------------------- -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the X86 implementation of ReturnProtectorLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_X86_X86RETURNPROTECTORLOWERING_H
+#define LLVM_LIB_TARGET_X86_X86RETURNPROTECTORLOWERING_H
+
+#include "llvm/CodeGen/ReturnProtectorLowering.h"
+
+namespace llvm {
+
+class X86ReturnProtectorLowering : public ReturnProtectorLowering {
+public:
+ /// insertReturnProtectorPrologue/Epilogue - insert return protector
+ /// instrumentation in prologue or epilogue.
+ virtual void
+ insertReturnProtectorPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
+ GlobalVariable *cookie) const override;
+ virtual void
+ insertReturnProtectorEpilogue(MachineFunction &MF, MachineInstr &MI,
+ GlobalVariable *cookie) const override;
+
+ /// opcodeIsReturn - Reuturn true is the given opcode is a return
+ /// instruction needing return protection, false otherwise.
+ virtual bool opcodeIsReturn(unsigned opcode) const override;
+
+ /// fillTempRegisters - Fill the list of available temp registers we can
+ /// use as a return protector register.
+ virtual void
+ fillTempRegisters(MachineFunction &MF,
+ std::vector<unsigned> &TempRegs) const override;
+};
+
+} // namespace llvm
+
+#endif