37#define DEBUG_TYPE "aarch64-sls-hardening"
39#define AARCH64_SLS_HARDENING_NAME "AArch64 sls hardening pass"
68char AArch64SLSHardening::ID = 0;
79 "Must not insert SpeculationBarrierEndBB as only instruction in MBB.");
81 "SpeculationBarrierEndBB must only follow unconditional control flow "
84 "SpeculationBarrierEndBB must only follow terminators.");
87 ? AArch64::SpeculationBarrierSBEndBB
88 : AArch64::SpeculationBarrierISBDSBEndBB;
90 (
MBBI->getOpcode() != AArch64::SpeculationBarrierSBEndBB &&
91 MBBI->getOpcode() != AArch64::SpeculationBarrierISBDSBEndBB))
101 for (
auto &
MBB : MF) {
110 switch (
MI.getOpcode()) {
112 case AArch64::BLRNoIP:
116 case AArch64::BLRAAZ:
117 case AArch64::BLRABZ:
119 "producing BLRA* instructions. Therefore, there's no "
120 "support in this pass for those instructions.");
126 if (!
ST->hardenSlsRetBr())
133 NextMBBI = std::next(
MBBI);
136 insertSpeculationBarrier(ST,
MBB, std::next(
MBBI),
MI.getDebugLoc());
143static const char SLSBLRNamePrefix[] =
"__llvm_slsblr_thunk_";
149 {
"__llvm_slsblr_thunk_x0", AArch64::X0},
150 {
"__llvm_slsblr_thunk_x1", AArch64::X1},
151 {
"__llvm_slsblr_thunk_x2", AArch64::X2},
152 {
"__llvm_slsblr_thunk_x3", AArch64::X3},
153 {
"__llvm_slsblr_thunk_x4", AArch64::X4},
154 {
"__llvm_slsblr_thunk_x5", AArch64::X5},
155 {
"__llvm_slsblr_thunk_x6", AArch64::X6},
156 {
"__llvm_slsblr_thunk_x7", AArch64::X7},
157 {
"__llvm_slsblr_thunk_x8", AArch64::X8},
158 {
"__llvm_slsblr_thunk_x9", AArch64::X9},
159 {
"__llvm_slsblr_thunk_x10", AArch64::X10},
160 {
"__llvm_slsblr_thunk_x11", AArch64::X11},
161 {
"__llvm_slsblr_thunk_x12", AArch64::X12},
162 {
"__llvm_slsblr_thunk_x13", AArch64::X13},
163 {
"__llvm_slsblr_thunk_x14", AArch64::X14},
164 {
"__llvm_slsblr_thunk_x15", AArch64::X15},
168 {
"__llvm_slsblr_thunk_x18", AArch64::X18},
169 {
"__llvm_slsblr_thunk_x19", AArch64::X19},
170 {
"__llvm_slsblr_thunk_x20", AArch64::X20},
171 {
"__llvm_slsblr_thunk_x21", AArch64::X21},
172 {
"__llvm_slsblr_thunk_x22", AArch64::X22},
173 {
"__llvm_slsblr_thunk_x23", AArch64::X23},
174 {
"__llvm_slsblr_thunk_x24", AArch64::X24},
175 {
"__llvm_slsblr_thunk_x25", AArch64::X25},
176 {
"__llvm_slsblr_thunk_x26", AArch64::X26},
177 {
"__llvm_slsblr_thunk_x27", AArch64::X27},
178 {
"__llvm_slsblr_thunk_x28", AArch64::X28},
179 {
"__llvm_slsblr_thunk_x29", AArch64::FP},
182 {
"__llvm_slsblr_thunk_x31", AArch64::XZR},
186struct SLSBLRThunkInserter :
ThunkInserter<SLSBLRThunkInserter> {
187 const char *getThunkPrefix() {
return SLSBLRNamePrefix; }
200 bool ComdatThunks =
true;
210 createThunkFunction(MMI,
T.Name, ComdatThunks);
233 Entry->addLiveIn(ThunkReg);
291 case AArch64::BLRNoIP:
292 BLOpcode = AArch64::BL;
294 assert(Reg != AArch64::X16 && Reg != AArch64::X17 && Reg != AArch64::LR);
299 case AArch64::BLRAAZ:
300 case AArch64::BLRABZ:
302 "therefore there is no need to support them for now.");
352 for (
unsigned OpIdx =
BL->getNumExplicitOperands();
353 OpIdx < BL->getNumOperands(); OpIdx++) {
357 if (
Op.getReg() == AArch64::LR &&
Op.isDef())
359 if (
Op.getReg() == AArch64::SP && !
Op.isDef())
364 int FirstOpIdxToRemove = std::max(ImpLROpIdx, ImpSPOpIdx);
365 int SecondOpIdxToRemove = std::min(ImpLROpIdx, ImpSPOpIdx);
366 BL->removeOperand(FirstOpIdxToRemove);
367 BL->removeOperand(SecondOpIdxToRemove);
369 BL->copyImplicitOps(MF, BLR);
381 if (!
ST->hardenSlsBlr())
389 NextMBBI = std::next(
MBBI);
399 return new AArch64SLSHardening();
415 std::tuple<SLSBLRThunkInserter> TIs;
418 template <
typename... ThunkInserterT>
419 static void initTIs(
Module &M,
420 std::tuple<ThunkInserterT...> &ThunkInserters) {
421 (void)std::initializer_list<int>{
422 (std::get<ThunkInserterT>(ThunkInserters).init(M), 0)...};
424 template <
typename... ThunkInserterT>
426 std::tuple<ThunkInserterT...> &ThunkInserters) {
428 (void)std::initializer_list<int>{
429 Modified |= std::get<ThunkInserterT>(ThunkInserters).run(MMI, MF)...};
436char AArch64IndirectThunks::ID = 0;
439 return new AArch64IndirectThunks();
442bool AArch64IndirectThunks::doInitialization(
Module &M) {
449 auto &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
450 return runTIs(MMI, MF, TIs);
#define AARCH64_SLS_HARDENING_NAME
static const struct ThunkNameAndReg SLSBLRThunks[]
MachineBasicBlock MachineBasicBlock::iterator DebugLoc bool AlwaysUseISBDSB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file implements the BitVector class.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Contains a base class for Passes that inject an MI thunk.
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
Context object for machine code objects.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
instr_iterator instr_begin()
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
bool doInitialization(Module &) override
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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.
MCContext & getContext() const
const MachineBasicBlock & front() const
void moveCallSiteInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
This class contains meta information specific to a module.
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
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)
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
StringRef - Represent a constant reference to a string, i.e.
bool startswith(StringRef Prefix) const
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
Iterator for intrusive lists based on ilist_node.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool isIndirectBranchOpcode(int Opc)
FunctionPass * createAArch64IndirectThunks()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void initializeAArch64SLSHardeningPass(PassRegistry &)
FunctionPass * createAArch64SLSHardeningPass()
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.