From: mortimer Date: Sun, 12 Aug 2018 17:07:00 +0000 (+0000) Subject: Add retguard for arm64. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=9866f44de26a847eaed067d23d8660b7dca51614;p=openbsd Add retguard for arm64. ok deraadt@ --- diff --git a/gnu/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/gnu/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 2ff2ee347f5..3fbd9892e30 100644 --- a/gnu/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/gnu/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -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. diff --git a/gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index d66f7b59a4b..250d4edcc56 100644 --- a/gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -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(); return AFI->hasCalleeSaveStackFreeSpace(); } + +const ReturnProtectorLowering *AArch64FrameLowering::getReturnProtector() const { + return &RPL; +} diff --git a/gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.h index 55a256867fa..fcbbc1434f1 100644 --- a/gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ b/gnu/llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -14,15 +14,19 @@ #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, diff --git a/gnu/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/gnu/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 79826ca2ed8..276d664ac61 100644 --- a/gnu/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/gnu/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -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 index 00000000000..9d4bdd9591b --- /dev/null +++ b/gnu/llvm/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 + +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 &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 &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 index 00000000000..47feb002978 --- /dev/null +++ b/gnu/llvm/lib/Target/AArch64/AArch64ReturnProtectorLowering.h @@ -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 &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 &CSI) const override; +}; + +} // namespace llvm + +#endif diff --git a/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp b/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp index 91a656f4a48..5c3953bd478 100644 --- a/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp +++ b/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp @@ -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")); diff --git a/gnu/usr.bin/clang/libLLVMAArch64CodeGen/Makefile b/gnu/usr.bin/clang/libLLVMAArch64CodeGen/Makefile index 059c87c027d..c7333b25152 100644 --- a/gnu/usr.bin/clang/libLLVMAArch64CodeGen/Makefile +++ b/gnu/usr.bin/clang/libLLVMAArch64CodeGen/Makefile @@ -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 \