1 //===- bolt/Passes/PLTCall.h - PLT call optimization ----------------------===// 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 PLTCall class, which replaces calls to PLT entries 10 // with indirect calls against GOT. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "bolt/Passes/PLTCall.h" 15 #include "llvm/Support/CommandLine.h" 16 17 #define DEBUG_TYPE "bolt-plt" 18 19 using namespace llvm; 20 21 namespace opts { 22 23 extern cl::OptionCategory BoltOptCategory; 24 25 cl::opt<bolt::PLTCall::OptType> 26 PLT("plt", 27 cl::desc("optimize PLT calls (requires linking with -znow)"), 28 cl::init(bolt::PLTCall::OT_NONE), 29 cl::values(clEnumValN(bolt::PLTCall::OT_NONE, 30 "none", 31 "do not optimize PLT calls"), 32 clEnumValN(bolt::PLTCall::OT_HOT, 33 "hot", 34 "optimize executed (hot) PLT calls"), 35 clEnumValN(bolt::PLTCall::OT_ALL, 36 "all", 37 "optimize all PLT calls")), 38 cl::ZeroOrMore, 39 cl::cat(BoltOptCategory)); 40 41 } 42 43 namespace llvm { 44 namespace bolt { 45 46 Error PLTCall::runOnFunctions(BinaryContext &BC) { 47 if (opts::PLT == OT_NONE) 48 return Error::success(); 49 50 uint64_t NumCallsOptimized = 0; 51 for (auto &BFI : BC.getBinaryFunctions()) { 52 BinaryFunction &Function = BFI.second; 53 if (!shouldOptimize(Function)) 54 continue; 55 56 if (opts::PLT == OT_HOT && 57 Function.getExecutionCount() == BinaryFunction::COUNT_NO_PROFILE) 58 continue; 59 60 for (BinaryBasicBlock &BB : Function) { 61 if (opts::PLT == OT_HOT && !BB.getKnownExecutionCount()) 62 continue; 63 64 for (auto II = BB.begin(); II != BB.end(); II++) { 65 if (!BC.MIB->isCall(*II)) 66 continue; 67 const MCSymbol *CallSymbol = BC.MIB->getTargetSymbol(*II); 68 if (!CallSymbol) 69 continue; 70 const BinaryFunction *CalleeBF = BC.getFunctionForSymbol(CallSymbol); 71 if (!CalleeBF || !CalleeBF->isPLTFunction()) 72 continue; 73 const InstructionListType NewCode = BC.MIB->createIndirectPLTCall( 74 std::move(*II), CalleeBF->getPLTSymbol(), BC.Ctx.get()); 75 II = BB.replaceInstruction(II, NewCode); 76 assert(!NewCode.empty() && "PLT Call replacement must be non-empty"); 77 std::advance(II, NewCode.size() - 1); 78 BC.MIB->addAnnotation(*II, "PLTCall", true); 79 ++NumCallsOptimized; 80 } 81 } 82 } 83 84 if (NumCallsOptimized) { 85 BC.RequiresZNow = true; 86 BC.outs() << "BOLT-INFO: " << NumCallsOptimized 87 << " PLT calls in the binary were optimized.\n"; 88 } 89 return Error::success(); 90 } 91 92 } // namespace bolt 93 } // namespace llvm 94