LLVM  9.0.0svn
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 "llvm/ADT/Statistic.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "x86-indirect-branch-tracking"
29 
31  "x86-indirect-branch-tracking", cl::init(false), cl::Hidden,
32  cl::desc("Enable X86 indirect branch tracking pass."));
33 
34 STATISTIC(NumEndBranchAdded, "Number of ENDBR instructions added");
35 
36 namespace {
37 class X86IndirectBranchTrackingPass : public MachineFunctionPass {
38 public:
39  X86IndirectBranchTrackingPass() : MachineFunctionPass(ID) {}
40 
41  StringRef getPassName() const override {
42  return "X86 Indirect Branch Tracking";
43  }
44 
45  bool runOnMachineFunction(MachineFunction &MF) override;
46 
47 private:
48  static char ID;
49 
50  /// Machine instruction info used throughout the class.
51  const X86InstrInfo *TII;
52 
53  /// Endbr opcode for the current machine function.
54  unsigned int EndbrOpcode;
55 
56  /// Adds a new ENDBR instruction to the begining of the MBB.
57  /// The function will not add it if already exists.
58  /// It will add ENDBR32 or ENDBR64 opcode, depending on the target.
59  /// \returns true if the ENDBR was added and false otherwise.
60  bool addENDBR(MachineBasicBlock &MBB) const;
61 };
62 
63 } // end anonymous namespace
64 
66 
68  return new X86IndirectBranchTrackingPass();
69 }
70 
71 bool X86IndirectBranchTrackingPass::addENDBR(MachineBasicBlock &MBB) const {
72  assert(TII && "Target instruction info was not initialized");
73  assert((X86::ENDBR64 == EndbrOpcode || X86::ENDBR32 == EndbrOpcode) &&
74  "Unexpected Endbr opcode");
75 
76  auto MI = MBB.begin();
77  // If the MBB is empty or the first instruction is not ENDBR,
78  // add the ENDBR instruction to the beginning of the MBB.
79  if (MI == MBB.end() || EndbrOpcode != MI->getOpcode()) {
80  BuildMI(MBB, MI, MBB.findDebugLoc(MI), TII->get(EndbrOpcode));
81  NumEndBranchAdded++;
82  return true;
83  }
84 
85  return false;
86 }
87 
88 bool X86IndirectBranchTrackingPass::runOnMachineFunction(MachineFunction &MF) {
90 
91  // Check that the cf-protection-branch is enabled.
92  Metadata *isCFProtectionSupported =
93  MF.getMMI().getModule()->getModuleFlag("cf-protection-branch");
94  if (!isCFProtectionSupported && !IndirectBranchTracking)
95  return false;
96 
97  // True if the current MF was changed and false otherwise.
98  bool Changed = false;
99 
100  TII = SubTarget.getInstrInfo();
101  EndbrOpcode = SubTarget.is64Bit() ? X86::ENDBR64 : X86::ENDBR32;
102 
103  // Non-internal function or function whose address was taken, can be
104  // accessed through indirect calls. Mark the first BB with ENDBR instruction
105  // unless nocf_check attribute is used.
106  if ((MF.getFunction().hasAddressTaken() ||
107  !MF.getFunction().hasLocalLinkage()) &&
108  !MF.getFunction().doesNoCfCheck()) {
109  auto MBB = MF.begin();
110  Changed |= addENDBR(*MBB);
111  }
112 
113  for (auto &MBB : MF)
114  // Find all basic blocks that their address was taken (for example
115  // in the case of indirect jump) and add ENDBR instruction.
116  if (MBB.hasAddressTaken())
117  Changed |= addENDBR(MBB);
118 
119  return Changed;
120 }
bool is64Bit() const
Is this x86_64? (disregarding specific ABI / programming model)
Definition: X86Subtarget.h:521
bool hasLocalLinkage() const
Definition: GlobalValue.h:435
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const X86InstrInfo * getInstrInfo() const override
Definition: X86Subtarget.h:480
STATISTIC(NumFunctions, "Total number of functions")
MachineModuleInfo & getMMI() const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
static cl::opt< bool > IndirectBranchTracking("x86-indirect-branch-tracking", cl::init(false), cl::Hidden, cl::desc("Enable X86 indirect branch tracking pass."))
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:422
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
Definition: Module.cpp:310
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE and DBG_LABEL instructions...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
bool hasAddressTaken() const
Test whether this block is potentially the target of an indirect branch.
FunctionPass * createX86IndirectBranchTrackingPass()
This pass inserts ENDBR instructions before indirect jump/call destinations as part of CET IBT mechan...
const Function & getFunction() const
Return the LLVM function that this machine code represents.
const Module * getModule() const
bool hasAddressTaken(const User **=nullptr) const
hasAddressTaken - returns true if there are any uses of this function other than direct calls or invo...
Definition: Function.cpp:1257
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
bool doesNoCfCheck() const
Determine if the function should not perform indirect branch tracking.
Definition: Function.h:516
Root of the metadata hierarchy.
Definition: Metadata.h:57