1 //===- bolt/Passes/Instrumentation.h ----------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This is an instrumentation pass that modifies the input binary to generate 10 // a profile after execution finishes. It can modify branches and calls to 11 // increment counters stored in the process memory. A runtime library is linked 12 // into the final binary to handle writing these counters to an fdata file. See 13 // runtime/instr.cpp 14 // 15 //===----------------------------------------------------------------------===// 16 17 #ifndef BOLT_PASSES_INSTRUMENTATION_H 18 #define BOLT_PASSES_INSTRUMENTATION_H 19 20 #include "bolt/Passes/BinaryPasses.h" 21 #include "bolt/Passes/InstrumentationSummary.h" 22 #include "llvm/Support/RWMutex.h" 23 24 namespace llvm { 25 namespace bolt { 26 27 class Instrumentation : public BinaryFunctionPass { 28 public: Instrumentation(const cl::opt<bool> & PrintPass)29 Instrumentation(const cl::opt<bool> &PrintPass) 30 : BinaryFunctionPass(PrintPass), 31 Summary(std::make_unique<InstrumentationSummary>()) {} 32 33 /// Modifies all functions by inserting instrumentation code (first step) 34 Error runOnFunctions(BinaryContext &BC) override; 35 getName()36 const char *getName() const override { return "instrumentation"; } 37 38 private: 39 void instrumentFunction(BinaryFunction &Function, 40 MCPlusBuilder::AllocatorIdTy = 0); 41 42 /// Retrieve the string table index for the name of \p Function. We encode 43 /// instrumented locations descriptions with the aid of a string table to 44 /// manage memory of the instrumentation runtime in a more efficient way. 45 /// If this function name is not represented in the string table yet, it will 46 /// be inserted and its index returned. 47 uint32_t getFunctionNameIndex(const BinaryFunction &Function); 48 49 /// Metadata creation methods 50 void createIndCallDescription(const BinaryFunction &FromFunction, 51 uint32_t From); 52 void createIndCallTargetDescription(const BinaryFunction &ToFunction, 53 uint32_t To); 54 bool createCallDescription(FunctionDescription &FuncDesc, 55 const BinaryFunction &FromFunction, uint32_t From, 56 uint32_t FromNodeID, 57 const BinaryFunction &ToFunction, uint32_t To, 58 bool IsInvoke); 59 bool createEdgeDescription(FunctionDescription &FuncDesc, 60 const BinaryFunction &FromFunction, uint32_t From, 61 uint32_t FromNodeID, 62 const BinaryFunction &ToFunction, uint32_t To, 63 uint32_t ToNodeID, bool Instrumented); 64 void createLeafNodeDescription(FunctionDescription &FuncDesc, uint32_t Node); 65 66 /// Create the sequence of instructions to increment a counter 67 InstructionListType createInstrumentationSnippet(BinaryContext &BC, 68 bool IsLeaf); 69 70 // Critical edges worklist 71 // This worklist keeps track of CFG edges <From-To> that needs to be split. 72 // This task is deferred until we finish processing all BBs because we can't 73 // modify the CFG while iterating over it. For each edge, \p SplitInstrsTy 74 // stores the list of instrumentation instructions as a vector of MCInsts. 75 // instrumentOneTarget() populates this, instrumentFunction() consumes. 76 using SplitWorklistTy = 77 std::vector<std::pair<BinaryBasicBlock *, BinaryBasicBlock *>>; 78 using SplitInstrsTy = std::vector<InstructionListType>; 79 80 /// Instrument the branch or call in \p Iter. \p TargetBB should be non-null 81 /// if this is a local branch and null if it is a call. Return true if the 82 /// location was instrumented with an explicit counter or false if it just 83 /// created the description, but no explicit counters were necessary. 84 bool instrumentOneTarget(SplitWorklistTy &SplitWorklist, 85 SplitInstrsTy &SplitInstrs, 86 BinaryBasicBlock::iterator &Iter, 87 BinaryFunction &FromFunction, 88 BinaryBasicBlock &FromBB, uint32_t From, 89 BinaryFunction &ToFunc, BinaryBasicBlock *TargetBB, 90 uint32_t ToOffset, bool IsLeaf, bool IsInvoke, 91 FunctionDescription *FuncDesc, uint32_t FromNodeID, 92 uint32_t ToNodeID = 0); 93 94 void instrumentLeafNode(BinaryBasicBlock &BB, BinaryBasicBlock::iterator Iter, 95 bool IsLeaf, FunctionDescription &FuncDesc, 96 uint32_t Node); 97 98 void instrumentIndirectTarget(BinaryBasicBlock &BB, 99 BinaryBasicBlock::iterator &Iter, 100 BinaryFunction &FromFunction, uint32_t From); 101 102 void createAuxiliaryFunctions(BinaryContext &BC); 103 104 uint32_t getFDSize() const; 105 106 /// Create a runtime library, pass the BinData over, and register it 107 /// under \p BC. 108 void setupRuntimeLibrary(BinaryContext &BC); 109 110 /// strtab indices in StringTable for each function name 111 std::unordered_map<const BinaryFunction *, uint32_t> FuncToStringIdx; 112 113 mutable llvm::sys::RWMutex FDMutex; 114 115 /// The data generated during Instrumentation pass that needs to 116 /// be passed to the Instrument runtime library. 117 std::unique_ptr<InstrumentationSummary> Summary; 118 119 /// Statistics on counters 120 uint32_t DirectCallCounters{0}; 121 uint32_t BranchCounters{0}; 122 uint32_t LeafNodeCounters{0}; 123 124 /// Indirect call instrumentation functions 125 BinaryFunction *IndCallHandlerExitBBFunction; 126 BinaryFunction *IndTailCallHandlerExitBBFunction; 127 }; 128 } // namespace bolt 129 } // namespace llvm 130 131 #endif 132