1 //===- bolt/Passes/PatchEntries.cpp - Pass for patching function entries --===// 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 PatchEntries class that is used for patching 10 // the original function entry points. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "bolt/Passes/PatchEntries.h" 15 #include "bolt/Utils/NameResolver.h" 16 #include "llvm/Support/CommandLine.h" 17 18 namespace opts { 19 20 extern llvm::cl::OptionCategory BoltCategory; 21 22 extern llvm::cl::opt<unsigned> Verbosity; 23 24 llvm::cl::opt<bool> 25 ForcePatch("force-patch", 26 llvm::cl::desc("force patching of original entry points"), 27 llvm::cl::Hidden, llvm::cl::cat(BoltCategory)); 28 } 29 30 namespace llvm { 31 namespace bolt { 32 33 void PatchEntries::runOnFunctions(BinaryContext &BC) { 34 if (!opts::ForcePatch) { 35 // Mark the binary for patching if we did not create external references 36 // for original code in any of functions we are not going to emit. 37 bool NeedsPatching = false; 38 for (auto &BFI : BC.getBinaryFunctions()) { 39 BinaryFunction &Function = BFI.second; 40 if (!BC.shouldEmit(Function) && !Function.hasExternalRefRelocations()) { 41 NeedsPatching = true; 42 break; 43 } 44 } 45 46 if (!NeedsPatching) 47 return; 48 } 49 50 if (opts::Verbosity >= 1) 51 outs() << "BOLT-INFO: patching entries in original code\n"; 52 53 // Calculate the size of the patch. 54 static size_t PatchSize = 0; 55 if (!PatchSize) { 56 InstructionListType Seq; 57 BC.MIB->createLongTailCall(Seq, BC.Ctx->createTempSymbol(), BC.Ctx.get()); 58 PatchSize = BC.computeCodeSize(Seq.begin(), Seq.end()); 59 } 60 61 for (auto &BFI : BC.getBinaryFunctions()) { 62 BinaryFunction &Function = BFI.second; 63 64 // Patch original code only for functions that will be emitted. 65 if (!BC.shouldEmit(Function)) 66 continue; 67 68 // Check if we can skip patching the function. 69 if (!opts::ForcePatch && !Function.hasEHRanges() && 70 Function.getSize() < PatchThreshold) 71 continue; 72 73 // List of patches for function entries. We either successfully patch 74 // all entries or, if we cannot patch one or more, do no patch any and 75 // mark the function as ignorable. 76 std::vector<Patch> PendingPatches; 77 78 uint64_t NextValidByte = 0; // offset of the byte past the last patch 79 bool Success = Function.forEachEntryPoint([&](uint64_t Offset, 80 const MCSymbol *Symbol) { 81 if (Offset < NextValidByte) { 82 if (opts::Verbosity >= 1) 83 outs() << "BOLT-INFO: unable to patch entry point in " << Function 84 << " at offset 0x" << Twine::utohexstr(Offset) << '\n'; 85 return false; 86 } 87 88 PendingPatches.emplace_back(Patch{Symbol, Function.getAddress() + Offset, 89 Function.getFileOffset() + Offset, 90 Function.getOriginSection()}); 91 NextValidByte = Offset + PatchSize; 92 if (NextValidByte > Function.getMaxSize()) { 93 if (opts::Verbosity >= 1) 94 outs() << "BOLT-INFO: function " << Function 95 << " too small to patch its entry point\n"; 96 return false; 97 } 98 99 return true; 100 }); 101 102 if (!Success) { 103 // If the original function entries cannot be patched, then we cannot 104 // safely emit new function body. 105 errs() << "BOLT-WARNING: failed to patch entries in " << Function 106 << ". The function will not be optimized.\n"; 107 Function.setIgnored(); 108 continue; 109 } 110 111 for (Patch &Patch : PendingPatches) { 112 BinaryFunction *PatchFunction = BC.createInjectedBinaryFunction( 113 NameResolver::append(Patch.Symbol->getName(), ".org.0")); 114 // Force the function to be emitted at the given address. 115 PatchFunction->setOutputAddress(Patch.Address); 116 PatchFunction->setFileOffset(Patch.FileOffset); 117 PatchFunction->setOriginSection(Patch.Section); 118 119 InstructionListType Seq; 120 BC.MIB->createLongTailCall(Seq, Patch.Symbol, BC.Ctx.get()); 121 PatchFunction->addBasicBlock(0)->addInstructions(Seq); 122 123 // Verify the size requirements. 124 uint64_t HotSize, ColdSize; 125 std::tie(HotSize, ColdSize) = BC.calculateEmittedSize(*PatchFunction); 126 assert(!ColdSize && "unexpected cold code"); 127 assert(HotSize <= PatchSize && "max patch size exceeded"); 128 } 129 130 Function.setIsPatched(true); 131 } 132 } 133 134 } // end namespace bolt 135 } // end namespace llvm 136