29#define DEBUG_TYPE "arm-sls-hardening"
31#define ARM_SLS_HARDENING_NAME "ARM sls hardening pass"
65char ARMSLSHardening::ID = 0;
76 "Must not insert SpeculationBarrierEndBB as only instruction in MBB.");
78 "SpeculationBarrierEndBB must only follow unconditional control flow "
81 "SpeculationBarrierEndBB must only follow terminators.");
83 assert(ST->hasDataBarrier() || ST->hasSB());
86 ProduceSB ? (ST->isThumb() ? ARM::t2SpeculationBarrierSBEndBB
87 : ARM::SpeculationBarrierSBEndBB)
88 : (ST->isThumb() ? ARM::t2SpeculationBarrierISBDSBEndBB
89 : ARM::SpeculationBarrierISBDSBEndBB);
99 for (
auto &
MBB : MF) {
107bool ARMSLSHardening::hardenReturnsAndBRs(MachineBasicBlock &
MBB)
const {
108 if (!ST->hardenSlsRetBr())
116 NextMBBI = std::next(
MBBI);
127static const char SLSBLRNamePrefix[] =
"__llvm_slsblr_thunk_";
134 {
"__llvm_slsblr_thunk_arm_r0", ARM::R0,
false},
135 {
"__llvm_slsblr_thunk_arm_r1", ARM::R1,
false},
136 {
"__llvm_slsblr_thunk_arm_r2", ARM::R2,
false},
137 {
"__llvm_slsblr_thunk_arm_r3", ARM::R3,
false},
138 {
"__llvm_slsblr_thunk_arm_r4", ARM::R4,
false},
139 {
"__llvm_slsblr_thunk_arm_r5", ARM::R5,
false},
140 {
"__llvm_slsblr_thunk_arm_r6", ARM::R6,
false},
141 {
"__llvm_slsblr_thunk_arm_r7", ARM::R7,
false},
142 {
"__llvm_slsblr_thunk_arm_r8", ARM::R8,
false},
143 {
"__llvm_slsblr_thunk_arm_r9", ARM::R9,
false},
144 {
"__llvm_slsblr_thunk_arm_r10", ARM::R10,
false},
145 {
"__llvm_slsblr_thunk_arm_r11", ARM::R11,
false},
146 {
"__llvm_slsblr_thunk_arm_sp", ARM::SP,
false},
147 {
"__llvm_slsblr_thunk_arm_pc", ARM::PC,
false},
148 {
"__llvm_slsblr_thunk_thumb_r0", ARM::R0,
true},
149 {
"__llvm_slsblr_thunk_thumb_r1", ARM::R1,
true},
150 {
"__llvm_slsblr_thunk_thumb_r2", ARM::R2,
true},
151 {
"__llvm_slsblr_thunk_thumb_r3", ARM::R3,
true},
152 {
"__llvm_slsblr_thunk_thumb_r4", ARM::R4,
true},
153 {
"__llvm_slsblr_thunk_thumb_r5", ARM::R5,
true},
154 {
"__llvm_slsblr_thunk_thumb_r6", ARM::R6,
true},
155 {
"__llvm_slsblr_thunk_thumb_r7", ARM::R7,
true},
156 {
"__llvm_slsblr_thunk_thumb_r8", ARM::R8,
true},
157 {
"__llvm_slsblr_thunk_thumb_r9", ARM::R9,
true},
158 {
"__llvm_slsblr_thunk_thumb_r10", ARM::R10,
true},
159 {
"__llvm_slsblr_thunk_thumb_r11", ARM::R11,
true},
160 {
"__llvm_slsblr_thunk_thumb_sp", ARM::SP,
true},
161 {
"__llvm_slsblr_thunk_thumb_pc", ARM::PC,
true},
174struct SLSBLRThunkInserter
175 : ThunkInserter<SLSBLRThunkInserter, ArmInsertedThunks> {
176 const char *getThunkPrefix() {
return SLSBLRNamePrefix; }
177 bool mayUseThunk(
const MachineFunction &MF) {
178 ComdatThunks &= !MF.
getSubtarget<ARMSubtarget>().hardenSlsNoComdat();
183 void populateThunk(MachineFunction &MF);
186 bool ComdatThunks =
true;
191SLSBLRThunkInserter::insertThunks(MachineModuleInfo &MMI, MachineFunction &MF,
203 if (
ST->isThumb() ==
T.isThumb)
204 createThunkFunction(MMI,
T.Name, ComdatThunks,
205 T.isThumb ?
"+thumb-mode" :
"");
209void SLSBLRThunkInserter::populateThunk(MachineFunction &MF) {
211 "ComdatThunks value changed since MF creation");
219 bool isThumb = ThunkIt->isThumb;
221 const TargetInstrInfo *
TII = MF.
getSubtarget<ARMSubtarget>().getInstrInfo();
229 Entry->addLiveIn(ThunkReg);
246MachineBasicBlock &ARMSLSHardening::ConvertIndirectCallToIndirectJump(
279 int RegOpIdxOnIndirectCall = -1;
285 RegOpIdxOnIndirectCall = 0;
288 case ARM::tBLXr_noip:
290 RegOpIdxOnIndirectCall = 2;
304 bool RegIsKilled =
IndirectCall.getOperand(RegOpIdxOnIndirectCall).isKill();
308 MachineFunction &MF = *
MBBI->getMF();
338 if (
Op.getReg() == ARM::LR &&
Op.isDef())
340 if (
Op.getReg() == ARM::SP && !
Op.isDef())
345 int FirstOpIdxToRemove = std::max(ImpLROpIdx, ImpSPOpIdx);
346 int SecondOpIdxToRemove = std::min(ImpLROpIdx, ImpSPOpIdx);
361bool ARMSLSHardening::hardenIndirectCalls(MachineBasicBlock &
MBB)
const {
362 if (!
ST->hardenSlsBlr())
369 NextMBBI = std::next(
MBBI);
374 ConvertIndirectCallToIndirectJump(
MBB,
MBBI);
384 return new ARMSLSHardening();
394 StringRef getPassName()
const override {
return "ARM Indirect Thunks"; }
398char ARMIndirectThunks::ID = 0;
401 return new ARMIndirectThunks();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void insertSpeculationBarrier(const AArch64Subtarget *ST, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL, bool AlwaysUseISBDSB=false)
static bool isThumb(const MCSubtargetInfo &STI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc bool AlwaysUseISBDSB
#define ARM_SLS_HARDENING_NAME
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const struct ThunkNameRegMode SLSBLRThunks[]
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Contains a base ThunkInserter class that simplifies injection of MI thunks as well as a default imple...
Machine Check Debug Module
Promote Memory to Register
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
bool isThumb1Only() const
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
Module * getParent()
Get the module that this global value is contained inside of...
bool isPredicated(const MachineInstr &MI) const override
Returns true if the instruction is already predicated.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
void moveAdditionalCallInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
LLVM_ABI void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)
Copy implicit register operands from specified instruction to this instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Wrapper class representing virtual and physical registers.
Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetInstrInfo * getInstrInfo() const
Basic implementation of MachineFunctionPass wrapping one or more ThunkInserters passed as type parame...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
static bool isIndirectCall(const MachineInstr &MI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
void initializeARMSLSHardeningPass(PassRegistry &)
FunctionPass * createARMSLSHardeningPass()
static bool isIndirectControlFlowNotComingBack(const MachineInstr &MI)
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
FunctionPass * createARMIndirectThunks()
bool operator|=(SparseBitVector< ElementSize > &LHS, const SparseBitVector< ElementSize > *RHS)
static bool isSpeculationBarrierEndBBOpcode(int Opc)