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