LLVM  10.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;
105  if (EC) {
106  report_fatal_error(Twine("Failed to open ") + ClOrderFileWriteMapping +
107  " to save mapping file for order file instrumentation\n");
108  } else {
109  std::stringstream stream;
110  stream << std::hex << MD5Hash(F.getName());
111  std::string singleLine = "MD5 " + stream.str() + " " +
112  std::string(F.getName()) + '\n';
113  OS << singleLine;
114  }
115  }
116 
117  BasicBlock *OrigEntry = &F.getEntryBlock();
118 
119  LLVMContext &Ctx = M.getContext();
121  IntegerType *Int8Ty = Type::getInt8Ty(Ctx);
122 
123  // Create a new entry block for instrumentation. We will check the bitmap
124  // in this basic block.
125  BasicBlock *NewEntry =
126  BasicBlock::Create(M.getContext(), "order_file_entry", &F, OrigEntry);
127  IRBuilder<> entryB(NewEntry);
128  // Create a basic block for updating the circular buffer.
129  BasicBlock *UpdateOrderFileBB =
130  BasicBlock::Create(M.getContext(), "order_file_set", &F, OrigEntry);
131  IRBuilder<> updateB(UpdateOrderFileBB);
132 
133  // Check the bitmap, if it is already 1, do nothing.
134  // Otherwise, set the bit, grab the index, update the buffer.
135  Value *IdxFlags[] = {ConstantInt::get(Int32Ty, 0),
136  ConstantInt::get(Int32Ty, FuncId)};
137  Value *MapAddr = entryB.CreateGEP(MapTy, BitMap, IdxFlags, "");
138  LoadInst *loadBitMap = entryB.CreateLoad(Int8Ty, MapAddr, "");
139  entryB.CreateStore(ConstantInt::get(Int8Ty, 1), MapAddr);
140  Value *IsNotExecuted =
141  entryB.CreateICmpEQ(loadBitMap, ConstantInt::get(Int8Ty, 0));
142  entryB.CreateCondBr(IsNotExecuted, UpdateOrderFileBB, OrigEntry);
143 
144  // Fill up UpdateOrderFileBB: grab the index, update the buffer!
145  Value *IdxVal = updateB.CreateAtomicRMW(
146  AtomicRMWInst::Add, BufferIdx, ConstantInt::get(Int32Ty, 1),
148  // We need to wrap around the index to fit it inside the buffer.
149  Value *WrappedIdx = updateB.CreateAnd(
150  IdxVal, ConstantInt::get(Int32Ty, INSTR_ORDER_FILE_BUFFER_MASK));
151  Value *BufferGEPIdx[] = {ConstantInt::get(Int32Ty, 0), WrappedIdx};
152  Value *BufferAddr =
153  updateB.CreateGEP(BufferTy, OrderFileBuffer, BufferGEPIdx, "");
154  updateB.CreateStore(ConstantInt::get(Type::getInt64Ty(Ctx), MD5Hash(F.getName())),
155  BufferAddr);
156  updateB.CreateBr(OrigEntry);
157  }
158 
159  bool run(Module &M) {
160  createOrderFileData(M);
161 
162  int FuncId = 0;
163  for (Function &F : M) {
164  if (F.isDeclaration())
165  continue;
166  generateCodeSequence(M, F, FuncId);
167  ++FuncId;
168  }
169 
170  return true;
171  }
172 
173 }; // End of InstrOrderFile struct
174 
175 class InstrOrderFileLegacyPass : public ModulePass {
176 public:
177  static char ID;
178 
179  InstrOrderFileLegacyPass() : ModulePass(ID) {
182  }
183 
184  bool runOnModule(Module &M) override;
185 };
186 
187 } // End anonymous namespace
188 
189 bool InstrOrderFileLegacyPass::runOnModule(Module &M) {
190  if (skipModule(M))
191  return false;
192 
193  return InstrOrderFile().run(M);
194 }
195 
198  if (InstrOrderFile().run(M))
199  return PreservedAnalyses::none();
200  return PreservedAnalyses::all();
201 }
202 
203 INITIALIZE_PASS_BEGIN(InstrOrderFileLegacyPass, "instrorderfile",
204  "Instrumentation for Order File", false, false)
205 INITIALIZE_PASS_END(InstrOrderFileLegacyPass, "instrorderfile",
206  "Instrumentation for Order File", false, false)
207 
208 char InstrOrderFileLegacyPass::ID = 0;
209 
211  return new InstrOrderFileLegacyPass();
212 }
Profile::FuncID FuncId
Definition: Profile.cpp:321
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:289
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:779
ModulePass * createInstrOrderFilePass()
void initializeInstrOrderFileLegacyPassPass(PassRegistry &)
Class to represent array types.
Definition: DerivedTypes.h:403
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:156
const BasicBlock & getEntryBlock() const
Definition: Function.h:664
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:40
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
The file should be opened in append mode.
Definition: FileSystem.h:771
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:653
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:384
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:175
ObjectFormatType getObjectFormat() const
getFormat - Get the object format for this triple.
Definition: Triple.h:326
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:582
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:231
LLVM Value Representation.
Definition: Value.h:73
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:215
IntegerType * Int32Ty