1 //===- bolt/Passes/PLTCall.h - PLT call optimization ----------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the PLTCall class, which replaces calls to PLT entries
10 // with indirect calls against GOT.
12 //===----------------------------------------------------------------------===//
14 #include "bolt/Passes/PLTCall.h"
15 #include "llvm/Support/CommandLine.h"
17 #define DEBUG_TYPE "bolt-plt"
23 extern cl::OptionCategory BoltOptCategory
;
25 cl::opt
<bolt::PLTCall::OptType
>
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
,
31 "do not optimize PLT calls"),
32 clEnumValN(bolt::PLTCall::OT_HOT
,
34 "optimize executed (hot) PLT calls"),
35 clEnumValN(bolt::PLTCall::OT_ALL
,
37 "optimize all PLT calls")),
39 cl::cat(BoltOptCategory
));
46 Error
PLTCall::runOnFunctions(BinaryContext
&BC
) {
47 if (opts::PLT
== OT_NONE
)
48 return Error::success();
50 uint64_t NumCallsOptimized
= 0;
51 for (auto &BFI
: BC
.getBinaryFunctions()) {
52 BinaryFunction
&Function
= BFI
.second
;
53 if (!shouldOptimize(Function
))
56 if (opts::PLT
== OT_HOT
&&
57 Function
.getExecutionCount() == BinaryFunction::COUNT_NO_PROFILE
)
60 for (BinaryBasicBlock
&BB
: Function
) {
61 if (opts::PLT
== OT_HOT
&& !BB
.getKnownExecutionCount())
64 for (auto II
= BB
.begin(); II
!= BB
.end(); II
++) {
65 if (!BC
.MIB
->isCall(*II
))
67 const MCSymbol
*CallSymbol
= BC
.MIB
->getTargetSymbol(*II
);
70 const BinaryFunction
*CalleeBF
= BC
.getFunctionForSymbol(CallSymbol
);
71 if (!CalleeBF
|| !CalleeBF
->isPLTFunction())
73 const InstructionListType NewCode
= BC
.MIB
->createIndirectPltCall(
74 *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);
84 if (NumCallsOptimized
) {
85 BC
.RequiresZNow
= true;
86 BC
.outs() << "BOLT-INFO: " << NumCallsOptimized
87 << " PLT calls in the binary were optimized.\n";
89 return Error::success();