xref: /llvm-project/bolt/lib/Passes/Instrumentation.cpp (revision be2f67c4d87deb513ba200ab3f4dba385faf709a)
1 //===- bolt/Passes/Instrumentation.cpp ------------------------------------===//
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 file implements the Instrumentation class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "bolt/Passes/Instrumentation.h"
14 #include "bolt/Core/ParallelUtilities.h"
15 #include "bolt/RuntimeLibs/InstrumentationRuntimeLibrary.h"
16 #include "bolt/Utils/Utils.h"
17 #include "llvm/Support/CommandLine.h"
18 #include "llvm/Support/RWMutex.h"
19 #include <stack>
20 
21 #define DEBUG_TYPE "bolt-instrumentation"
22 
23 using namespace llvm;
24 
25 namespace opts {
26 extern cl::OptionCategory BoltInstrCategory;
27 
28 cl::opt<std::string> InstrumentationFilename(
29     "instrumentation-file",
30     cl::desc("file name where instrumented profile will be saved (default: "
31              "/tmp/prof.fdata)"),
32     cl::init("/tmp/prof.fdata"), cl::Optional, cl::cat(BoltInstrCategory));
33 
34 cl::opt<std::string> InstrumentationBinpath(
35     "instrumentation-binpath",
36     cl::desc("path to instumented binary in case if /proc/self/map_files "
37              "is not accessible due to access restriction issues"),
38     cl::Optional, cl::cat(BoltInstrCategory));
39 
40 cl::opt<bool> InstrumentationFileAppendPID(
41     "instrumentation-file-append-pid",
42     cl::desc("append PID to saved profile file name (default: false)"),
43     cl::init(false), cl::Optional, cl::cat(BoltInstrCategory));
44 
45 cl::opt<bool> ConservativeInstrumentation(
46     "conservative-instrumentation",
47     cl::desc("disable instrumentation optimizations that sacrifice profile "
48              "accuracy (for debugging, default: false)"),
49     cl::init(false), cl::Optional, cl::cat(BoltInstrCategory));
50 
51 cl::opt<uint32_t> InstrumentationSleepTime(
52     "instrumentation-sleep-time",
53     cl::desc("interval between profile writes (default: 0 = write only at "
54              "program end).  This is useful for service workloads when you "
55              "want to dump profile every X minutes or if you are killing the "
56              "program and the profile is not being dumped at the end."),
57     cl::init(0), cl::Optional, cl::cat(BoltInstrCategory));
58 
59 cl::opt<bool> InstrumentationNoCountersClear(
60     "instrumentation-no-counters-clear",
61     cl::desc("Don't clear counters across dumps "
62              "(use with instrumentation-sleep-time option)"),
63     cl::init(false), cl::Optional, cl::cat(BoltInstrCategory));
64 
65 cl::opt<bool> InstrumentationWaitForks(
66     "instrumentation-wait-forks",
67     cl::desc("Wait until all forks of instrumented process will finish "
68              "(use with instrumentation-sleep-time option)"),
69     cl::init(false), cl::Optional, cl::cat(BoltInstrCategory));
70 
71 cl::opt<bool>
72     InstrumentHotOnly("instrument-hot-only",
73                       cl::desc("only insert instrumentation on hot functions "
74                                "(needs profile, default: false)"),
75                       cl::init(false), cl::Optional,
76                       cl::cat(BoltInstrCategory));
77 
78 cl::opt<bool> InstrumentCalls("instrument-calls",
79                               cl::desc("record profile for inter-function "
80                                        "control flow activity (default: true)"),
81                               cl::init(true), cl::Optional,
82                               cl::cat(BoltInstrCategory));
83 } // namespace opts
84 
85 namespace llvm {
86 namespace bolt {
87 
88 uint32_t Instrumentation::getFunctionNameIndex(const BinaryFunction &Function) {
89   auto Iter = FuncToStringIdx.find(&Function);
90   if (Iter != FuncToStringIdx.end())
91     return Iter->second;
92   size_t Idx = Summary->StringTable.size();
93   FuncToStringIdx.emplace(std::make_pair(&Function, Idx));
94   Summary->StringTable.append(getEscapedName(Function.getOneName()));
95   Summary->StringTable.append(1, '\0');
96   return Idx;
97 }
98 
99 bool Instrumentation::createCallDescription(FunctionDescription &FuncDesc,
100                                             const BinaryFunction &FromFunction,
101                                             uint32_t From, uint32_t FromNodeID,
102                                             const BinaryFunction &ToFunction,
103                                             uint32_t To, bool IsInvoke) {
104   CallDescription CD;
105   // Ordinarily, we don't augment direct calls with an explicit counter, except
106   // when forced to do so or when we know this callee could be throwing
107   // exceptions, in which case there is no other way to accurately record its
108   // frequency.
109   bool ForceInstrumentation = opts::ConservativeInstrumentation || IsInvoke;
110   CD.FromLoc.FuncString = getFunctionNameIndex(FromFunction);
111   CD.FromLoc.Offset = From;
112   CD.FromNode = FromNodeID;
113   CD.Target = &ToFunction;
114   CD.ToLoc.FuncString = getFunctionNameIndex(ToFunction);
115   CD.ToLoc.Offset = To;
116   CD.Counter = ForceInstrumentation ? Summary->Counters.size() : 0xffffffff;
117   if (ForceInstrumentation)
118     ++DirectCallCounters;
119   FuncDesc.Calls.emplace_back(CD);
120   return ForceInstrumentation;
121 }
122 
123 void Instrumentation::createIndCallDescription(
124     const BinaryFunction &FromFunction, uint32_t From) {
125   IndCallDescription ICD;
126   ICD.FromLoc.FuncString = getFunctionNameIndex(FromFunction);
127   ICD.FromLoc.Offset = From;
128   Summary->IndCallDescriptions.emplace_back(ICD);
129 }
130 
131 void Instrumentation::createIndCallTargetDescription(
132     const BinaryFunction &ToFunction, uint32_t To) {
133   IndCallTargetDescription ICD;
134   ICD.ToLoc.FuncString = getFunctionNameIndex(ToFunction);
135   ICD.ToLoc.Offset = To;
136   ICD.Target = &ToFunction;
137   Summary->IndCallTargetDescriptions.emplace_back(ICD);
138 }
139 
140 bool Instrumentation::createEdgeDescription(FunctionDescription &FuncDesc,
141                                             const BinaryFunction &FromFunction,
142                                             uint32_t From, uint32_t FromNodeID,
143                                             const BinaryFunction &ToFunction,
144                                             uint32_t To, uint32_t ToNodeID,
145                                             bool Instrumented) {
146   EdgeDescription ED;
147   auto Result = FuncDesc.EdgesSet.insert(std::make_pair(FromNodeID, ToNodeID));
148   // Avoid creating duplicated edge descriptions. This happens in CFGs where a
149   // block jumps to its fall-through.
150   if (Result.second == false)
151     return false;
152   ED.FromLoc.FuncString = getFunctionNameIndex(FromFunction);
153   ED.FromLoc.Offset = From;
154   ED.FromNode = FromNodeID;
155   ED.ToLoc.FuncString = getFunctionNameIndex(ToFunction);
156   ED.ToLoc.Offset = To;
157   ED.ToNode = ToNodeID;
158   ED.Counter = Instrumented ? Summary->Counters.size() : 0xffffffff;
159   if (Instrumented)
160     ++BranchCounters;
161   FuncDesc.Edges.emplace_back(ED);
162   return Instrumented;
163 }
164 
165 void Instrumentation::createLeafNodeDescription(FunctionDescription &FuncDesc,
166                                                 uint32_t Node) {
167   InstrumentedNode IN;
168   IN.Node = Node;
169   IN.Counter = Summary->Counters.size();
170   ++LeafNodeCounters;
171   FuncDesc.LeafNodes.emplace_back(IN);
172 }
173 
174 InstructionListType
175 Instrumentation::createInstrumentationSnippet(BinaryContext &BC, bool IsLeaf) {
176   auto L = BC.scopeLock();
177   MCSymbol *Label;
178   Label = BC.Ctx->createNamedTempSymbol("InstrEntry");
179   Summary->Counters.emplace_back(Label);
180   InstructionListType CounterInstrs;
181   BC.MIB->createInstrIncMemory(CounterInstrs, Label, &*BC.Ctx, IsLeaf);
182   return CounterInstrs;
183 }
184 
185 // Helper instruction sequence insertion function
186 static BinaryBasicBlock::iterator
187 insertInstructions(InstructionListType &Instrs, BinaryBasicBlock &BB,
188                    BinaryBasicBlock::iterator Iter) {
189   for (MCInst &NewInst : Instrs) {
190     Iter = BB.insertInstruction(Iter, NewInst);
191     ++Iter;
192   }
193   return Iter;
194 }
195 
196 void Instrumentation::instrumentLeafNode(BinaryBasicBlock &BB,
197                                          BinaryBasicBlock::iterator Iter,
198                                          bool IsLeaf,
199                                          FunctionDescription &FuncDesc,
200                                          uint32_t Node) {
201   createLeafNodeDescription(FuncDesc, Node);
202   InstructionListType CounterInstrs = createInstrumentationSnippet(
203       BB.getFunction()->getBinaryContext(), IsLeaf);
204   insertInstructions(CounterInstrs, BB, Iter);
205 }
206 
207 void Instrumentation::instrumentIndirectTarget(BinaryBasicBlock &BB,
208                                                BinaryBasicBlock::iterator &Iter,
209                                                BinaryFunction &FromFunction,
210                                                uint32_t From) {
211   auto L = FromFunction.getBinaryContext().scopeLock();
212   const size_t IndCallSiteID = Summary->IndCallDescriptions.size();
213   createIndCallDescription(FromFunction, From);
214 
215   BinaryContext &BC = FromFunction.getBinaryContext();
216   bool IsTailCall = BC.MIB->isTailCall(*Iter);
217   InstructionListType CounterInstrs = BC.MIB->createInstrumentedIndirectCall(
218       *Iter, IsTailCall,
219       IsTailCall ? IndTailCallHandlerExitBBFunction->getSymbol()
220                  : IndCallHandlerExitBBFunction->getSymbol(),
221       IndCallSiteID, &*BC.Ctx);
222 
223   Iter = BB.eraseInstruction(Iter);
224   Iter = insertInstructions(CounterInstrs, BB, Iter);
225   --Iter;
226 }
227 
228 bool Instrumentation::instrumentOneTarget(
229     SplitWorklistTy &SplitWorklist, SplitInstrsTy &SplitInstrs,
230     BinaryBasicBlock::iterator &Iter, BinaryFunction &FromFunction,
231     BinaryBasicBlock &FromBB, uint32_t From, BinaryFunction &ToFunc,
232     BinaryBasicBlock *TargetBB, uint32_t ToOffset, bool IsLeaf, bool IsInvoke,
233     FunctionDescription *FuncDesc, uint32_t FromNodeID, uint32_t ToNodeID) {
234   {
235     auto L = FromFunction.getBinaryContext().scopeLock();
236     bool Created = true;
237     if (!TargetBB)
238       Created = createCallDescription(*FuncDesc, FromFunction, From, FromNodeID,
239                                       ToFunc, ToOffset, IsInvoke);
240     else
241       Created = createEdgeDescription(*FuncDesc, FromFunction, From, FromNodeID,
242                                       ToFunc, ToOffset, ToNodeID,
243                                       /*Instrumented=*/true);
244     if (!Created)
245       return false;
246   }
247 
248   InstructionListType CounterInstrs =
249       createInstrumentationSnippet(FromFunction.getBinaryContext(), IsLeaf);
250 
251   BinaryContext &BC = FromFunction.getBinaryContext();
252   const MCInst &Inst = *Iter;
253   if (BC.MIB->isCall(Inst)) {
254     // This code handles both
255     // - (regular) inter-function calls (cross-function control transfer),
256     // - (rare) intra-function calls (function-local control transfer)
257     Iter = insertInstructions(CounterInstrs, FromBB, Iter);
258     return true;
259   }
260 
261   if (!TargetBB || !FuncDesc)
262     return false;
263 
264   // Indirect branch, conditional branches or fall-throughs
265   // Regular cond branch, put counter at start of target block
266   //
267   // N.B.: (FromBB != TargetBBs) checks below handle conditional jumps where
268   // we can't put the instrumentation counter in this block because not all
269   // paths that reach it at this point will be taken and going to the target.
270   if (TargetBB->pred_size() == 1 && &FromBB != TargetBB &&
271       !TargetBB->isEntryPoint()) {
272     insertInstructions(CounterInstrs, *TargetBB, TargetBB->begin());
273     return true;
274   }
275   if (FromBB.succ_size() == 1 && &FromBB != TargetBB) {
276     Iter = insertInstructions(CounterInstrs, FromBB, Iter);
277     return true;
278   }
279   // Critical edge, create BB and put counter there
280   SplitWorklist.emplace_back(&FromBB, TargetBB);
281   SplitInstrs.emplace_back(std::move(CounterInstrs));
282   return true;
283 }
284 
285 void Instrumentation::instrumentFunction(BinaryFunction &Function,
286                                          MCPlusBuilder::AllocatorIdTy AllocId) {
287   if (Function.hasUnknownControlFlow())
288     return;
289 
290   BinaryContext &BC = Function.getBinaryContext();
291   if (BC.isMachO() && Function.hasName("___GLOBAL_init_65535/1"))
292     return;
293 
294   SplitWorklistTy SplitWorklist;
295   SplitInstrsTy SplitInstrs;
296 
297   FunctionDescription *FuncDesc = nullptr;
298   {
299     std::unique_lock<llvm::sys::RWMutex> L(FDMutex);
300     Summary->FunctionDescriptions.emplace_back();
301     FuncDesc = &Summary->FunctionDescriptions.back();
302   }
303 
304   FuncDesc->Function = &Function;
305   Function.disambiguateJumpTables(AllocId);
306   Function.deleteConservativeEdges();
307 
308   std::unordered_map<const BinaryBasicBlock *, uint32_t> BBToID;
309   uint32_t Id = 0;
310   for (auto BBI = Function.begin(); BBI != Function.end(); ++BBI) {
311     BBToID[&*BBI] = Id++;
312   }
313   std::unordered_set<const BinaryBasicBlock *> VisitedSet;
314   // DFS to establish edges we will use for a spanning tree. Edges in the
315   // spanning tree can be instrumentation-free since their count can be
316   // inferred by solving flow equations on a bottom-up traversal of the tree.
317   // Exit basic blocks are always instrumented so we start the traversal with
318   // a minimum number of defined variables to make the equation solvable.
319   std::stack<std::pair<const BinaryBasicBlock *, BinaryBasicBlock *>> Stack;
320   std::unordered_map<const BinaryBasicBlock *,
321                      std::set<const BinaryBasicBlock *>>
322       STOutSet;
323   for (auto BBI = Function.getLayout().block_rbegin();
324        BBI != Function.getLayout().block_rend(); ++BBI) {
325     if ((*BBI)->isEntryPoint() || (*BBI)->isLandingPad()) {
326       Stack.push(std::make_pair(nullptr, *BBI));
327       if (opts::InstrumentCalls && (*BBI)->isEntryPoint()) {
328         EntryNode E;
329         E.Node = BBToID[&**BBI];
330         E.Address = (*BBI)->getInputOffset();
331         FuncDesc->EntryNodes.emplace_back(E);
332         createIndCallTargetDescription(Function, (*BBI)->getInputOffset());
333       }
334     }
335   }
336 
337   // Modified version of BinaryFunction::dfs() to build a spanning tree
338   if (!opts::ConservativeInstrumentation) {
339     while (!Stack.empty()) {
340       BinaryBasicBlock *BB;
341       const BinaryBasicBlock *Pred;
342       std::tie(Pred, BB) = Stack.top();
343       Stack.pop();
344       if (VisitedSet.find(BB) != VisitedSet.end())
345         continue;
346 
347       VisitedSet.insert(BB);
348       if (Pred)
349         STOutSet[Pred].insert(BB);
350 
351       for (BinaryBasicBlock *SuccBB : BB->successors())
352         Stack.push(std::make_pair(BB, SuccBB));
353     }
354   }
355 
356   // Determine whether this is a leaf function, which needs special
357   // instructions to protect the red zone
358   bool IsLeafFunction = true;
359   DenseSet<const BinaryBasicBlock *> InvokeBlocks;
360   for (auto BBI = Function.begin(), BBE = Function.end(); BBI != BBE; ++BBI) {
361     for (auto I = BBI->begin(), E = BBI->end(); I != E; ++I) {
362       if (BC.MIB->isCall(*I)) {
363         if (BC.MIB->isInvoke(*I))
364           InvokeBlocks.insert(&*BBI);
365         IsLeafFunction = false;
366       }
367     }
368   }
369 
370   for (auto BBI = Function.begin(), BBE = Function.end(); BBI != BBE; ++BBI) {
371     BinaryBasicBlock &BB = *BBI;
372     bool HasUnconditionalBranch = false;
373     bool HasJumpTable = false;
374     bool IsInvokeBlock = InvokeBlocks.count(&BB) > 0;
375 
376     for (auto I = BB.begin(); I != BB.end(); ++I) {
377       const MCInst &Inst = *I;
378       if (!BC.MIB->getOffset(Inst))
379         continue;
380 
381       const bool IsJumpTable = Function.getJumpTable(Inst);
382       if (IsJumpTable)
383         HasJumpTable = true;
384       else if (BC.MIB->isUnconditionalBranch(Inst))
385         HasUnconditionalBranch = true;
386       else if ((!BC.MIB->isCall(Inst) && !BC.MIB->isConditionalBranch(Inst)) ||
387                BC.MIB->isUnsupportedBranch(Inst.getOpcode()))
388         continue;
389 
390       const uint32_t FromOffset = *BC.MIB->getOffset(Inst);
391       const MCSymbol *Target = BC.MIB->getTargetSymbol(Inst);
392       BinaryBasicBlock *TargetBB = Function.getBasicBlockForLabel(Target);
393       uint32_t ToOffset = TargetBB ? TargetBB->getInputOffset() : 0;
394       BinaryFunction *TargetFunc =
395           TargetBB ? &Function : BC.getFunctionForSymbol(Target);
396       if (TargetFunc && BC.MIB->isCall(Inst)) {
397         if (opts::InstrumentCalls) {
398           const BinaryBasicBlock *ForeignBB =
399               TargetFunc->getBasicBlockForLabel(Target);
400           if (ForeignBB)
401             ToOffset = ForeignBB->getInputOffset();
402           instrumentOneTarget(SplitWorklist, SplitInstrs, I, Function, BB,
403                               FromOffset, *TargetFunc, TargetBB, ToOffset,
404                               IsLeafFunction, IsInvokeBlock, FuncDesc,
405                               BBToID[&BB]);
406         }
407         continue;
408       }
409       if (TargetFunc) {
410         // Do not instrument edges in the spanning tree
411         if (STOutSet[&BB].find(TargetBB) != STOutSet[&BB].end()) {
412           auto L = BC.scopeLock();
413           createEdgeDescription(*FuncDesc, Function, FromOffset, BBToID[&BB],
414                                 Function, ToOffset, BBToID[TargetBB],
415                                 /*Instrumented=*/false);
416           continue;
417         }
418         instrumentOneTarget(SplitWorklist, SplitInstrs, I, Function, BB,
419                             FromOffset, *TargetFunc, TargetBB, ToOffset,
420                             IsLeafFunction, IsInvokeBlock, FuncDesc,
421                             BBToID[&BB], BBToID[TargetBB]);
422         continue;
423       }
424 
425       if (IsJumpTable) {
426         for (BinaryBasicBlock *&Succ : BB.successors()) {
427           // Do not instrument edges in the spanning tree
428           if (STOutSet[&BB].find(&*Succ) != STOutSet[&BB].end()) {
429             auto L = BC.scopeLock();
430             createEdgeDescription(*FuncDesc, Function, FromOffset, BBToID[&BB],
431                                   Function, Succ->getInputOffset(),
432                                   BBToID[&*Succ], /*Instrumented=*/false);
433             continue;
434           }
435           instrumentOneTarget(
436               SplitWorklist, SplitInstrs, I, Function, BB, FromOffset, Function,
437               &*Succ, Succ->getInputOffset(), IsLeafFunction, IsInvokeBlock,
438               FuncDesc, BBToID[&BB], BBToID[&*Succ]);
439         }
440         continue;
441       }
442 
443       // Handle indirect calls -- could be direct calls with unknown targets
444       // or secondary entry points of known functions, so check it is indirect
445       // to be sure.
446       if (opts::InstrumentCalls && BC.MIB->isIndirectCall(*I))
447         instrumentIndirectTarget(BB, I, Function, FromOffset);
448 
449     } // End of instructions loop
450 
451     // Instrument fallthroughs (when the direct jump instruction is missing)
452     if (!HasUnconditionalBranch && !HasJumpTable && BB.succ_size() > 0 &&
453         BB.size() > 0) {
454       BinaryBasicBlock *FTBB = BB.getFallthrough();
455       assert(FTBB && "expected valid fall-through basic block");
456       auto I = BB.begin();
457       auto LastInstr = BB.end();
458       --LastInstr;
459       while (LastInstr != I && BC.MIB->isPseudo(*LastInstr))
460         --LastInstr;
461       uint32_t FromOffset = 0;
462       // The last instruction in the BB should have an annotation, except
463       // if it was branching to the end of the function as a result of
464       // __builtin_unreachable(), in which case it was deleted by fixBranches.
465       // Ignore this case. FIXME: force fixBranches() to preserve the offset.
466       if (!BC.MIB->getOffset(*LastInstr))
467         continue;
468       FromOffset = *BC.MIB->getOffset(*LastInstr);
469 
470       // Do not instrument edges in the spanning tree
471       if (STOutSet[&BB].find(FTBB) != STOutSet[&BB].end()) {
472         auto L = BC.scopeLock();
473         createEdgeDescription(*FuncDesc, Function, FromOffset, BBToID[&BB],
474                               Function, FTBB->getInputOffset(), BBToID[FTBB],
475                               /*Instrumented=*/false);
476         continue;
477       }
478       instrumentOneTarget(SplitWorklist, SplitInstrs, I, Function, BB,
479                           FromOffset, Function, FTBB, FTBB->getInputOffset(),
480                           IsLeafFunction, IsInvokeBlock, FuncDesc, BBToID[&BB],
481                           BBToID[FTBB]);
482     }
483   } // End of BBs loop
484 
485   // Instrument spanning tree leaves
486   if (!opts::ConservativeInstrumentation) {
487     for (auto BBI = Function.begin(), BBE = Function.end(); BBI != BBE; ++BBI) {
488       BinaryBasicBlock &BB = *BBI;
489       if (STOutSet[&BB].size() == 0)
490         instrumentLeafNode(BB, BB.begin(), IsLeafFunction, *FuncDesc,
491                            BBToID[&BB]);
492     }
493   }
494 
495   // Consume list of critical edges: split them and add instrumentation to the
496   // newly created BBs
497   auto Iter = SplitInstrs.begin();
498   for (std::pair<BinaryBasicBlock *, BinaryBasicBlock *> &BBPair :
499        SplitWorklist) {
500     BinaryBasicBlock *NewBB = Function.splitEdge(BBPair.first, BBPair.second);
501     NewBB->addInstructions(Iter->begin(), Iter->end());
502     ++Iter;
503   }
504 
505   // Unused now
506   FuncDesc->EdgesSet.clear();
507 }
508 
509 void Instrumentation::runOnFunctions(BinaryContext &BC) {
510   if (!BC.isX86())
511     return;
512 
513   const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/false,
514                                                  /*IsText=*/false,
515                                                  /*IsAllocatable=*/true);
516   BC.registerOrUpdateSection(".bolt.instr.counters", ELF::SHT_PROGBITS, Flags,
517                              nullptr, 0, 1);
518 
519   BC.registerOrUpdateNoteSection(".bolt.instr.tables", nullptr, 0,
520                                  /*Alignment=*/1,
521                                  /*IsReadOnly=*/true, ELF::SHT_NOTE);
522 
523   Summary->IndCallCounterFuncPtr =
524       BC.Ctx->getOrCreateSymbol("__bolt_ind_call_counter_func_pointer");
525   Summary->IndTailCallCounterFuncPtr =
526       BC.Ctx->getOrCreateSymbol("__bolt_ind_tailcall_counter_func_pointer");
527 
528   createAuxiliaryFunctions(BC);
529 
530   ParallelUtilities::PredicateTy SkipPredicate = [&](const BinaryFunction &BF) {
531     return (!BF.isSimple() || BF.isIgnored() ||
532             (opts::InstrumentHotOnly && !BF.getKnownExecutionCount()));
533   };
534 
535   ParallelUtilities::WorkFuncWithAllocTy WorkFun =
536       [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) {
537         instrumentFunction(BF, AllocatorId);
538       };
539 
540   ParallelUtilities::runOnEachFunctionWithUniqueAllocId(
541       BC, ParallelUtilities::SchedulingPolicy::SP_INST_QUADRATIC, WorkFun,
542       SkipPredicate, "instrumentation", /* ForceSequential=*/true);
543 
544   if (BC.isMachO()) {
545     if (BC.StartFunctionAddress) {
546       BinaryFunction *Main =
547           BC.getBinaryFunctionAtAddress(*BC.StartFunctionAddress);
548       assert(Main && "Entry point function not found");
549       BinaryBasicBlock &BB = Main->front();
550 
551       ErrorOr<BinarySection &> SetupSection =
552           BC.getUniqueSectionByName("I__setup");
553       if (!SetupSection) {
554         llvm::errs() << "Cannot find I__setup section\n";
555         exit(1);
556       }
557       MCSymbol *Target = BC.registerNameAtAddress(
558           "__bolt_instr_setup", SetupSection->getAddress(), 0, 0);
559       MCInst NewInst;
560       BC.MIB->createCall(NewInst, Target, BC.Ctx.get());
561       BB.insertInstruction(BB.begin(), std::move(NewInst));
562     } else {
563       llvm::errs() << "BOLT-WARNING: Entry point not found\n";
564     }
565 
566     if (BinaryData *BD = BC.getBinaryDataByName("___GLOBAL_init_65535/1")) {
567       BinaryFunction *Ctor = BC.getBinaryFunctionAtAddress(BD->getAddress());
568       assert(Ctor && "___GLOBAL_init_65535 function not found");
569       BinaryBasicBlock &BB = Ctor->front();
570       ErrorOr<BinarySection &> FiniSection =
571           BC.getUniqueSectionByName("I__fini");
572       if (!FiniSection) {
573         llvm::errs() << "Cannot find I__fini section\n";
574         exit(1);
575       }
576       MCSymbol *Target = BC.registerNameAtAddress(
577           "__bolt_instr_fini", FiniSection->getAddress(), 0, 0);
578       auto IsLEA = [&BC](const MCInst &Inst) { return BC.MIB->isLEA64r(Inst); };
579       const auto LEA = std::find_if(
580           std::next(llvm::find_if(reverse(BB), IsLEA)), BB.rend(), IsLEA);
581       LEA->getOperand(4).setExpr(
582           MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *BC.Ctx));
583     } else {
584       llvm::errs() << "BOLT-WARNING: ___GLOBAL_init_65535 not found\n";
585     }
586   }
587 
588   setupRuntimeLibrary(BC);
589 }
590 
591 void Instrumentation::createAuxiliaryFunctions(BinaryContext &BC) {
592   auto createSimpleFunction =
593       [&](StringRef Title, InstructionListType Instrs) -> BinaryFunction * {
594     BinaryFunction *Func = BC.createInjectedBinaryFunction(std::string(Title));
595 
596     std::vector<std::unique_ptr<BinaryBasicBlock>> BBs;
597     BBs.emplace_back(Func->createBasicBlock());
598     BBs.back()->addInstructions(Instrs.begin(), Instrs.end());
599     BBs.back()->setCFIState(0);
600     Func->insertBasicBlocks(nullptr, std::move(BBs),
601                             /*UpdateLayout=*/true,
602                             /*UpdateCFIState=*/false);
603     Func->updateState(BinaryFunction::State::CFG_Finalized);
604     return Func;
605   };
606 
607   // Here we are creating a set of functions to handle BB entry/exit.
608   // IndCallHandlerExitBB contains instructions to finish handling traffic to an
609   // indirect call. We pass it to createInstrumentedIndCallHandlerEntryBB(),
610   // which will check if a pointer to runtime library traffic accounting
611   // function was initialized (it is done during initialization of runtime
612   // library). If it is so - calls it. Then this routine returns to normal
613   // execution by jumping to exit BB.
614   BinaryFunction *IndCallHandlerExitBB =
615       createSimpleFunction("__bolt_instr_ind_call_handler",
616                            BC.MIB->createInstrumentedIndCallHandlerExitBB());
617 
618   IndCallHandlerExitBBFunction =
619       createSimpleFunction("__bolt_instr_ind_call_handler_func",
620                            BC.MIB->createInstrumentedIndCallHandlerEntryBB(
621                                Summary->IndCallCounterFuncPtr,
622                                IndCallHandlerExitBB->getSymbol(), &*BC.Ctx));
623 
624   BinaryFunction *IndTailCallHandlerExitBB = createSimpleFunction(
625       "__bolt_instr_ind_tail_call_handler",
626       BC.MIB->createInstrumentedIndTailCallHandlerExitBB());
627 
628   IndTailCallHandlerExitBBFunction = createSimpleFunction(
629       "__bolt_instr_ind_tailcall_handler_func",
630       BC.MIB->createInstrumentedIndCallHandlerEntryBB(
631           Summary->IndTailCallCounterFuncPtr,
632           IndTailCallHandlerExitBB->getSymbol(), &*BC.Ctx));
633 
634   createSimpleFunction("__bolt_num_counters_getter",
635                        BC.MIB->createNumCountersGetter(BC.Ctx.get()));
636   createSimpleFunction("__bolt_instr_locations_getter",
637                        BC.MIB->createInstrLocationsGetter(BC.Ctx.get()));
638   createSimpleFunction("__bolt_instr_tables_getter",
639                        BC.MIB->createInstrTablesGetter(BC.Ctx.get()));
640   createSimpleFunction("__bolt_instr_num_funcs_getter",
641                        BC.MIB->createInstrNumFuncsGetter(BC.Ctx.get()));
642 
643   if (BC.isELF()) {
644     if (BC.StartFunctionAddress) {
645       BinaryFunction *Start =
646           BC.getBinaryFunctionAtAddress(*BC.StartFunctionAddress);
647       assert(Start && "Entry point function not found");
648       const MCSymbol *StartSym = Start->getSymbol();
649       createSimpleFunction(
650           "__bolt_start_trampoline",
651           BC.MIB->createSymbolTrampoline(StartSym, BC.Ctx.get()));
652     }
653     if (BC.FiniFunctionAddress) {
654       BinaryFunction *Fini =
655           BC.getBinaryFunctionAtAddress(*BC.FiniFunctionAddress);
656       assert(Fini && "Finalization function not found");
657       const MCSymbol *FiniSym = Fini->getSymbol();
658       createSimpleFunction(
659           "__bolt_fini_trampoline",
660           BC.MIB->createSymbolTrampoline(FiniSym, BC.Ctx.get()));
661     } else {
662       // Create dummy return function for trampoline to avoid issues
663       // with unknown symbol in runtime library. E.g. for static PIE
664       // executable
665       createSimpleFunction("__bolt_fini_trampoline",
666                            BC.MIB->createDummyReturnFunction(BC.Ctx.get()));
667     }
668   }
669 }
670 
671 void Instrumentation::setupRuntimeLibrary(BinaryContext &BC) {
672   uint32_t FuncDescSize = Summary->getFDSize();
673 
674   outs() << "BOLT-INSTRUMENTER: Number of indirect call site descriptors: "
675          << Summary->IndCallDescriptions.size() << "\n";
676   outs() << "BOLT-INSTRUMENTER: Number of indirect call target descriptors: "
677          << Summary->IndCallTargetDescriptions.size() << "\n";
678   outs() << "BOLT-INSTRUMENTER: Number of function descriptors: "
679          << Summary->FunctionDescriptions.size() << "\n";
680   outs() << "BOLT-INSTRUMENTER: Number of branch counters: " << BranchCounters
681          << "\n";
682   outs() << "BOLT-INSTRUMENTER: Number of ST leaf node counters: "
683          << LeafNodeCounters << "\n";
684   outs() << "BOLT-INSTRUMENTER: Number of direct call counters: "
685          << DirectCallCounters << "\n";
686   outs() << "BOLT-INSTRUMENTER: Total number of counters: "
687          << Summary->Counters.size() << "\n";
688   outs() << "BOLT-INSTRUMENTER: Total size of counters: "
689          << (Summary->Counters.size() * 8) << " bytes (static alloc memory)\n";
690   outs() << "BOLT-INSTRUMENTER: Total size of string table emitted: "
691          << Summary->StringTable.size() << " bytes in file\n";
692   outs() << "BOLT-INSTRUMENTER: Total size of descriptors: "
693          << (FuncDescSize +
694              Summary->IndCallDescriptions.size() * sizeof(IndCallDescription) +
695              Summary->IndCallTargetDescriptions.size() *
696                  sizeof(IndCallTargetDescription))
697          << " bytes in file\n";
698   outs() << "BOLT-INSTRUMENTER: Profile will be saved to file "
699          << opts::InstrumentationFilename << "\n";
700 
701   InstrumentationRuntimeLibrary *RtLibrary =
702       static_cast<InstrumentationRuntimeLibrary *>(BC.getRuntimeLibrary());
703   assert(RtLibrary && "instrumentation runtime library object must be set");
704   RtLibrary->setSummary(std::move(Summary));
705 }
706 } // namespace bolt
707 } // namespace llvm
708