Skip to content

Commit f6a351c

Browse files
committed
pcc: add option to use the program counter for the call site identifier
1 parent 674d63f commit f6a351c

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

Transform/PCC.cpp

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <stdlib.h>
1818

1919
#include "llvm/IR/IRBuilder.h"
20+
#include "llvm/IR/InlineAsm.h"
2021
#include "llvm/IR/InstIterator.h"
2122
#include "llvm/IR/LegacyPassManager.h"
2223
#include "llvm/IR/Module.h"
@@ -31,6 +32,11 @@ namespace {
3132

3233
static const char *const PCCVarName = "__pcc_V";
3334

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+
3440
/// ProbabilisticCallingContext: instrument the code in a module to maintain a
3541
/// probabilistic unique value representing the current calling context.
3642
class ProbabilisticCallingContext : public ModulePass {
@@ -52,6 +58,15 @@ bool ProbabilisticCallingContext::runOnModule(Module &M) {
5258
// Either 32 or 64 bit depending on the target
5359
IntegerType *IntTy = DL.getIntPtrType(C);
5460

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+
5570
// PCCVar is the variable `__pcc_V` that stores the probabilistic calling
5671
// context
5772
GlobalVariable *PCCVar = new GlobalVariable(
@@ -78,23 +93,27 @@ bool ProbabilisticCallingContext::runOnModule(Module &M) {
7893
//
7994
// Note that a hash of the method name and line number are used for
8095
// `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);
92111
} else if (isa<ReturnInst>(I)) {
93112
// (3) at function return, store the local copy back into the global
94113
// variable `V` (this redundancy is helpful for correctly maintaining
95114
// `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);
98117
}
99118
}
100119
}

0 commit comments

Comments
 (0)