LLVM  14.0.0git
X86IndirectBranchTracking.cpp
Go to the documentation of this file.
1 //===---- X86IndirectBranchTracking.cpp - Enables CET IBT mechanism -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a pass that enables Indirect Branch Tracking (IBT) as part
10 // of Control-Flow Enforcement Technology (CET).
11 // The pass adds ENDBR (End Branch) machine instructions at the beginning of
12 // each basic block or function that is referenced by an indrect jump/call
13 // instruction.
14 // The ENDBR instructions have a NOP encoding and as such are ignored in
15 // targets that do not support CET IBT mechanism.
16 //===----------------------------------------------------------------------===//
17 
18 #include "X86.h"
19 #include "X86InstrInfo.h"
20 #include "X86Subtarget.h"
21 #include "X86TargetMachine.h"
22 #include "llvm/ADT/Statistic.h"
26 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "x86-indirect-branch-tracking"
30 
32  "x86-indirect-branch-tracking", cl::init(false), cl::Hidden,
33  cl::desc("Enable X86 indirect branch tracking pass."));
34 
35 STATISTIC(NumEndBranchAdded, "Number of ENDBR instructions added");
36 
37 namespace {
38 class X86IndirectBranchTrackingPass : public MachineFunctionPass {
39 public:
40  X86IndirectBranchTrackingPass() : MachineFunctionPass(ID) {}
41 
42  StringRef getPassName() const override {
43  return "X86 Indirect Branch Tracking";
44  }
45 
46  bool runOnMachineFunction(MachineFunction &MF) override;
47 
48 private:
49  static char ID;
50 
51  /// Machine instruction info used throughout the class.
52  const X86InstrInfo *TII = nullptr;
53 
54  /// Endbr opcode for the current machine function.
55  unsigned int EndbrOpcode = 0;
56 
57  /// Adds a new ENDBR instruction to the beginning of the MBB.
58  /// The function will not add it if already exists.
59  /// It will add ENDBR32 or ENDBR64 opcode, depending on the target.
60  /// \returns true if the ENDBR was added and false otherwise.
61  bool addENDBR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const;
62 };
63 
64 } // end anonymous namespace
65 
67 
69  return new X86IndirectBranchTrackingPass();
70 }
71 
72 bool X86IndirectBranchTrackingPass::addENDBR(
74  assert(TII && "Target instruction info was not initialized");
75  assert((X86::ENDBR64 == EndbrOpcode || X86::ENDBR32 == EndbrOpcode) &&
76  "Unexpected Endbr opcode");
77 
78  // If the MBB/I is empty or the current instruction is not ENDBR,
79  // insert ENDBR instruction to the location of I.
80  if (I == MBB.end() || I->getOpcode() != EndbrOpcode) {
81  BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(EndbrOpcode));
82  ++NumEndBranchAdded;
83  return true;
84  }
85  return false;
86 }
87 
89  if (!MOp.isGlobal())
90  return false;
91  auto *CalleeFn = dyn_cast<Function>(MOp.getGlobal());
92  if (!CalleeFn)
93  return false;
94  AttributeList Attrs = CalleeFn->getAttributes();
95  return Attrs.hasFnAttr(Attribute::ReturnsTwice);
96 }
97 
98 bool X86IndirectBranchTrackingPass::runOnMachineFunction(MachineFunction &MF) {
99  const X86Subtarget &SubTarget = MF.getSubtarget<X86Subtarget>();
100 
101  // Check that the cf-protection-branch is enabled.
102  Metadata *isCFProtectionSupported =
103  MF.getMMI().getModule()->getModuleFlag("cf-protection-branch");
104  // NB: We need to enable IBT in jitted code if JIT compiler is CET
105  // enabled.
106  const X86TargetMachine *TM =
107  static_cast<const X86TargetMachine *>(&MF.getTarget());
108 #ifdef __CET__
109  bool isJITwithCET = TM->isJIT();
110 #else
111  bool isJITwithCET = false;
112 #endif
113  if (!isCFProtectionSupported && !IndirectBranchTracking && !isJITwithCET)
114  return false;
115 
116  // True if the current MF was changed and false otherwise.
117  bool Changed = false;
118 
119  TII = SubTarget.getInstrInfo();
120  EndbrOpcode = SubTarget.is64Bit() ? X86::ENDBR64 : X86::ENDBR32;
121 
122  // Large code model, non-internal function or function whose address
123  // was taken, can be accessed through indirect calls. Mark the first
124  // BB with ENDBR instruction unless nocf_check attribute is used.
125  if ((TM->getCodeModel() == CodeModel::Large ||
126  MF.getFunction().hasAddressTaken() ||
127  !MF.getFunction().hasLocalLinkage()) &&
128  !MF.getFunction().doesNoCfCheck()) {
129  auto MBB = MF.begin();
130  Changed |= addENDBR(*MBB, MBB->begin());
131  }
132 
133  for (auto &MBB : MF) {
134  // Find all basic blocks that their address was taken (for example
135  // in the case of indirect jump) and add ENDBR instruction.
136  if (MBB.hasAddressTaken())
137  Changed |= addENDBR(MBB, MBB.begin());
138 
139  for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
140  if (I->isCall() && IsCallReturnTwice(I->getOperand(0)))
141  Changed |= addENDBR(MBB, std::next(I));
142  }
143 
144  // Exception handle may indirectly jump to catch pad, So we should add
145  // ENDBR before catch pad instructions. For SjLj exception model, it will
146  // create a new BB(new landingpad) indirectly jump to the old landingpad.
147  if (TM->Options.ExceptionModel == ExceptionHandling::SjLj) {
148  for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
149  // New Landingpad BB without EHLabel.
150  if (MBB.isEHPad()) {
151  if (I->isDebugInstr())
152  continue;
153  Changed |= addENDBR(MBB, I);
154  break;
155  } else if (I->isEHLabel()) {
156  // Old Landingpad BB (is not Landingpad now) with
157  // the the old "callee" EHLabel.
158  MCSymbol *Sym = I->getOperand(0).getMCSymbol();
159  if (!MF.hasCallSiteLandingPad(Sym))
160  continue;
161  Changed |= addENDBR(MBB, std::next(I));
162  break;
163  }
164  }
165  } else if (MBB.isEHPad()){
166  for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
167  if (!I->isEHLabel())
168  continue;
169  Changed |= addENDBR(MBB, std::next(I));
170  break;
171  }
172  }
173  }
174  return Changed;
175 }
Attrs
Function Attrs
Definition: README_ALTIVEC.txt:215
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
X86Subtarget.h
llvm::Function::doesNoCfCheck
bool doesNoCfCheck() const
Determine if the function should not perform indirect branch tracking.
Definition: Function.h:563
llvm::ExceptionHandling::SjLj
@ SjLj
setjmp/longjmp based exceptions
llvm::MachineOperand::getGlobal
const GlobalValue * getGlobal() const
Definition: MachineOperand.h:563
llvm::X86Subtarget::getInstrInfo
const X86InstrInfo * getInstrInfo() const override
Definition: X86Subtarget.h:560
Statistic.h
llvm::X86Subtarget
Definition: X86Subtarget.h:52
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
llvm::Module::getModuleFlag
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
Definition: Module.cpp:325
llvm::MachineBasicBlock::findDebugLoc
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE and DBG_LABEL instructions.
Definition: MachineBasicBlock.cpp:1373
llvm::AttributeList
Definition: Attributes.h:398
X86.h
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:129
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
llvm::MachineFunction::begin
iterator begin()
Definition: MachineFunction.h:808
IsCallReturnTwice
static bool IsCallReturnTwice(llvm::MachineOperand &MOp)
Definition: X86IndirectBranchTracking.cpp:88
llvm::Metadata
Root of the metadata hierarchy.
Definition: Metadata.h:62
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
llvm::Function::getAttributes
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:326
llvm::MachineFunction::getMMI
MachineModuleInfo & getMMI() const
Definition: MachineFunction.h:577
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:626
llvm::cl::opt< bool >
llvm::MachineBasicBlock::hasAddressTaken
bool hasAddressTaken() const
Test whether this block is potentially the target of an indirect branch.
Definition: MachineBasicBlock.h:211
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
MachineFunctionPass.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::GlobalValue::hasLocalLinkage
bool hasLocalLinkage() const
Definition: GlobalValue.h:445
llvm::X86TargetMachine
Definition: X86TargetMachine.h:28
MachineModuleInfo.h
llvm::MachineFunction
Definition: MachineFunction.h:230
llvm::X86InstrInfo
Definition: X86InstrInfo.h:130
llvm::MachineBasicBlock::isEHPad
bool isEHPad() const
Returns true if the block is a landing pad.
Definition: MachineBasicBlock.h:526
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::Function::hasAddressTaken
bool hasAddressTaken(const User **=nullptr, bool IgnoreCallbackUses=false, bool IgnoreAssumeLikeCalls=true, bool IngoreLLVMUsed=false, bool IgnoreARCAttachedCall=false) const
hasAddressTaken - returns true if there are any uses of this function other than direct calls or invo...
Definition: Function.cpp:1738
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:592
llvm::MachineFunction::getTarget
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Definition: MachineFunction.h:622
X86TargetMachine.h
llvm::CodeModel::Large
@ Large
Definition: CodeGen.h:28
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:268
MachineInstrBuilder.h
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:328
llvm::createX86IndirectBranchTrackingPass
FunctionPass * createX86IndirectBranchTrackingPass()
This pass inserts ENDBR instructions before indirect jump/call destinations as part of CET IBT mechan...
Definition: X86IndirectBranchTracking.cpp:68
llvm::X86Subtarget::is64Bit
bool is64Bit() const
Is this x86_64? (disregarding specific ABI / programming model)
Definition: X86Subtarget.h:606
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::cl::desc
Definition: CommandLine.h:414
X86InstrInfo.h
llvm::MachineInstrBundleIterator< MachineInstr >
llvm::MachineModuleInfo::getModule
const Module * getModule() const
Definition: MachineModuleInfo.h:174
IndirectBranchTracking
cl::opt< bool > IndirectBranchTracking("x86-indirect-branch-tracking", cl::init(false), cl::Hidden, cl::desc("Enable X86 indirect branch tracking pass."))
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:270
llvm::MachineOperand::isGlobal
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Definition: MachineOperand.h:339
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37