1 //===- bolt/Passes/VeneerElimination.cpp ----------------------------------===// 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 class implements a pass that removes linker-inserted veneers from the 10 // code and redirects veneer callers to call to veneers destinations 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "bolt/Passes/VeneerElimination.h" 15 #define DEBUG_TYPE "veneer-elim" 16 17 using namespace llvm; 18 19 namespace opts { 20 21 extern cl::OptionCategory BoltOptCategory; 22 23 static llvm::cl::opt<bool> 24 EliminateVeneers("elim-link-veneers", 25 cl::desc("run veneer elimination pass"), cl::init(true), 26 cl::Hidden, cl::cat(BoltOptCategory)); 27 } // namespace opts 28 29 namespace llvm { 30 namespace bolt { 31 32 void VeneerElimination::runOnFunctions(BinaryContext &BC) { 33 if (!opts::EliminateVeneers || !BC.isAArch64()) 34 return; 35 36 std::map<uint64_t, BinaryFunction> &BFs = BC.getBinaryFunctions(); 37 std::unordered_map<const MCSymbol *, const MCSymbol *> VeneerDestinations; 38 uint64_t VeneersCount = 0; 39 for (auto &It : BFs) { 40 BinaryFunction &VeneerFunction = It.second; 41 if (!VeneerFunction.isAArch64Veneer()) 42 continue; 43 44 VeneersCount++; 45 VeneerFunction.setPseudo(true); 46 MCInst &FirstInstruction = *(VeneerFunction.begin()->begin()); 47 const MCSymbol *VeneerTargetSymbol = 48 BC.MIB->getTargetSymbol(FirstInstruction, 1); 49 assert(VeneerTargetSymbol && "Expecting target symbol for instruction"); 50 for (const MCSymbol *Symbol : VeneerFunction.getSymbols()) 51 VeneerDestinations[Symbol] = VeneerTargetSymbol; 52 } 53 54 outs() << "BOLT-INFO: number of removed linker-inserted veneers: " 55 << VeneersCount << "\n"; 56 57 // Handle veneers to veneers in case they occur 58 for (auto &Entry : VeneerDestinations) { 59 const MCSymbol *Src = Entry.first; 60 const MCSymbol *Dest = Entry.second; 61 while (VeneerDestinations.find(Dest) != VeneerDestinations.end()) 62 Dest = VeneerDestinations[Dest]; 63 64 VeneerDestinations[Src] = Dest; 65 } 66 67 uint64_t VeneerCallers = 0; 68 for (auto &It : BFs) { 69 BinaryFunction &Function = It.second; 70 for (BinaryBasicBlock &BB : Function) { 71 for (MCInst &Instr : BB) { 72 if (!BC.MIB->isCall(Instr) || BC.MIB->isIndirectCall(Instr)) 73 continue; 74 75 const MCSymbol *TargetSymbol = BC.MIB->getTargetSymbol(Instr, 0); 76 if (VeneerDestinations.find(TargetSymbol) == VeneerDestinations.end()) 77 continue; 78 79 VeneerCallers++; 80 if (!BC.MIB->replaceBranchTarget( 81 Instr, VeneerDestinations[TargetSymbol], BC.Ctx.get())) { 82 errs() << "BOLT-ERROR: updating veneer call destination failed\n"; 83 exit(1); 84 } 85 } 86 } 87 } 88 89 LLVM_DEBUG( 90 dbgs() << "BOLT-INFO: number of linker-inserted veneers call sites: " 91 << VeneerCallers << "\n"); 92 } 93 94 } // namespace bolt 95 } // namespace llvm 96