LLVM  13.0.0git
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 
13 #include "llvm/ADT/Statistic.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/InitializePasses.h"
23 #include "llvm/Pass.h"
24 #include "llvm/PassRegistry.h"
27 #include "llvm/Support/Debug.h"
29 #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,
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),
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(
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 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
Instrumentation.h
Int32Ty
IntegerType * Int32Ty
Definition: NVVMIntrRange.cpp:67
llvm
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
instrorderfile
instrorderfile
Definition: InstrOrderFile.cpp:205
llvm::ARM::PredBlockMask::TT
@ TT
FileSystem.h
Metadata.h
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
llvm::Function
Definition: Function.h:61
Pass.h
Statistic.h
Path.h
llvm::IRBuilder<>
llvm::GlobalVariable
Definition: GlobalVariable.h:40
llvm::AtomicOrdering::SequentiallyConsistent
@ SequentiallyConsistent
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:158
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
Module.h
llvm::ArrayType
Class to represent array types.
Definition: DerivedTypes.h:359
llvm::Type::getInt8Ty
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:195
PassRegistry.h
llvm::Type::getInt32Ty
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:197
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
Instruction.h
CommandLine.h
llvm::InstrOrderFilePass::run
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition: InstrOrderFile.cpp:197
GlobalValue.h
ClOrderFileWriteMapping
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)
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
Constants.h
llvm::GlobalObject::setSection
void setSection(StringRef S)
Change the section for this global.
Definition: Globals.cpp:212
false
Definition: StackSlotColoring.cpp:142
llvm::MaybeAlign
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition: Alignment.h:119
llvm::IntegerType
Class to represent integer types.
Definition: DerivedTypes.h:40
InstrProf.h
llvm::report_fatal_error
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:140
llvm::ConstantInt::get
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:885
llvm::AtomicRMWInst::Add
@ Add
*p = old + v
Definition: Instructions.h:718
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
llvm::cl::opt
Definition: CommandLine.h:1422
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
FuncId
Profile::FuncID FuncId
Definition: Profile.cpp:321
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(InstrOrderFileLegacyPass, "instrorderfile", "Instrumentation for Order File", false, false) INITIALIZE_PASS_END(InstrOrderFileLegacyPass
IRBuilder.h
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::ArrayType::get
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:598
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::BasicBlock::Create
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:100
for
this could be done in SelectionDAGISel along with other special for
Definition: README.txt:104
llvm::LoadInst
An instruction for reading from memory.
Definition: Instructions.h:174
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:432
llvm::AMDGPU::HSAMD::Kernel::Key::SymbolName
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Definition: AMDGPUMetadata.h:381
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
llvm::Type::getInt64Ty
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:198
llvm::Constant::getNullValue
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:347
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
Function.h
llvm::initializeInstrOrderFileLegacyPassPass
void initializeInstrOrderFileLegacyPassPass(PassRegistry &)
llvm::getInstrProfSectionName
std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
Definition: InstrProf.cpp:174
llvm::GlobalValue::PrivateLinkage
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:56
Instructions.h
llvm::sys::fs::OF_Append
@ OF_Append
The file should be opened in append mode.
Definition: FileSystem.h:775
llvm::createInstrOrderFilePass
ModulePass * createInstrOrderFilePass()
Definition: InstrOrderFile.cpp:210
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
InstrOrderFile.h
llvm::cl::desc
Definition: CommandLine.h:414
raw_ostream.h
llvm::GlobalValue::LinkOnceODRLinkage
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:51
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
Debug.h
File
Instrumentation for Order File
Definition: InstrOrderFile.cpp:206
llvm::MD5Hash
uint64_t MD5Hash(StringRef Str)
Helper to compute and return lower 64 bits of the given string's MD5 hash.
Definition: MD5.h:109
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38