17
17
#include < stdlib.h>
18
18
19
19
#include " llvm/IR/IRBuilder.h"
20
+ #include " llvm/IR/InlineAsm.h"
20
21
#include " llvm/IR/InstIterator.h"
21
22
#include " llvm/IR/LegacyPassManager.h"
22
23
#include " llvm/IR/Module.h"
@@ -31,6 +32,11 @@ namespace {
31
32
32
33
static const char *const PCCVarName = " __pcc_V" ;
33
34
35
+ static cl::opt<bool > ClUseCallSitePC (
36
+ " pcc-use-call-site-pc" ,
37
+ cl::desc (" Use the program counter for the call site identifier" ),
38
+ cl::init(false ));
39
+
34
40
// / ProbabilisticCallingContext: instrument the code in a module to maintain a
35
41
// / probabilistic unique value representing the current calling context.
36
42
class ProbabilisticCallingContext : public ModulePass {
@@ -52,6 +58,15 @@ bool ProbabilisticCallingContext::runOnModule(Module &M) {
52
58
// Either 32 or 64 bit depending on the target
53
59
IntegerType *IntTy = DL.getIntPtrType (C);
54
60
61
+ // Decide on whether to use the program counter or a random integer as the
62
+ // call site identifier
63
+ InlineAsm *ReadPC = nullptr ;
64
+ if (ClUseCallSitePC) {
65
+ ReadPC = InlineAsm::get (
66
+ FunctionType::get (IntegerType::getInt64Ty (C), /* isVarArg */ false ),
67
+ " leaq (%rip), $0" , /* Constraints */ " =r" , /* hasSideEffects */ false );
68
+ }
69
+
55
70
// PCCVar is the variable `__pcc_V` that stores the probabilistic calling
56
71
// context
57
72
GlobalVariable *PCCVar = new GlobalVariable (
@@ -78,23 +93,27 @@ bool ProbabilisticCallingContext::runOnModule(Module &M) {
78
93
//
79
94
// Note that a hash of the method name and line number are used for
80
95
// `cs` in Mike Bond's original paper. Since this is C/C++ and not
81
- // Java, we just assign a random value to `cs` instead :)
82
- //
83
- // Originally I wanted to use the address of the call site, but this
84
- // would not be consistent across multiple program executions (thanks
85
- // ASLR!)
86
- ConstantInt *CS = ConstantInt::get (IntTy, random ());
87
-
88
- IRBuilder<> CallSiteIRB (I);
89
- auto *Mul = CallSiteIRB.CreateMul (ConstantInt::get (IntTy, 3 ), Temp);
90
- auto *Add = CallSiteIRB.CreateAdd (Mul, CS);
91
- CallSiteIRB.CreateStore (Add, PCCVar);
96
+ // Java, we either use the call site runtime address or assign a random
97
+ // value to `cs` instead :)
98
+ IRBuilder<> IRB (I);
99
+
100
+ Value *CS = nullptr ;
101
+ if (ReadPC) {
102
+ CS = IRB.CreateZExtOrTrunc (IRB.CreateCall (ReadPC), IntTy);
103
+ } else {
104
+ CS = ConstantInt::get (IntTy, random ());
105
+ }
106
+
107
+ assert (CS);
108
+ auto *Mul = IRB.CreateMul (ConstantInt::get (IntTy, 3 ), Temp);
109
+ auto *Add = IRB.CreateAdd (Mul, CS);
110
+ IRB.CreateStore (Add, PCCVar);
92
111
} else if (isa<ReturnInst>(I)) {
93
112
// (3) at function return, store the local copy back into the global
94
113
// variable `V` (this redundancy is helpful for correctly maintaining
95
114
// `V` in the face of exception control flow)
96
- IRBuilder<> ReturnIRB (I);
97
- ReturnIRB .CreateStore (Temp, PCCVar);
115
+ IRBuilder<> IRB (I);
116
+ IRB .CreateStore (Temp, PCCVar);
98
117
}
99
118
}
100
119
}
0 commit comments