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"
20#include "llvm/IR/IRBuilder.h"
22#include "llvm/IR/Intrinsics.h"
23#include "llvm/IR/MDBuilder.h"
24#include "llvm/IR/Module.h"
28
29using namespace llvm;
30
31#define DEBUG_TYPE "cross-dso-cfi"
32
33STATISTIC(NumTypeIds, "Number of unique type identifiers");
34
35namespace {
36
37struct CrossDSOCFI {
38 MDNode *VeryLikelyWeights;
39
40 void buildCFICheck(Module &M);
41 bool runOnModule(Module &M);
42};
43
44} // anonymous namespace
45
46/// buildCFICheck - emits __cfi_check for the current module.
47void CrossDSOCFI::buildCFICheck(Module &M) {
48 // FIXME: verify that __cfi_check ends up near the end of the code section,
49 // but before the jump slots created in LowerTypeTests.
50 SetVector<uint64_t> TypeIds = lowertypetests::findCfiTypeIds(M);
51
52 LLVMContext &Ctx = M.getContext();
53 FunctionCallee C = M.getOrInsertFunction(
54 "__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx),
55 PointerType::getUnqual(Ctx), PointerType::getUnqual(Ctx));
56 Function *F = cast<Function>(C.getCallee());
57 // Take over the existing function. The frontend emits a weak stub so that the
58 // linker knows about the symbol; this pass replaces the function body.
59 F->deleteBody();
60 F->setAlignment(Align(4096));
61 // __cfi_check is synthesized by this pass, so there is no profile data for
62 // it.
64
65 Triple T(M.getTargetTriple());
66 if (T.isARM() || T.isThumb())
67 F->addFnAttr("target-features", "+thumb-mode");
68
69 auto args = F->arg_begin();
70 Value &CallSiteTypeId = *(args++);
71 CallSiteTypeId.setName("CallSiteTypeId");
72 Value &Addr = *(args++);
73 Addr.setName("Addr");
74 Value &CFICheckFailData = *(args++);
75 CFICheckFailData.setName("CFICheckFailData");
76 assert(args == F->arg_end());
77
78 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
79 BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
80
81 BasicBlock *TrapBB = BasicBlock::Create(Ctx, "fail", F);
82 IRBuilder<> IRBFail(TrapBB);
83 FunctionCallee CFICheckFailFn = M.getOrInsertFunction(
84 "__cfi_check_fail", Type::getVoidTy(Ctx), PointerType::getUnqual(Ctx),
85 PointerType::getUnqual(Ctx));
86 IRBFail.CreateCall(CFICheckFailFn, {&CFICheckFailData, &Addr});
87 IRBFail.CreateBr(ExitBB);
88
89 IRBuilder<> IRBExit(ExitBB);
90 IRBExit.CreateRetVoid();
91
92 IRBuilder<> IRB(BB);
93 SwitchInst *SI = IRB.CreateSwitch(&CallSiteTypeId, TrapBB, TypeIds.size());
94 // The distribution of type ids at the call sites is not known.
96 for (uint64_t TypeId : TypeIds) {
97 ConstantInt *CaseTypeId = ConstantInt::get(Type::getInt64Ty(Ctx), TypeId);
98 BasicBlock *TestBB = BasicBlock::Create(Ctx, "test", F);
99 IRBuilder<> IRBTest(TestBB);
100
101 Value *Test = IRBTest.CreateIntrinsic(
102 Intrinsic::type_test,
103 {&Addr,
105 CondBrInst *BI = IRBTest.CreateCondBr(Test, ExitBB, TrapBB);
106 BI->setMetadata(LLVMContext::MD_prof, VeryLikelyWeights);
107
108 SI->addCase(CaseTypeId, TestBB);
109 ++NumTypeIds;
110 }
111}
112
113bool CrossDSOCFI::runOnModule(Module &M) {
114 VeryLikelyWeights = MDBuilder(M.getContext()).createLikelyBranchWeights();
115 if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
116 return false;
117 buildCFICheck(M);
118 return true;
119}
120
122 CrossDSOCFI Impl;
123 bool Changed = Impl.runOnModule(M);
124 if (!Changed)
125 return PreservedAnalyses::all();
127}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned 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:107
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:394
Changed
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