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