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"
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
61 Triple T(M.getTargetTriple());
62 if (T.isARM() || T.isThumb())
63 F->addFnAttr("target-features", "+thumb-mode");
64
65 auto args = F->arg_begin();
66 Value &CallSiteTypeId = *(args++);
67 CallSiteTypeId.setName("CallSiteTypeId");
68 Value &Addr = *(args++);
69 Addr.setName("Addr");
70 Value &CFICheckFailData = *(args++);
71 CFICheckFailData.setName("CFICheckFailData");
72 assert(args == F->arg_end());
73
74 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
75 BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
76
77 BasicBlock *TrapBB = BasicBlock::Create(Ctx, "fail", F);
78 IRBuilder<> IRBFail(TrapBB);
79 FunctionCallee CFICheckFailFn = M.getOrInsertFunction(
80 "__cfi_check_fail", Type::getVoidTy(Ctx), PointerType::getUnqual(Ctx),
81 PointerType::getUnqual(Ctx));
82 IRBFail.CreateCall(CFICheckFailFn, {&CFICheckFailData, &Addr});
83 IRBFail.CreateBr(ExitBB);
84
85 IRBuilder<> IRBExit(ExitBB);
86 IRBExit.CreateRetVoid();
87
88 IRBuilder<> IRB(BB);
89 SwitchInst *SI = IRB.CreateSwitch(&CallSiteTypeId, TrapBB, TypeIds.size());
90 for (uint64_t TypeId : TypeIds) {
91 ConstantInt *CaseTypeId = ConstantInt::get(Type::getInt64Ty(Ctx), TypeId);
92 BasicBlock *TestBB = BasicBlock::Create(Ctx, "test", F);
93 IRBuilder<> IRBTest(TestBB);
94
95 Value *Test = IRBTest.CreateIntrinsic(
96 Intrinsic::type_test,
97 {&Addr,
99 CondBrInst *BI = IRBTest.CreateCondBr(Test, ExitBB, TrapBB);
100 BI->setMetadata(LLVMContext::MD_prof, VeryLikelyWeights);
101
102 SI->addCase(CaseTypeId, TestBB);
103 ++NumTypeIds;
104 }
105}
106
107bool CrossDSOCFI::runOnModule(Module &M) {
108 VeryLikelyWeights = MDBuilder(M.getContext()).createLikelyBranchWeights();
109 if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
110 return false;
111 buildCFICheck(M);
112 return true;
113}
114
116 CrossDSOCFI Impl;
117 bool Changed = Impl.runOnModule(M);
118 if (!Changed)
119 return PreservedAnalyses::all();
121}
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...
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 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:81
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
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