LLVM  15.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/Constants.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/IR/GlobalObject.h"
21 #include "llvm/IR/IRBuilder.h"
22 #include "llvm/IR/Instructions.h"
23 #include "llvm/IR/Intrinsics.h"
24 #include "llvm/IR/MDBuilder.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/InitializePasses.h"
27 #include "llvm/Pass.h"
28 #include "llvm/Transforms/IPO.h"
29 
30 using namespace llvm;
31 
32 #define DEBUG_TYPE "cross-dso-cfi"
33 
34 STATISTIC(NumTypeIds, "Number of unique type identifiers");
35 
36 namespace {
37 
38 struct CrossDSOCFI : public ModulePass {
39  static char ID;
40  CrossDSOCFI() : ModulePass(ID) {
42  }
43 
44  MDNode *VeryLikelyWeights;
45 
46  ConstantInt *extractNumericTypeId(MDNode *MD);
47  void buildCFICheck(Module &M);
48  bool runOnModule(Module &M) override;
49 };
50 
51 } // anonymous namespace
52 
53 INITIALIZE_PASS_BEGIN(CrossDSOCFI, "cross-dso-cfi", "Cross-DSO CFI", false,
54  false)
55 INITIALIZE_PASS_END(CrossDSOCFI, "cross-dso-cfi", "Cross-DSO CFI", false, false)
56 char CrossDSOCFI::ID = 0;
57 
58 ModulePass *llvm::createCrossDSOCFIPass() { return new CrossDSOCFI; }
59 
60 /// Extracts a numeric type identifier from an MDNode containing type metadata.
61 ConstantInt *CrossDSOCFI::extractNumericTypeId(MDNode *MD) {
62  // This check excludes vtables for classes inside anonymous namespaces.
63  auto TM = dyn_cast<ValueAsMetadata>(MD->getOperand(1));
64  if (!TM)
65  return nullptr;
66  auto C = dyn_cast_or_null<ConstantInt>(TM->getValue());
67  if (!C) return nullptr;
68  // We are looking for i64 constants.
69  if (C->getBitWidth() != 64) return nullptr;
70 
71  return C;
72 }
73 
74 /// buildCFICheck - emits __cfi_check for the current module.
75 void CrossDSOCFI::buildCFICheck(Module &M) {
76  // FIXME: verify that __cfi_check ends up near the end of the code section,
77  // but before the jump slots created in LowerTypeTests.
78  SetVector<uint64_t> TypeIds;
80  for (GlobalObject &GO : M.global_objects()) {
81  Types.clear();
82  GO.getMetadata(LLVMContext::MD_type, Types);
83  for (MDNode *Type : Types)
84  if (ConstantInt *TypeId = extractNumericTypeId(Type))
85  TypeIds.insert(TypeId->getZExtValue());
86  }
87 
88  NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
89  if (CfiFunctionsMD) {
90  for (auto Func : CfiFunctionsMD->operands()) {
91  assert(Func->getNumOperands() >= 2);
92  for (unsigned I = 2; I < Func->getNumOperands(); ++I)
93  if (ConstantInt *TypeId =
94  extractNumericTypeId(cast<MDNode>(Func->getOperand(I).get())))
95  TypeIds.insert(TypeId->getZExtValue());
96  }
97  }
98 
99  LLVMContext &Ctx = M.getContext();
100  FunctionCallee C = M.getOrInsertFunction(
101  "__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx),
103  Function *F = cast<Function>(C.getCallee());
104  // Take over the existing function. The frontend emits a weak stub so that the
105  // linker knows about the symbol; this pass replaces the function body.
106  F->deleteBody();
107  F->setAlignment(Align(4096));
108 
109  Triple T(M.getTargetTriple());
110  if (T.isARM() || T.isThumb())
111  F->addFnAttr("target-features", "+thumb-mode");
112 
113  auto args = F->arg_begin();
114  Value &CallSiteTypeId = *(args++);
115  CallSiteTypeId.setName("CallSiteTypeId");
116  Value &Addr = *(args++);
117  Addr.setName("Addr");
118  Value &CFICheckFailData = *(args++);
119  CFICheckFailData.setName("CFICheckFailData");
120  assert(args == F->arg_end());
121 
122  BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
123  BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
124 
125  BasicBlock *TrapBB = BasicBlock::Create(Ctx, "fail", F);
126  IRBuilder<> IRBFail(TrapBB);
127  FunctionCallee CFICheckFailFn =
128  M.getOrInsertFunction("__cfi_check_fail", Type::getVoidTy(Ctx),
130  IRBFail.CreateCall(CFICheckFailFn, {&CFICheckFailData, &Addr});
131  IRBFail.CreateBr(ExitBB);
132 
133  IRBuilder<> IRBExit(ExitBB);
134  IRBExit.CreateRetVoid();
135 
136  IRBuilder<> IRB(BB);
137  SwitchInst *SI = IRB.CreateSwitch(&CallSiteTypeId, TrapBB, TypeIds.size());
138  for (uint64_t TypeId : TypeIds) {
139  ConstantInt *CaseTypeId = ConstantInt::get(Type::getInt64Ty(Ctx), TypeId);
140  BasicBlock *TestBB = BasicBlock::Create(Ctx, "test", F);
141  IRBuilder<> IRBTest(TestBB);
142  Function *BitsetTestFn = Intrinsic::getDeclaration(&M, Intrinsic::type_test);
143 
144  Value *Test = IRBTest.CreateCall(
145  BitsetTestFn, {&Addr, MetadataAsValue::get(
146  Ctx, ConstantAsMetadata::get(CaseTypeId))});
147  BranchInst *BI = IRBTest.CreateCondBr(Test, ExitBB, TrapBB);
148  BI->setMetadata(LLVMContext::MD_prof, VeryLikelyWeights);
149 
150  SI->addCase(CaseTypeId, TestBB);
151  ++NumTypeIds;
152  }
153 }
154 
155 bool CrossDSOCFI::runOnModule(Module &M) {
156  VeryLikelyWeights =
157  MDBuilder(M.getContext()).createBranchWeights((1U << 20) - 1, 1);
158  if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
159  return false;
160  buildCFICheck(M);
161  return true;
162 }
163 
165  CrossDSOCFI Impl;
166  bool Changed = Impl.runOnModule(M);
167  if (!Changed)
168  return PreservedAnalyses::all();
169  return PreservedAnalyses::none();
170 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:1488
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:1418
llvm::Type::getInt8PtrTy
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:291
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:248
llvm::Function
Definition: Function.h:60
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:1185
Statistic.h
llvm::IRBuilder<>
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:155
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:420
GlobalObject.h
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::Instruction::setMetadata
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
Definition: Metadata.cpp:1366
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
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:27
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:141
llvm::CrossDSOCFIPass::run
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition: CrossDSOCFI.cpp:164
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:372
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:928
Align
uint64_t Align
Definition: ELFObjHandler.cpp:81
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
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:1204
CrossDSOCFI.h
uint64_t
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:78
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:58
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:65
llvm::MDNode
Metadata node.
Definition: Metadata.h:937
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:97
llvm::initializeCrossDSOCFIPass
void initializeCrossDSOCFIPass(PassRegistry &)
llvm::ifs::IFSSymbolType::Func
@ Func
llvm::NamedMDNode::operands
iterator_range< op_iterator > operands()
Definition: Metadata.h:1584
llvm::Type::getInt64Ty
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:240
llvm::MetadataAsValue::get
static MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition: Metadata.cpp:102
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
Function.h
llvm::SmallVectorImpl::clear
void clear()
Definition: SmallVector.h:591
llvm::MDBuilder
Definition: MDBuilder.h:35
llvm::Type::getVoidTy
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:222
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:42
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:3230
llvm::BranchInst
Conditional or Unconditional Branch instruction.
Definition: Instructions.h:3086
llvm::SetVector
A vector that has set insertion semantics.
Definition: SetVector.h:40
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
SetVector.h
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38