Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/Instrumentation/InstrOrderFile.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- InstrOrderFile.cpp ---- Late IR instrumentation for order file ----===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
//===----------------------------------------------------------------------===//
11
12
#include "llvm/ADT/Statistic.h"
13
#include "llvm/IR/CallSite.h"
14
#include "llvm/IR/Constants.h"
15
#include "llvm/IR/Function.h"
16
#include "llvm/IR/GlobalValue.h"
17
#include "llvm/IR/IRBuilder.h"
18
#include "llvm/IR/Instruction.h"
19
#include "llvm/IR/Instructions.h"
20
#include "llvm/IR/Metadata.h"
21
#include "llvm/IR/Module.h"
22
#include "llvm/Pass.h"
23
#include "llvm/PassRegistry.h"
24
#include "llvm/ProfileData/InstrProf.h"
25
#include "llvm/Support/CommandLine.h"
26
#include "llvm/Support/Debug.h"
27
#include "llvm/Support/FileSystem.h"
28
#include "llvm/Support/Path.h"
29
#include "llvm/Support/raw_ostream.h"
30
#include "llvm/Transforms/Instrumentation.h"
31
#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
32
#include <fstream>
33
#include <map>
34
#include <mutex>
35
#include <set>
36
#include <sstream>
37
38
using namespace llvm;
39
#define DEBUG_TYPE "instrorderfile"
40
41
static cl::opt<std::string> ClOrderFileWriteMapping(
42
    "orderfile-write-mapping", cl::init(""),
43
    cl::desc(
44
        "Dump functions and their MD5 hash to deobfuscate profile data"),
45
    cl::Hidden);
46
47
namespace {
48
49
// We need a global bitmap to tell if a function is executed. We also
50
// need a global variable to save the order of functions. We can use a
51
// fixed-size buffer that saves the MD5 hash of the function. We need
52
// a global variable to save the index into the buffer.
53
54
std::mutex MappingMutex;
55
56
struct InstrOrderFile {
57
private:
58
  GlobalVariable *OrderFileBuffer;
59
  GlobalVariable *BufferIdx;
60
  GlobalVariable *BitMap;
61
  ArrayType *BufferTy;
62
  ArrayType *MapTy;
63
64
public:
65
2
  InstrOrderFile() {}
66
67
2
  void createOrderFileData(Module &M) {
68
2
    LLVMContext &Ctx = M.getContext();
69
2
    int NumFunctions = 0;
70
2
    for (Function &F : M) {
71
2
      if (!F.isDeclaration())
72
2
        NumFunctions++;
73
2
    }
74
2
75
2
    BufferTy =
76
2
        ArrayType::get(Type::getInt64Ty(Ctx), INSTR_ORDER_FILE_BUFFER_SIZE);
77
2
    Type *IdxTy = Type::getInt32Ty(Ctx);
78
2
    MapTy = ArrayType::get(Type::getInt8Ty(Ctx), NumFunctions);
79
2
80
2
    // Create the global variables.
81
2
    std::string SymbolName = INSTR_PROF_ORDERFILE_BUFFER_NAME_STR;
82
2
    OrderFileBuffer = new GlobalVariable(M, BufferTy, false, GlobalValue::LinkOnceODRLinkage,
83
2
                           Constant::getNullValue(BufferTy), SymbolName);
84
2
    Triple TT = Triple(M.getTargetTriple());
85
2
    OrderFileBuffer->setSection(
86
2
        getInstrProfSectionName(IPSK_orderfile, TT.getObjectFormat()));
87
2
88
2
    std::string IndexName = INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME_STR;
89
2
    BufferIdx = new GlobalVariable(M, IdxTy, false, GlobalValue::LinkOnceODRLinkage,
90
2
                           Constant::getNullValue(IdxTy), IndexName);
91
2
92
2
    std::string BitMapName = "bitmap_0";
93
2
    BitMap = new GlobalVariable(M, MapTy, false, GlobalValue::PrivateLinkage,
94
2
                                Constant::getNullValue(MapTy), BitMapName);
95
2
  }
96
97
  // Generate the code sequence in the entry block of each function to
98
  // update the buffer.
99
2
  void generateCodeSequence(Module &M, Function &F, int FuncId) {
100
2
    if (!ClOrderFileWriteMapping.empty()) {
101
0
      std::lock_guard<std::mutex> LogLock(MappingMutex);
102
0
      std::error_code EC;
103
0
      llvm::raw_fd_ostream OS(ClOrderFileWriteMapping, EC, llvm::sys::fs::F_Append);
104
0
      if (EC) {
105
0
        report_fatal_error(Twine("Failed to open ") + ClOrderFileWriteMapping +
106
0
                           " to save mapping file for order file instrumentation\n");
107
0
      } else {
108
0
        std::stringstream stream;
109
0
        stream << std::hex << MD5Hash(F.getName());
110
0
        std::string singleLine = "MD5 " + stream.str() + " " +
111
0
                                 std::string(F.getName()) + '\n';
112
0
        OS << singleLine;
113
0
      }
114
0
    }
115
2
116
2
    BasicBlock *OrigEntry = &F.getEntryBlock();
117
2
118
2
    LLVMContext &Ctx = M.getContext();
119
2
    IntegerType *Int32Ty = Type::getInt32Ty(Ctx);
120
2
    IntegerType *Int8Ty = Type::getInt8Ty(Ctx);
121
2
122
2
    // Create a new entry block for instrumentation. We will check the bitmap
123
2
    // in this basic block.
124
2
    BasicBlock *NewEntry =
125
2
        BasicBlock::Create(M.getContext(), "order_file_entry", &F, OrigEntry);
126
2
    IRBuilder<> entryB(NewEntry);
127
2
    // Create a basic block for updating the circular buffer.
128
2
    BasicBlock *UpdateOrderFileBB =
129
2
        BasicBlock::Create(M.getContext(), "order_file_set", &F, OrigEntry);
130
2
    IRBuilder<> updateB(UpdateOrderFileBB);
131
2
132
2
    // Check the bitmap, if it is already 1, do nothing.
133
2
    // Otherwise, set the bit, grab the index, update the buffer.
134
2
    Value *IdxFlags[] = {ConstantInt::get(Int32Ty, 0),
135
2
                         ConstantInt::get(Int32Ty, FuncId)};
136
2
    Value *MapAddr = entryB.CreateGEP(MapTy, BitMap, IdxFlags, "");
137
2
    LoadInst *loadBitMap = entryB.CreateLoad(Int8Ty, MapAddr, "");
138
2
    entryB.CreateStore(ConstantInt::get(Int8Ty, 1), MapAddr);
139
2
    Value *IsNotExecuted =
140
2
        entryB.CreateICmpEQ(loadBitMap, ConstantInt::get(Int8Ty, 0));
141
2
    entryB.CreateCondBr(IsNotExecuted, UpdateOrderFileBB, OrigEntry);
142
2
143
2
    // Fill up UpdateOrderFileBB: grab the index, update the buffer!
144
2
    Value *IdxVal = updateB.CreateAtomicRMW(
145
2
        AtomicRMWInst::Add, BufferIdx, ConstantInt::get(Int32Ty, 1),
146
2
        AtomicOrdering::SequentiallyConsistent);
147
2
    // We need to wrap around the index to fit it inside the buffer.
148
2
    Value *WrappedIdx = updateB.CreateAnd(
149
2
        IdxVal, ConstantInt::get(Int32Ty, INSTR_ORDER_FILE_BUFFER_MASK));
150
2
    Value *BufferGEPIdx[] = {ConstantInt::get(Int32Ty, 0), WrappedIdx};
151
2
    Value *BufferAddr =
152
2
        updateB.CreateGEP(BufferTy, OrderFileBuffer, BufferGEPIdx, "");
153
2
    updateB.CreateStore(ConstantInt::get(Type::getInt64Ty(Ctx), MD5Hash(F.getName())),
154
2
                        BufferAddr);
155
2
    updateB.CreateBr(OrigEntry);
156
2
  }
157
158
2
  bool run(Module &M) {
159
2
    createOrderFileData(M);
160
2
161
2
    int FuncId = 0;
162
2
    for (Function &F : M) {
163
2
      if (F.isDeclaration())
164
0
        continue;
165
2
      generateCodeSequence(M, F, FuncId);
166
2
      ++FuncId;
167
2
    }
168
2
169
2
    return true;
170
2
  }
171
172
}; // End of InstrOrderFile struct
173
174
class InstrOrderFileLegacyPass : public ModulePass {
175
public:
176
  static char ID;
177
178
1
  InstrOrderFileLegacyPass() : ModulePass(ID) {
179
1
    initializeInstrOrderFileLegacyPassPass(
180
1
        *PassRegistry::getPassRegistry());
181
1
  }
182
183
  bool runOnModule(Module &M) override;
184
};
185
186
} // End anonymous namespace
187
188
1
bool InstrOrderFileLegacyPass::runOnModule(Module &M) {
189
1
  if (skipModule(M))
190
0
    return false;
191
1
192
1
  return InstrOrderFile().run(M);
193
1
}
194
195
PreservedAnalyses
196
1
InstrOrderFilePass::run(Module &M, ModuleAnalysisManager &AM) {
197
1
  if (InstrOrderFile().run(M))
198
1
    return PreservedAnalyses::none();
199
0
  return PreservedAnalyses::all();
200
0
}
201
202
11.0k
INITIALIZE_PASS_BEGIN(InstrOrderFileLegacyPass, "instrorderfile",
203
11.0k
                      "Instrumentation for Order File", false, false)
204
11.0k
INITIALIZE_PASS_END(InstrOrderFileLegacyPass, "instrorderfile",
205
                    "Instrumentation for Order File", false, false)
206
207
char InstrOrderFileLegacyPass::ID = 0;
208
209
0
ModulePass *llvm::createInstrOrderFilePass() {
210
0
  return new InstrOrderFileLegacyPass();
211
0
}