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