LLVM  9.0.0svn
InstrOrderFile.cpp
Go to the documentation of this file.
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"
26 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/Path.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 
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  InstrOrderFile() {}
66 
67  void createOrderFileData(Module &M) {
68  LLVMContext &Ctx = M.getContext();
69  int NumFunctions = 0;
70  for (Function &F : M) {
71  if (!F.isDeclaration())
72  NumFunctions++;
73  }
74 
75  BufferTy =
76  ArrayType::get(Type::getInt64Ty(Ctx), INSTR_ORDER_FILE_BUFFER_SIZE);
77  Type *IdxTy = Type::getInt32Ty(Ctx);
78  MapTy = ArrayType::get(Type::getInt8Ty(Ctx), NumFunctions);
79 
80  // Create the global variables.
81  std::string SymbolName = INSTR_PROF_ORDERFILE_BUFFER_NAME_STR;
82  OrderFileBuffer = new GlobalVariable(M, BufferTy, false, GlobalValue::LinkOnceODRLinkage,
83  Constant::getNullValue(BufferTy), SymbolName);
84  Triple TT = Triple(M.getTargetTriple());
85  OrderFileBuffer->setSection(
86  getInstrProfSectionName(IPSK_orderfile, TT.getObjectFormat()));
87 
88  std::string IndexName = INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME_STR;
89  BufferIdx = new GlobalVariable(M, IdxTy, false, GlobalValue::LinkOnceODRLinkage,
90  Constant::getNullValue(IdxTy), IndexName);
91 
92  std::string BitMapName = "bitmap_0";
93  BitMap = new GlobalVariable(M, MapTy, false, GlobalValue::PrivateLinkage,
94  Constant::getNullValue(MapTy), BitMapName);
95  }
96 
97  // Generate the code sequence in the entry block of each function to
98  // update the buffer.
99  void generateCodeSequence(Module &M, Function &F, int FuncId) {
100  if (!ClOrderFileWriteMapping.empty()) {
101  std::lock_guard<std::mutex> LogLock(MappingMutex);
102  std::error_code EC;
104  if (EC) {
105  report_fatal_error(Twine("Failed to open ") + ClOrderFileWriteMapping +
106  " to save mapping file for order file instrumentation\n");
107  } else {
108  std::stringstream stream;
109  stream << std::hex << MD5Hash(F.getName());
110  std::string singleLine = "MD5 " + stream.str() + " " +
111  std::string(F.getName()) + '\n';
112  OS << singleLine;
113  }
114  }
115 
116  BasicBlock *OrigEntry = &F.getEntryBlock();
117 
118  LLVMContext &Ctx = M.getContext();
120  IntegerType *Int8Ty = Type::getInt8Ty(Ctx);
121 
122  // Create a new entry block for instrumentation. We will check the bitmap
123  // in this basic block.
124  BasicBlock *NewEntry =
125  BasicBlock::Create(M.getContext(), "order_file_entry", &F, OrigEntry);
126  IRBuilder<> entryB(NewEntry);
127  // Create a basic block for updating the circular buffer.
128  BasicBlock *UpdateOrderFileBB =
129  BasicBlock::Create(M.getContext(), "order_file_set", &F, OrigEntry);
130  IRBuilder<> updateB(UpdateOrderFileBB);
131 
132  // Check the bitmap, if it is already 1, do nothing.
133  // Otherwise, set the bit, grab the index, update the buffer.
134  Value *IdxFlags[] = {ConstantInt::get(Int32Ty, 0),
135  ConstantInt::get(Int32Ty, FuncId)};
136  Value *MapAddr = entryB.CreateGEP(MapTy, BitMap, IdxFlags, "");
137  LoadInst *loadBitMap = entryB.CreateLoad(Int8Ty, MapAddr, "");
138  entryB.CreateStore(ConstantInt::get(Int8Ty, 1), MapAddr);
139  Value *IsNotExecuted =
140  entryB.CreateICmpEQ(loadBitMap, ConstantInt::get(Int8Ty, 0));
141  entryB.CreateCondBr(IsNotExecuted, UpdateOrderFileBB, OrigEntry);
142 
143  // Fill up UpdateOrderFileBB: grab the index, update the buffer!
144  Value *IdxVal = updateB.CreateAtomicRMW(
145  AtomicRMWInst::Add, BufferIdx, ConstantInt::get(Int32Ty, 1),
147  // We need to wrap around the index to fit it inside the buffer.
148  Value *WrappedIdx = updateB.CreateAnd(
149  IdxVal, ConstantInt::get(Int32Ty, INSTR_ORDER_FILE_BUFFER_MASK));
150  Value *BufferGEPIdx[] = {ConstantInt::get(Int32Ty, 0), WrappedIdx};
151  Value *BufferAddr =
152  updateB.CreateGEP(BufferTy, OrderFileBuffer, BufferGEPIdx, "");
153  updateB.CreateStore(ConstantInt::get(Type::getInt64Ty(Ctx), MD5Hash(F.getName())),
154  BufferAddr);
155  updateB.CreateBr(OrigEntry);
156  }
157 
158  bool run(Module &M) {
159  createOrderFileData(M);
160 
161  int FuncId = 0;
162  for (Function &F : M) {
163  if (F.isDeclaration())
164  continue;
165  generateCodeSequence(M, F, FuncId);
166  ++FuncId;
167  }
168 
169  return true;
170  }
171 
172 }; // End of InstrOrderFile struct
173 
174 class InstrOrderFileLegacyPass : public ModulePass {
175 public:
176  static char ID;
177 
178  InstrOrderFileLegacyPass() : ModulePass(ID) {
181  }
182 
183  bool runOnModule(Module &M) override;
184 };
185 
186 } // End anonymous namespace
187 
188 bool InstrOrderFileLegacyPass::runOnModule(Module &M) {
189  if (skipModule(M))
190  return false;
191 
192  return InstrOrderFile().run(M);
193 }
194 
197  if (InstrOrderFile().run(M))
198  return PreservedAnalyses::none();
199  return PreservedAnalyses::all();
200 }
201 
202 INITIALIZE_PASS_BEGIN(InstrOrderFileLegacyPass, "instrorderfile",
203  "Instrumentation for Order File", false, false)
204 INITIALIZE_PASS_END(InstrOrderFileLegacyPass, "instrorderfile",
205  "Instrumentation for Order File", false, false)
206 
207 char InstrOrderFileLegacyPass::ID = 0;
208 
210  return new InstrOrderFileLegacyPass();
211 }
Profile::FuncID FuncId
Definition: Profile.cpp:320
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
INITIALIZE_PASS_BEGIN(InstrOrderFileLegacyPass, "instrorderfile", "Instrumentation for Order File", false, false) INITIALIZE_PASS_END(InstrOrderFileLegacyPass
This file contains the declarations for metadata subclasses.
uint64_t MD5Hash(StringRef Str)
Helper to compute and return lower 64 bits of the given string&#39;s MD5 hash.
Definition: MD5.h:109
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:56
std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
Definition: InstrProf.cpp:165
F(f)
An instruction for reading from memory.
Definition: Instructions.h:167
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:176
static Constant * getNullValue(Type *Ty)
Constructor to create a &#39;0&#39; constant of arbitrary type.
Definition: Constants.cpp:274
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:244
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:742
ModulePass * createInstrOrderFilePass()
void initializeInstrOrderFileLegacyPassPass(PassRegistry &)
Class to represent array types.
Definition: DerivedTypes.h:400
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:156
const BasicBlock & getEntryBlock() const
Definition: Function.h:645
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:51
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:153
LLVM Basic Block Representation.
Definition: BasicBlock.h:57
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:64
Instrumentation for Order File
static cl::opt< std::string > ClOrderFileWriteMapping("orderfile-write-mapping", cl::init(""), cl::desc("Dump functions and their MD5 hash to deobfuscate profile data"), cl::Hidden)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:99
Class to represent integer types.
Definition: DerivedTypes.h:39
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:159
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:43
Module.h This file contains the declarations for the Module class.
instrorderfile
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:631
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:365
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:175
ObjectFormatType getObjectFormat() const
getFormat - Get the object format for this triple.
Definition: Triple.h:322
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:224
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:580
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:205
LLVM Value Representation.
Definition: Value.h:72
A container for analyses that lazily runs them and caches their results.
for(unsigned i=Desc.getNumOperands(), e=OldMI.getNumOperands();i !=e;++i)
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:173
void setSection(StringRef S)
Change the section for this global.
Definition: Globals.cpp:188
IntegerType * Int32Ty