diff options
author | mortimer <mortimer@cvs.openbsd.org> | 2018-08-12 16:59:32 +0000 |
---|---|---|
committer | mortimer <mortimer@cvs.openbsd.org> | 2018-08-12 16:59:32 +0000 |
commit | a466ca26e9d453aaeb0c4de1551426d89a376cf9 (patch) | |
tree | 7e3f6e14eb7eda982aaefe1136c2e9c2d59cb306 /gnu/llvm | |
parent | e34416cdb4ab34920fd178243b0cf8601f7a8b59 (diff) |
Refactor retguard to make adding additional arches easier.
Diffstat (limited to 'gnu/llvm')
-rw-r--r-- | gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h | 24 | ||||
-rw-r--r-- | gnu/llvm/include/llvm/CodeGen/ReturnProtectorLowering.h | 78 | ||||
-rw-r--r-- | gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h | 19 | ||||
-rw-r--r-- | gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp | 32 | ||||
-rw-r--r-- | gnu/llvm/lib/CodeGen/ReturnProtectorLowering.cpp | 177 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/X86/X86FrameLowering.cpp | 200 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/X86/X86FrameLowering.h | 16 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.cpp | 118 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/X86/X86ReturnProtectorLowering.h | 45 |
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 |