Refactor retguard to make adding additional arches easier.
authormortimer <mortimer@openbsd.org>
Sun, 12 Aug 2018 16:59:31 +0000 (16:59 +0000)
committermortimer <mortimer@openbsd.org>
Sun, 12 Aug 2018 16:59:31 +0000 (16:59 +0000)
gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h
gnu/llvm/include/llvm/CodeGen/ReturnProtectorLowering.h [new file with mode: 0644]
gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h
gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp
gnu/llvm/lib/CodeGen/ReturnProtectorLowering.cpp [new file with mode: 0644]
gnu/llvm/lib/Target/X86/X86FrameLowering.cpp
gnu/llvm/lib/Target/X86/X86FrameLowering.h
gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.cpp [new file with mode: 0644]
gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.h [new file with mode: 0644]
gnu/usr.bin/clang/libLLVMCodeGen/Makefile
gnu/usr.bin/clang/libLLVMX86CodeGen/Makefile

index ad18d16..f506dfb 100644 (file)
@@ -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 (file)
index 0000000..fb9ef0c
--- /dev/null
@@ -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
index e07aadd..30c4d01 100644 (file)
@@ -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
index 529fa74..4517c3a 100644 (file)
@@ -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 (file)
index 0000000..60ad3ed
--- /dev/null
@@ -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);
+}
index e0a4b31..170cd09 100644 (file)
@@ -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;
 }
index 5938b36..fb6aa91 100644 (file)
@@ -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 (file)
index 0000000..c881e2a
--- /dev/null
@@ -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 (file)
index 0000000..1eb5f12
--- /dev/null
@@ -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
index f66dfe2..23a5281 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.7 2018/06/06 00:14:29 mortimer Exp $
+# $OpenBSD: Makefile,v 1.8 2018/08/12 16:59:31 mortimer Exp $
 
 LIB=   LLVMCodeGen
 NOPIC=
@@ -129,6 +129,7 @@ SRCS=       AggressiveAntiDepBreaker.cpp \
        RegisterUsageInfo.cpp \
        RenameIndependentSubregs.cpp \
        ResetMachineFunctionPass.cpp \
+       ReturnProtectorLowering.cpp \
        ReturnProtectorPass.cpp \
        SafeStack.cpp \
        SafeStackColoring.cpp \
index 3ec6619..7f2e1ea 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.9 2018/04/28 23:00:28 mortimer Exp $
+# $OpenBSD: Makefile,v 1.10 2018/08/12 16:59:31 mortimer Exp $
 
 LIB=   LLVMX86CodeGen
 NOPIC=
@@ -36,6 +36,7 @@ SRCS= X86AsmPrinter.cpp \
        X86RegisterBankInfo.cpp \
        X86RegisterInfo.cpp \
        X86RetpolineThunks.cpp \
+       X86ReturnProtectorLowering.cpp \
        X86SelectionDAGInfo.cpp \
        X86ShuffleDecodeConstantPool.cpp \
        X86Subtarget.cpp \