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")
 
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
 
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 & 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
 
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
 
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.
 
StringRef - 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.
 
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
 
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)