Add retguard for arm64.
authormortimer <mortimer@openbsd.org>
Sun, 12 Aug 2018 17:07:00 +0000 (17:07 +0000)
committermortimer <mortimer@openbsd.org>
Sun, 12 Aug 2018 17:07:00 +0000 (17:07 +0000)
ok deraadt@

gnu/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.h
gnu/llvm/lib/Target/AArch64/AArch64InstrInfo.td
gnu/llvm/lib/Target/AArch64/AArch64ReturnProtectorLowering.cpp [new file with mode: 0644]
gnu/llvm/lib/Target/AArch64/AArch64ReturnProtectorLowering.h [new file with mode: 0644]
gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
gnu/usr.bin/clang/libLLVMAArch64CodeGen/Makefile

index 2ff2ee3..3fbd989 100644 (file)
@@ -703,6 +703,19 @@ void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
   case TargetOpcode::PATCHABLE_TAIL_CALL:
     LowerPATCHABLE_TAIL_CALL(*MI);
     return;
+
+  case AArch64::RETGUARD_JMP_TRAP:
+    {
+    MCSymbol *RGSuccSym = OutContext.createTempSymbol();
+    /* Compare and branch */
+    EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CBZX)
+        .addReg(MI->getOperand(0).getReg())
+        .addExpr(MCSymbolRefExpr::create(RGSuccSym, OutContext)));
+    EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(1));
+    OutStreamer->EmitLabel(RGSuccSym);
+    return;
+    }
+
   }
 
   // Finally, do the automated lowerings for everything else.
index d66f7b5..250d4ed 100644 (file)
@@ -95,6 +95,7 @@
 #include "AArch64InstrInfo.h"
 #include "AArch64MachineFunctionInfo.h"
 #include "AArch64RegisterInfo.h"
+#include "AArch64ReturnProtectorLowering.h"
 #include "AArch64Subtarget.h"
 #include "AArch64TargetMachine.h"
 #include "MCTargetDesc/AArch64AddressingModes.h"
@@ -1235,6 +1236,12 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
     if (produceCompactUnwindFrame(MF) && !SavedRegs.test(PairedReg))
       SpillEstimate++;
   }
+
+  if (MFI.hasReturnProtectorRegister()) {
+    SavedRegs.set(MFI.getReturnProtectorRegister());
+    SpillEstimate++;
+  }
+
   SpillEstimate += 2; // Conservatively include FP+LR in the estimate
   unsigned StackEstimate = MFI.estimateStackSize(MF) + 8 * SpillEstimate;
 
@@ -1337,3 +1344,7 @@ bool AArch64FrameLowering::enableStackSlotScavenging(
   const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
   return AFI->hasCalleeSaveStackFreeSpace();
 }
+
+const ReturnProtectorLowering *AArch64FrameLowering::getReturnProtector() const {
+  return &RPL;
+}
index 55a2568..fcbbc14 100644 (file)
 #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H
 #define LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H
 
+#include "AArch64ReturnProtectorLowering.h"
 #include "llvm/CodeGen/TargetFrameLowering.h"
 
 namespace llvm {
 
 class AArch64FrameLowering : public TargetFrameLowering {
 public:
+
+  const AArch64ReturnProtectorLowering RPL;
+
   explicit AArch64FrameLowering()
       : TargetFrameLowering(StackGrowsDown, 16, 0, 16,
-                            true /*StackRealignable*/) {}
+                            true /*StackRealignable*/), RPL() {}
 
   void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB,
                                  MachineBasicBlock::iterator MBBI) const;
@@ -36,6 +40,8 @@ public:
   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
 
+  const ReturnProtectorLowering *getReturnProtector() const override;
+
   bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
 
   int getFrameIndexReference(const MachineFunction &MF, int FI,
index 79826ca..276d664 100644 (file)
@@ -399,6 +399,12 @@ def MOVaddrEXT
 
 } // isReMaterializable, isCodeGenOnly
 
+//===----------------------------------------------------------------------===//
+// Pseudo instruction used by retguard
+let isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
+    def RETGUARD_JMP_TRAP: Pseudo<(outs), (ins GPR64:$reg), []>;
+}
+
 def : Pat<(AArch64LOADgot tglobaltlsaddr:$addr),
           (LOADgot tglobaltlsaddr:$addr)>;
 
diff --git a/gnu/llvm/lib/Target/AArch64/AArch64ReturnProtectorLowering.cpp b/gnu/llvm/lib/Target/AArch64/AArch64ReturnProtectorLowering.cpp
new file mode 100644 (file)
index 0000000..9d4bdd9
--- /dev/null
@@ -0,0 +1,123 @@
+//===-- AArch64ReturnProtectorLowering.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 AArch64 implementation of ReturnProtectorLowering
+// class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64InstrInfo.h"
+#include "AArch64MachineFunctionInfo.h"
+#include "AArch64RegisterInfo.h"
+#include "AArch64ReturnProtectorLowering.h"
+#include "AArch64Subtarget.h"
+#include "AArch64TargetMachine.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 AArch64ReturnProtectorLowering::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(AArch64::ADRP), REG)
+      .addGlobalAddress(cookie, 0, AArch64II::MO_PAGE);
+  BuildMI(MBB, MI, MBBDL, TII->get(AArch64::LDRXui), REG)
+      .addReg(REG)
+      .addGlobalAddress(cookie, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
+  BuildMI(MBB, MI, MBBDL, TII->get(AArch64::EORXrr), REG)
+      .addReg(REG)
+      .addReg(AArch64::LR);
+}
+
+void AArch64ReturnProtectorLowering::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);
+  MBB.addLiveIn(AArch64::X9);
+  // REG holds the cookie we calculated in prologue. We use X9 as a
+  // scratch reg to pull the random data. XOR REG with LR should yield
+  // the random data again. Compare REG with X9 to check.
+  BuildMI(MBB, MI, MBBDL, TII->get(AArch64::EORXrr), REG)
+      .addReg(REG)
+      .addReg(AArch64::LR);
+  BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ADRP), AArch64::X9)
+      .addGlobalAddress(cookie, 0, AArch64II::MO_PAGE);
+  BuildMI(MBB, MI, MBBDL, TII->get(AArch64::LDRXui), AArch64::X9)
+      .addReg(AArch64::X9)
+      .addGlobalAddress(cookie, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
+  BuildMI(MBB, MI, MBBDL, TII->get(AArch64::SUBSXrr), REG)
+      .addReg(REG)
+      .addReg(AArch64::X9);
+  BuildMI(MBB, MI, MBBDL, TII->get(AArch64::RETGUARD_JMP_TRAP)).addReg(REG);
+}
+
+bool AArch64ReturnProtectorLowering::opcodeIsReturn(unsigned opcode) const {
+  switch (opcode) {
+  case AArch64::RET:
+  case AArch64::RET_ReallyLR:
+    return true;
+  default:
+    return false;
+  }
+}
+
+void AArch64ReturnProtectorLowering::fillTempRegisters(
+    MachineFunction &MF, std::vector<unsigned> &TempRegs) const {
+
+  TempRegs.push_back(AArch64::X15);
+  TempRegs.push_back(AArch64::X14);
+  TempRegs.push_back(AArch64::X13);
+  TempRegs.push_back(AArch64::X12);
+  TempRegs.push_back(AArch64::X11);
+  TempRegs.push_back(AArch64::X10);
+}
+
+void AArch64ReturnProtectorLowering::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");
+
+  // Put the temp reg after FP and LR to avoid layout issues
+  // with the D registers later.
+  bool added = false;
+  for (auto CSRI = CSI.begin(); CSRI != CSI.end(); CSRI++) {
+    if (CSRI->getReg() != AArch64::FP && CSRI->getReg() != AArch64::LR) {
+      CSI.insert(CSRI, CalleeSavedInfo(MFI.getReturnProtectorRegister()));
+      added = true;
+      break;
+    }
+  }
+  if (!added)
+    CSI.push_back(CalleeSavedInfo(MFI.getReturnProtectorRegister()));
+}
diff --git a/gnu/llvm/lib/Target/AArch64/AArch64ReturnProtectorLowering.h b/gnu/llvm/lib/Target/AArch64/AArch64ReturnProtectorLowering.h
new file mode 100644 (file)
index 0000000..47feb00
--- /dev/null
@@ -0,0 +1,52 @@
+//===-- AArch64ReturnProtectorLowering.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 AArch64 implementation of ReturnProtectorLowering
+// class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64RETURNPROTECTORLOWERING_H
+#define LLVM_LIB_TARGET_AARCH64_AARCH64RETURNPROTECTORLOWERING_H
+
+#include "llvm/CodeGen/ReturnProtectorLowering.h"
+
+namespace llvm {
+
+class AArch64ReturnProtectorLowering : 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;
+
+  /// 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 override;
+};
+
+} // namespace llvm
+
+#endif
index 91a656f..5c3953b 100644 (file)
@@ -3979,7 +3979,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       RetProtector = 1;
   }
   if (RetProtector &&
-      (getToolChain().getArch() == llvm::Triple::x86_64) &&
+      ((getToolChain().getArch() == llvm::Triple::x86_64) ||
+       (getToolChain().getArch() == llvm::Triple::aarch64)) &&
       !Args.hasArg(options::OPT_fno_stack_protector) &&
       !Args.hasArg(options::OPT_pg)) {
     CmdArgs.push_back(Args.MakeArgString("-D_RET_PROTECTOR"));
index 059c87c..c7333b2 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.6 2018/04/06 14:44:04 patrick Exp $
+# $OpenBSD: Makefile,v 1.7 2018/08/12 17:07:00 mortimer Exp $
 
 LIB=   LLVMAArch64CodeGen
 NOPIC=
@@ -36,6 +36,7 @@ SRCS= AArch64A57FPLoadBalancing.cpp \
        AArch64RedundantCopyElimination.cpp \
        AArch64RegisterBankInfo.cpp \
        AArch64RegisterInfo.cpp \
+       AArch64ReturnProtectorLowering.cpp \
        AArch64SIMDInstrOpt.cpp \
        AArch64SelectionDAGInfo.cpp \
        AArch64StorePairSuppress.cpp \