LLVM 24.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/IR/Constants.h"
18#include "llvm/IR/Function.h"
19#include "llvm/IR/IRBuilder.h"
21#include "llvm/IR/Intrinsics.h"
22#include "llvm/IR/MDBuilder.h"
23#include "llvm/IR/Module.h"
27
28using namespace llvm;
29
30#define DEBUG_TYPE "cross-dso-cfi"
31
32STATISTIC(NumTypeIds, "Number of unique type identifiers");
33
34namespace {
35
36struct CrossDSOCFI {
37 MDNode *VeryLikelyWeights;
38
39 void buildCFICheck(Module &M);
40 bool runOnModule(Module &M);
41};
42
43} // anonymous namespace
44
45/// buildCFICheck - emits __cfi_check for the current module.
46void CrossDSOCFI::buildCFICheck(Module &M) {
47 // FIXME: verify that __cfi_check ends up near the end of the code section,
48 // but before the jump slots created in LowerTypeTests.
49 SetVector<uint64_t> TypeIds = lowertypetests::findCfiTypeIds(M);
50
51 LLVMContext &Ctx = M.getContext();
52 FunctionCallee C = M.getOrInsertFunction(
53 "__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx),
54 PointerType::getUnqual(Ctx), PointerType::getUnqual(Ctx));
55 Function *F = cast<Function>(C.getCallee());
56 // Take over the existing function. The frontend emits a weak stub so that the
57 // linker knows about the symbol; this pass replaces the function body.
58 F->deleteBody();
59 F->setAlignment(Align(4096));
60 // __cfi_check is synthesized by this pass, so there is no profile data for
61 // it.
63
64 Triple T(M.getTargetTriple());
65 if (T.isARM() || T.isThumb())
66 F->addFnAttr("target-features", "+thumb-mode");
67
68 auto args = F->arg_begin();
69 Value &CallSiteTypeId = *(args++);
70 CallSiteTypeId.setName("CallSiteTypeId");
71 Value &Addr = *(args++);
72 Addr.setName("Addr");
73 Value &CFICheckFailData = *(args++);
74 CFICheckFailData.setName("CFICheckFailData");
75 assert(args == F->arg_end());
76
77 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
78 BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
79
80 BasicBlock *TrapBB = BasicBlock::Create(Ctx, "fail", F);
81 IRBuilder<> IRBFail(TrapBB);
82 FunctionCallee CFICheckFailFn = M.getOrInsertFunction(
83 "__cfi_check_fail", Type::getVoidTy(Ctx), PointerType::getUnqual(Ctx),
84 PointerType::getUnqual(Ctx));
85 IRBFail.CreateCall(CFICheckFailFn, {&CFICheckFailData, &Addr});
86 IRBFail.CreateBr(ExitBB);
87
88 IRBuilder<> IRBExit(ExitBB);
89 IRBExit.CreateRetVoid();
90
91 IRBuilder<> IRB(BB);
92 SwitchInst *SI = IRB.CreateSwitch(&CallSiteTypeId, TrapBB, TypeIds.size());
93 // The distribution of type ids at the call sites is not known.
95 for (uint64_t TypeId : TypeIds) {
96 ConstantInt *CaseTypeId = ConstantInt::get(Type::getInt64Ty(Ctx), TypeId);
97 BasicBlock *TestBB = BasicBlock::Create(Ctx, "test", F);
98 IRBuilder<> IRBTest(TestBB);
99
100 Value *Test = IRBTest.CreateIntrinsic(
101 Intrinsic::type_test,
102 {&Addr,
104 CondBrInst *BI = IRBTest.CreateCondBr(Test, ExitBB, TrapBB);
105 BI->setMetadata(LLVMContext::MD_prof, VeryLikelyWeights);
106
107 SI->addCase(CaseTypeId, TestBB);
108 ++NumTypeIds;
109 }
110}
111
112bool CrossDSOCFI::runOnModule(Module &M) {
113 VeryLikelyWeights = MDBuilder(M.getContext()).createLikelyBranchWeights();
114 if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
115 return false;
116 buildCFICheck(M);
117 return true;
118}
119
121 CrossDSOCFI Impl;
122 bool Changed = Impl.runOnModule(M);
123 if (!Changed)
124 return PreservedAnalyses::all();
126}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
Machine Check Debug Module
#define T
nvptx lower args
This file contains the declarations for profiling metadata utility functions.
This file implements a set that has insertion order iteration characteristics.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:548
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
Metadata node.
Definition Metadata.h:1081
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:105
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:389
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
LLVM_ABI SetVector< uint64_t > findCfiTypeIds(const Module &M)
Finds all 64-bit numeric type identifiers in M used for cross-DSO CFI.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void setExplicitlyUnknownBranchWeights(Instruction &I, StringRef PassName)
Specify that the branch weights for this terminator cannot be known at compile time.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void setExplicitlyUnknownFunctionEntryCount(Function &F, StringRef PassName)
Analogous to setExplicitlyUnknownBranchWeights, but for functions and their entry counts.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39