Go to the documentation of this file.
37 #define DEBUG_TYPE "aarch64-sls-hardening"
39 #define AARCH64_SLS_HARDENING_NAME "AArch64 sls hardening pass"
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());
143 static 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},
186 struct SLSBLRThunkInserter :
ThunkInserter<SLSBLRThunkInserter> {
187 const char *getThunkPrefix() {
return SLSBLRNamePrefix; }
203 createThunkFunction(MMI,
T.Name);
225 Entry->addLiveIn(ThunkReg);
284 case AArch64::BLRNoIP:
287 assert(
Reg != AArch64::X16 &&
Reg != AArch64::X17 &&
Reg != AArch64::LR);
292 case AArch64::BLRAAZ:
293 case AArch64::BLRABZ:
295 "therefore there is no need to support them for now.");
345 for (
unsigned OpIdx =
BL->getNumExplicitOperands();
346 OpIdx < BL->getNumOperands(); OpIdx++) {
350 if (
Op.getReg() == AArch64::LR &&
Op.isDef())
352 if (
Op.getReg() == AArch64::SP && !
Op.isDef())
357 int FirstOpIdxToRemove =
std::max(ImpLROpIdx, ImpSPOpIdx);
358 int SecondOpIdxToRemove =
std::min(ImpLROpIdx, ImpSPOpIdx);
359 BL->RemoveOperand(FirstOpIdxToRemove);
360 BL->RemoveOperand(SecondOpIdxToRemove);
362 BL->copyImplicitOps(MF, BLR);
374 if (!
ST->hardenSlsBlr())
381 NextMBBI = std::next(
MBBI);
391 return new AArch64SLSHardening();
401 StringRef getPassName()
const override {
return "AArch64 Indirect Thunks"; }
403 bool doInitialization(
Module &M)
override;
407 std::tuple<SLSBLRThunkInserter> TIs;
410 template <
typename... ThunkInserterT>
411 static void initTIs(
Module &M,
412 std::tuple<ThunkInserterT...> &ThunkInserters) {
413 (void)std::initializer_list<int>{
414 (std::get<ThunkInserterT>(ThunkInserters).init(M), 0)...};
416 template <
typename... ThunkInserterT>
418 std::tuple<ThunkInserterT...> &ThunkInserters) {
420 (void)std::initializer_list<int>{
421 Modified |= std::get<ThunkInserterT>(ThunkInserters).run(MMI, MF)...};
431 return new AArch64IndirectThunks();
434 bool AArch64IndirectThunks::doInitialization(
Module &M) {
439 bool AArch64IndirectThunks::runOnMachineFunction(
MachineFunction &MF) {
441 auto &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
442 return runTIs(MMI, MF, TIs);
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
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)
Context object for machine code objects.
MCContext & getContext() const
virtual const TargetInstrInfo * getInstrInfo() const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
void moveCallSiteInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
const_iterator end(StringRef path)
Get end iterator over path.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc bool AlwaysUseISBDSB
unsigned const TargetRegisterInfo * TRI
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const MachineBasicBlock & front() const
TargetInstrInfo - Interface to description of machine instruction set.
#define AARCH64_SLS_HARDENING_NAME
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const MachineOperand & getOperand(unsigned i) const
const HexagonInstrInfo * TII
MachineOperand class - Representation of each machine instruction operand.
This class contains meta information specific to a module.
void initializeAArch64SLSHardeningPass(PassRegistry &)
static const struct ThunkNameAndReg SLSBLRThunks[]
FunctionPass * createAArch64IndirectThunks()
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static bool isIndirectBranchOpcode(int Opc)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Representation of each machine instruction.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Register getReg() const
getReg - Returns the register number.
A Module instance is used to store all the information related to an LLVM module.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
FunctionPass * createAArch64SLSHardeningPass()
StringRef - Represent a constant reference to a string, i.e.
MachineBasicBlock MachineBasicBlock::iterator MBBI
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Wrapper class representing virtual and physical registers.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
@ BR
Control flow instructions. These all have token chains.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
INITIALIZE_PASS(AArch64SLSHardening, "aarch64-sls-hardening", AARCH64_SLS_HARDENING_NAME, false, false) static void insertSpeculationBarrier(const AArch64Subtarget *ST
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Align max(MaybeAlign Lhs, Align Rhs)
FunctionPass class - This class is used to implement most global optimizations.