Coverage Report

Created: 2024-01-17 10:31

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