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 void PLTCall::runOnFunctions(BinaryContext &BC) { 47 if (opts::PLT == OT_NONE) 48 return; 49 50 uint64_t NumCallsOptimized = 0; 51 for (auto &It : BC.getBinaryFunctions()) { 52 BinaryFunction &Function = It.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.layout()) { 61 if (opts::PLT == OT_HOT && !BB->getKnownExecutionCount()) 62 continue; 63 64 for (MCInst &Instr : *BB) { 65 if (!BC.MIB->isCall(Instr)) 66 continue; 67 const MCSymbol *CallSymbol = BC.MIB->getTargetSymbol(Instr); 68 if (!CallSymbol) 69 continue; 70 const BinaryFunction *CalleeBF = BC.getFunctionForSymbol(CallSymbol); 71 if (!CalleeBF || !CalleeBF->isPLTFunction()) 72 continue; 73 BC.MIB->convertCallToIndirectCall(Instr, CalleeBF->getPLTSymbol(), 74 BC.Ctx.get()); 75 BC.MIB->addAnnotation(Instr, "PLTCall", true); 76 ++NumCallsOptimized; 77 } 78 } 79 } 80 81 if (NumCallsOptimized) { 82 BC.RequiresZNow = true; 83 outs() << "BOLT-INFO: " << NumCallsOptimized 84 << " PLT calls in the binary were optimized.\n"; 85 } 86 } 87 88 } // namespace bolt 89 } // namespace llvm 90