LLVM  14.0.0git
CrossDSOCFI.cpp
Go to the documentation of this file.
1 //===-- CrossDSOCFI.cpp - Externalize this module's CFI checks ------------===//
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 pass exports all llvm.bitset's found in the module in the form of a
10 // __cfi_check function, which can be used to verify cross-DSO call targets.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/SetVector.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/ADT/Triple.h"
18 #include "llvm/IR/Constant.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/IR/GlobalObject.h"
22 #include "llvm/IR/GlobalVariable.h"
23 #include "llvm/IR/IRBuilder.h"
24 #include "llvm/IR/Instructions.h"
25 #include "llvm/IR/Intrinsics.h"
26 #include "llvm/IR/MDBuilder.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/IR/Operator.h"
29 #include "llvm/InitializePasses.h"
30 #include "llvm/Pass.h"
31 #include "llvm/Support/Debug.h"
33 #include "llvm/Transforms/IPO.h"
34 
35 using namespace llvm;
36 
37 #define DEBUG_TYPE "cross-dso-cfi"
38 
39 STATISTIC(NumTypeIds, "Number of unique type identifiers");
40 
41 namespace {
42 
43 struct CrossDSOCFI : public ModulePass {
44  static char ID;
45  CrossDSOCFI() : ModulePass(ID) {
47  }
48 
49  MDNode *VeryLikelyWeights;
50 
51  ConstantInt *extractNumericTypeId(MDNode *MD);
52  void buildCFICheck(Module &M);
53  bool runOnModule(Module &M) override;
54 };
55 
56 } // anonymous namespace
57 
58 INITIALIZE_PASS_BEGIN(CrossDSOCFI, "cross-dso-cfi", "Cross-DSO CFI", false,
59  false)
60 INITIALIZE_PASS_END(CrossDSOCFI, "cross-dso-cfi", "Cross-DSO CFI", false, false)
61 char CrossDSOCFI::ID = 0;
62 
63 ModulePass *llvm::createCrossDSOCFIPass() { return new CrossDSOCFI; }
64 
65 /// Extracts a numeric type identifier from an MDNode containing type metadata.
66 ConstantInt *CrossDSOCFI::extractNumericTypeId(MDNode *MD) {
67  // This check excludes vtables for classes inside anonymous namespaces.
68  auto TM = dyn_cast<ValueAsMetadata>(MD->getOperand(1));
69  if (!TM)
70  return nullptr;
71  auto C = dyn_cast_or_null<ConstantInt>(TM->getValue());
72  if (!C) return nullptr;
73  // We are looking for i64 constants.
74  if (C->getBitWidth() != 64) return nullptr;
75 
76  return C;
77 }
78 
79 /// buildCFICheck - emits __cfi_check for the current module.
80 void CrossDSOCFI::buildCFICheck(Module &M) {
81  // FIXME: verify that __cfi_check ends up near the end of the code section,
82  // but before the jump slots created in LowerTypeTests.
83  SetVector<uint64_t> TypeIds;
85  for (GlobalObject &GO : M.global_objects()) {
86  Types.clear();
87  GO.getMetadata(LLVMContext::MD_type, Types);
88  for (MDNode *Type : Types)
89  if (ConstantInt *TypeId = extractNumericTypeId(Type))
90  TypeIds.insert(TypeId->getZExtValue());
91  }
92 
93  NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
94  if (CfiFunctionsMD) {
95  for (auto Func : CfiFunctionsMD->operands()) {
96  assert(Func->getNumOperands() >= 2);
97  for (unsigned I = 2; I < Func->getNumOperands(); ++I)
98  if (ConstantInt *TypeId =
99  extractNumericTypeId(cast<MDNode>(Func->getOperand(I).get())))
100  TypeIds.insert(TypeId->getZExtValue());
101  }
102  }
103 
104  LLVMContext &Ctx = M.getContext();
105  FunctionCallee C = M.getOrInsertFunction(
106  "__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx),
108  Function *F = cast<Function>(C.getCallee());
109  // Take over the existing function. The frontend emits a weak stub so that the
110  // linker knows about the symbol; this pass replaces the function body.
111  F->deleteBody();
112  F->setAlignment(Align(4096));
113 
114  Triple T(M.getTargetTriple());
115  if (T.isARM() || T.isThumb())
116  F->addFnAttr("target-features", "+thumb-mode");
117 
118  auto args = F->arg_begin();
119  Value &CallSiteTypeId = *(args++);
120  CallSiteTypeId.setName("CallSiteTypeId");
121  Value &Addr = *(args++);
122  Addr.setName("Addr");
123  Value &CFICheckFailData = *(args++);
124  CFICheckFailData.setName("CFICheckFailData");
125  assert(args == F->arg_end());
126 
127  BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
128  BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
129 
130  BasicBlock *TrapBB = BasicBlock::Create(Ctx, "fail", F);
131  IRBuilder<> IRBFail(TrapBB);
132  FunctionCallee CFICheckFailFn =
133  M.getOrInsertFunction("__cfi_check_fail", Type::getVoidTy(Ctx),
135  IRBFail.CreateCall(CFICheckFailFn, {&CFICheckFailData, &Addr});
136  IRBFail.CreateBr(ExitBB);
137 
138  IRBuilder<> IRBExit(ExitBB);
139  IRBExit.CreateRetVoid();
140 
141  IRBuilder<> IRB(BB);
142  SwitchInst *SI = IRB.CreateSwitch(&CallSiteTypeId, TrapBB, TypeIds.size());
143  for (uint64_t TypeId : TypeIds) {
144  ConstantInt *CaseTypeId = ConstantInt::get(Type::getInt64Ty(Ctx), TypeId);
145  BasicBlock *TestBB = BasicBlock::Create(Ctx, "test", F);
146  IRBuilder<> IRBTest(TestBB);
147  Function *BitsetTestFn = Intrinsic::getDeclaration(&M, Intrinsic::type_test);
148 
149  Value *Test = IRBTest.CreateCall(
150  BitsetTestFn, {&Addr, MetadataAsValue::get(
151  Ctx, ConstantAsMetadata::get(CaseTypeId))});
152  BranchInst *BI = IRBTest.CreateCondBr(Test, ExitBB, TrapBB);
153  BI->setMetadata(LLVMContext::MD_prof, VeryLikelyWeights);
154 
155  SI->addCase(CaseTypeId, TestBB);
156  ++NumTypeIds;
157  }
158 }
159 
160 bool CrossDSOCFI::runOnModule(Module &M) {
161  VeryLikelyWeights =
162  MDBuilder(M.getContext()).createBranchWeights((1U << 20) - 1, 1);
163  if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
164  return false;
165  buildCFICheck(M);
166  return true;
167 }
168 
170  CrossDSOCFI Impl;
171  bool Changed = Impl.runOnModule(M);
172  if (!Changed)
173  return PreservedAnalyses::all();
174  return PreservedAnalyses::none();
175 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::createCrossDSOCFIPass
ModulePass * createCrossDSOCFIPass()
This pass export CFI checks for use by external modules.
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::NamedMDNode
A tuple of MDNodes.
Definition: Metadata.h:1391
llvm::Intrinsic::getDeclaration
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
Definition: Function.cpp:1379
llvm::Type::getInt8PtrTy
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:255
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
llvm::Function
Definition: Function.h:61
Pass.h
llvm::SetVector::size
size_type size() const
Determine the number of elements in the SetVector.
Definition: SetVector.h:77
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
Statistic.h
llvm::IRBuilder<>
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:158
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Module.h
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::ConstantAsMetadata::get
static ConstantAsMetadata * get(Constant *C)
Definition: Metadata.h:419
GlobalObject.h
Operator.h
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::Instruction::setMetadata
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
Definition: Metadata.cpp:1336
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
llvm::PGSOQueryType::Test
@ Test
Constants.h
Intrinsics.h
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::GlobalObject
Definition: GlobalObject.h:28
llvm::MDBuilder::createBranchWeights
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
Definition: MDBuilder.cpp:37
false
Definition: StackSlotColoring.cpp:142
llvm::CrossDSOCFIPass::run
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition: CrossDSOCFI.cpp:169
MDBuilder.h
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
llvm::Value::setName
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:364
llvm::ConstantInt::get
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:900
Align
uint64_t Align
Definition: ELFObjHandler.cpp:83
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
llvm::MDNode::getOperand
const MDOperand & getOperand(unsigned I) const
Definition: Metadata.h:1107
CrossDSOCFI.h
uint64_t
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
IPO.h
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
I
#define I(x, y, z)
Definition: MD5.cpp:59
IRBuilder.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::MDNode
Metadata node.
Definition: Metadata.h:901
llvm::SetVector::insert
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:141
Triple.h
llvm::BasicBlock::Create
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:100
llvm::initializeCrossDSOCFIPass
void initializeCrossDSOCFIPass(PassRegistry &)
llvm::ifs::IFSSymbolType::Func
@ Func
llvm::NamedMDNode::operands
iterator_range< op_iterator > operands()
Definition: Metadata.h:1487
Constant.h
llvm::Type::getInt64Ty
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:204
llvm::MetadataAsValue::get
static MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition: Metadata.cpp:106
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
GlobalVariable.h
Function.h
llvm::SmallVectorImpl::clear
void clear()
Definition: SmallVector.h:585
llvm::MDBuilder
Definition: MDBuilder.h:35
llvm::Type::getVoidTy
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:186
Instructions.h
INITIALIZE_PASS_BEGIN
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:51
llvm::FunctionCallee
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:165
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::SwitchInst
Multiway switch.
Definition: Instructions.h:3204
llvm::BranchInst
Conditional or Unconditional Branch instruction.
Definition: Instructions.h:3060
raw_ostream.h
llvm::SetVector
A vector that has set insertion semantics.
Definition: SetVector.h:40
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
Debug.h
SetVector.h
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37