xref: /aosp_15_r20/external/llvm/lib/Transforms/Utils/SanitizerStats.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- SanitizerStats.cpp - Sanitizer statistics gathering ----------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Implements code generation for sanitizer statistics gathering.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/SanitizerStats.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/ModuleUtils.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Triple.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker using namespace llvm;
24*9880d681SAndroid Build Coastguard Worker 
SanitizerStatReport(Module * M)25*9880d681SAndroid Build Coastguard Worker SanitizerStatReport::SanitizerStatReport(Module *M) : M(M) {
26*9880d681SAndroid Build Coastguard Worker   StatTy = ArrayType::get(Type::getInt8PtrTy(M->getContext()), 2);
27*9880d681SAndroid Build Coastguard Worker   EmptyModuleStatsTy = makeModuleStatsTy();
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker   ModuleStatsGV = new GlobalVariable(*M, EmptyModuleStatsTy, false,
30*9880d681SAndroid Build Coastguard Worker                                      GlobalValue::InternalLinkage, nullptr);
31*9880d681SAndroid Build Coastguard Worker }
32*9880d681SAndroid Build Coastguard Worker 
makeModuleStatsArrayTy()33*9880d681SAndroid Build Coastguard Worker ArrayType *SanitizerStatReport::makeModuleStatsArrayTy() {
34*9880d681SAndroid Build Coastguard Worker   return ArrayType::get(StatTy, Inits.size());
35*9880d681SAndroid Build Coastguard Worker }
36*9880d681SAndroid Build Coastguard Worker 
makeModuleStatsTy()37*9880d681SAndroid Build Coastguard Worker StructType *SanitizerStatReport::makeModuleStatsTy() {
38*9880d681SAndroid Build Coastguard Worker   return StructType::get(M->getContext(), {Type::getInt8PtrTy(M->getContext()),
39*9880d681SAndroid Build Coastguard Worker                                            Type::getInt32Ty(M->getContext()),
40*9880d681SAndroid Build Coastguard Worker                                            makeModuleStatsArrayTy()});
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker 
create(IRBuilder<> & B,SanitizerStatKind SK)43*9880d681SAndroid Build Coastguard Worker void SanitizerStatReport::create(IRBuilder<> &B, SanitizerStatKind SK) {
44*9880d681SAndroid Build Coastguard Worker   Function *F = B.GetInsertBlock()->getParent();
45*9880d681SAndroid Build Coastguard Worker   Module *M = F->getParent();
46*9880d681SAndroid Build Coastguard Worker   PointerType *Int8PtrTy = B.getInt8PtrTy();
47*9880d681SAndroid Build Coastguard Worker   IntegerType *IntPtrTy = B.getIntPtrTy(M->getDataLayout());
48*9880d681SAndroid Build Coastguard Worker   ArrayType *StatTy = ArrayType::get(Int8PtrTy, 2);
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker   Inits.push_back(ConstantArray::get(
51*9880d681SAndroid Build Coastguard Worker       StatTy,
52*9880d681SAndroid Build Coastguard Worker       {Constant::getNullValue(Int8PtrTy),
53*9880d681SAndroid Build Coastguard Worker        ConstantExpr::getIntToPtr(
54*9880d681SAndroid Build Coastguard Worker            ConstantInt::get(IntPtrTy, uint64_t(SK) << (IntPtrTy->getBitWidth() -
55*9880d681SAndroid Build Coastguard Worker                                                        kSanitizerStatKindBits)),
56*9880d681SAndroid Build Coastguard Worker            Int8PtrTy)}));
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker   FunctionType *StatReportTy =
59*9880d681SAndroid Build Coastguard Worker       FunctionType::get(B.getVoidTy(), Int8PtrTy, false);
60*9880d681SAndroid Build Coastguard Worker   Constant *StatReport = M->getOrInsertFunction(
61*9880d681SAndroid Build Coastguard Worker       "__sanitizer_stat_report", StatReportTy);
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker   auto InitAddr = ConstantExpr::getGetElementPtr(
64*9880d681SAndroid Build Coastguard Worker       EmptyModuleStatsTy, ModuleStatsGV,
65*9880d681SAndroid Build Coastguard Worker       ArrayRef<Constant *>{
66*9880d681SAndroid Build Coastguard Worker           ConstantInt::get(IntPtrTy, 0), ConstantInt::get(B.getInt32Ty(), 2),
67*9880d681SAndroid Build Coastguard Worker           ConstantInt::get(IntPtrTy, Inits.size() - 1),
68*9880d681SAndroid Build Coastguard Worker       });
69*9880d681SAndroid Build Coastguard Worker   B.CreateCall(StatReport, ConstantExpr::getBitCast(InitAddr, Int8PtrTy));
70*9880d681SAndroid Build Coastguard Worker }
71*9880d681SAndroid Build Coastguard Worker 
finish()72*9880d681SAndroid Build Coastguard Worker void SanitizerStatReport::finish() {
73*9880d681SAndroid Build Coastguard Worker   if (Inits.empty()) {
74*9880d681SAndroid Build Coastguard Worker     ModuleStatsGV->eraseFromParent();
75*9880d681SAndroid Build Coastguard Worker     return;
76*9880d681SAndroid Build Coastguard Worker   }
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker   PointerType *Int8PtrTy = Type::getInt8PtrTy(M->getContext());
79*9880d681SAndroid Build Coastguard Worker   IntegerType *Int32Ty = Type::getInt32Ty(M->getContext());
80*9880d681SAndroid Build Coastguard Worker   Type *VoidTy = Type::getVoidTy(M->getContext());
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker   // Create a new ModuleStatsGV to replace the old one. We can't just set the
83*9880d681SAndroid Build Coastguard Worker   // old one's initializer because its type is different.
84*9880d681SAndroid Build Coastguard Worker   auto NewModuleStatsGV = new GlobalVariable(
85*9880d681SAndroid Build Coastguard Worker       *M, makeModuleStatsTy(), false, GlobalValue::InternalLinkage,
86*9880d681SAndroid Build Coastguard Worker       ConstantStruct::getAnon(
87*9880d681SAndroid Build Coastguard Worker           {Constant::getNullValue(Int8PtrTy),
88*9880d681SAndroid Build Coastguard Worker            ConstantInt::get(Int32Ty, Inits.size()),
89*9880d681SAndroid Build Coastguard Worker            ConstantArray::get(makeModuleStatsArrayTy(), Inits)}));
90*9880d681SAndroid Build Coastguard Worker   ModuleStatsGV->replaceAllUsesWith(
91*9880d681SAndroid Build Coastguard Worker       ConstantExpr::getBitCast(NewModuleStatsGV, ModuleStatsGV->getType()));
92*9880d681SAndroid Build Coastguard Worker   ModuleStatsGV->eraseFromParent();
93*9880d681SAndroid Build Coastguard Worker 
94*9880d681SAndroid Build Coastguard Worker   // Create a global constructor to register NewModuleStatsGV.
95*9880d681SAndroid Build Coastguard Worker   auto F = Function::Create(FunctionType::get(VoidTy, false),
96*9880d681SAndroid Build Coastguard Worker                             GlobalValue::InternalLinkage, "", M);
97*9880d681SAndroid Build Coastguard Worker   auto BB = BasicBlock::Create(M->getContext(), "", F);
98*9880d681SAndroid Build Coastguard Worker   IRBuilder<> B(BB);
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker   FunctionType *StatInitTy = FunctionType::get(VoidTy, Int8PtrTy, false);
101*9880d681SAndroid Build Coastguard Worker   Constant *StatInit = M->getOrInsertFunction(
102*9880d681SAndroid Build Coastguard Worker       "__sanitizer_stat_init", StatInitTy);
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker   B.CreateCall(StatInit, ConstantExpr::getBitCast(NewModuleStatsGV, Int8PtrTy));
105*9880d681SAndroid Build Coastguard Worker   B.CreateRetVoid();
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker   appendToGlobalCtors(*M, F, 0);
108*9880d681SAndroid Build Coastguard Worker }
109