$OpenBSD: patch-lib_Target_AArch64_AArch64ReturnProtectorLowering_cpp,v 1.1 2018/08/21 06:56:09 ajacoutot Exp $

Add retguard for arm64.

Index: lib/Target/AArch64/AArch64ReturnProtectorLowering.cpp
--- lib/Target/AArch64/AArch64ReturnProtectorLowering.cpp.orig
+++ lib/Target/AArch64/AArch64ReturnProtectorLowering.cpp
@@ -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()));
+}
