-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLLVMTutorial.cpp
More file actions
144 lines (129 loc) · 4.58 KB
/
LLVMTutorial.cpp
File metadata and controls
144 lines (129 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//===- LLVMTutorial.cpp - Skeleton code for LLVM Tutorial ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides skeleton code for a transformation that adds calls to
// every memory access operation and every branch.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/LLVMTutorial.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Type.h"
using namespace llvm;
#define DEBUG_TYPE "LLVMTutorial"
#define MEMORY_CHECK_FN "checkMemory"
//
// Create statistics that the opt and clang tools can report
//
STATISTIC(NumLoads, "Number of load instructions instrumented");
STATISTIC(NumStores, "Number of store instructions instrumented");
//
// Function: createRuntimeCheckFunc()
//
// Description:
// This function creates the declaration of the checkMemory function that
// checks the pointer dereferenced in a load or store instruction at run-time.
// If the checkMemory function is already declared or defined within the
// specified Module, a pointer to it is returned.
//
// Inputs:
// M - A reference to the Module to which the checkMemory function declaration
// should be added.
//
// Outputs:
// M - The Module modified (if necessary) to contain a checkMemory function
// declaration.
//
// Return value:
// A pointer to the checkMemory function is returned.
//
static FunctionCallee createRuntimeCheckFunc (Module & M) {
LLVMContext &C = M.getContext();
// Create the types needed for checkMemory's signature.
Type *voidTy = Type::getVoidTy(C);
// Note that LLVM does not allow creating a pointer to the void type. We need
// to create a pointer to a 8-bit integer type, which corresponds to "void *".
Type *voidPtrType = PointerType::getUnqual(IntegerType::get(C, 8));
FunctionType *FnTy = FunctionType::get(voidTy,
ArrayRef<Type *>(voidPtrType),
false
);
return M.getOrInsertFunction(MEMORY_CHECK_FN, FnTy);
}
//
// Method: visitLoadInst()
//
// Description:
// Add a call to a library function before every load instruction. This
// method is called by the InstVisitor class whenever it encounters a load
// instruction.
//
// Inputs:
// LI - A pointer to the load instruction to transform.
// checkMemoryFn - A pointer to the library function that checks for memory.
//
// Outputs:
// None.
//
// Return value:
// None
//
void LLVMTutorialPass::visitLoadInst(LoadInst *LI) {
Value *targetPtr = LI->getPointerOperand();
CallInst::Create(checkMemoryFn, ArrayRef<Value *>(targetPtr), "", LI);
++NumLoads;
}
//
// Method: visitStoreInst()
//
// Description:
// Add a call to a library function before every store instruction. This
// method is called by the InstVisitor class whenever it encounters a store
// instruction.
//
// Inputs:
// SI - A pointer to the store instruction to transform.
// checkMemoryFn - A pointer to the library function that checks for memory.
//
// Outputs:
// None.
//
// Return value:
// None
//
void LLVMTutorialPass::visitStoreInst(StoreInst *SI) {
Value *targetPtr = SI->getPointerOperand();
CallInst::Create(checkMemoryFn, ArrayRef<Value *>(targetPtr), "", SI);
++NumStores;
}
PreservedAnalyses LLVMTutorialPass::run(Module &M,
ModuleAnalysisManager &AM) {
checkMemoryFn = createRuntimeCheckFunc(M);
assert(checkMemoryFn.getCallee() && "Failed to create the prototype for checkMemoryFn");
// Scan all of the instructions within the module to determine if we need to
// transform them. If so, call the appropriate visit method to transform
// the instruction.
for (Function &F : M) {
errs() << "Instrumenting function " << F.getName() << "\n";
for (BasicBlock &BB : F) {
for (Instruction &I : BB) {
// If this is a load instruction, instrument it with a call to the
// function that checks the pointer used in the load.
if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
visitLoadInst(LI);
}
// If this is a store instruction, instrument it with a call to the
// function that checks the pointer used in the store.
if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
visitStoreInst(SI);
}
}
}
}
return PreservedAnalyses::all();
}