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 auto &BFs = BC.getBinaryFunctions(); 37 std::unordered_map<const MCSymbol *, const MCSymbol *> VeneerDestinations; 38 uint64_t VeneersCount = 0; 39 for (auto It = BFs.begin(); It != BFs.end();) { 40 auto CurrentIt = It; 41 ++It; 42 43 if (CurrentIt->second.isAArch64Veneer()) { 44 VeneersCount++; 45 BinaryFunction &VeneerFunction = CurrentIt->second; 46 47 MCInst &FirstInstruction = *(VeneerFunction.begin()->begin()); 48 const MCSymbol *VeneerTargetSymbol = 49 BC.MIB->getTargetSymbol(FirstInstruction, 1); 50 51 // Functions can have multiple symbols 52 for (StringRef Name : VeneerFunction.getNames()) { 53 MCSymbol *Symbol = BC.Ctx->lookupSymbol(Name); 54 VeneerDestinations[Symbol] = VeneerTargetSymbol; 55 BC.SymbolToFunctionMap.erase(Symbol); 56 } 57 58 BC.BinaryDataMap.erase(VeneerFunction.getAddress()); 59 BFs.erase(CurrentIt); 60 } 61 } 62 63 LLVM_DEBUG(dbgs() << "BOLT-INFO: number of removed linker-inserted veneers :" 64 << VeneersCount << "\n"); 65 66 // Handle veneers to veneers in case they occur 67 for (auto entry : VeneerDestinations) { 68 const MCSymbol *src = entry.first; 69 const MCSymbol *dest = entry.second; 70 while (VeneerDestinations.find(dest) != VeneerDestinations.end()) { 71 dest = VeneerDestinations[dest]; 72 } 73 VeneerDestinations[src] = dest; 74 } 75 76 uint64_t VeneerCallers = 0; 77 for (auto &It : BFs) { 78 BinaryFunction &Function = It.second; 79 for (BinaryBasicBlock &BB : Function) { 80 for (MCInst &Instr : BB) { 81 if (!BC.MIB->isCall(Instr) || BC.MIB->isIndirectCall(Instr)) 82 continue; 83 84 const MCSymbol *TargetSymbol = BC.MIB->getTargetSymbol(Instr, 0); 85 if (VeneerDestinations.find(TargetSymbol) == VeneerDestinations.end()) 86 continue; 87 88 VeneerCallers++; 89 if (!BC.MIB->replaceBranchTarget( 90 Instr, VeneerDestinations[TargetSymbol], BC.Ctx.get())) 91 assert(false && "updating veneer call destination failed"); 92 } 93 } 94 } 95 96 LLVM_DEBUG( 97 dbgs() << "BOLT-INFO: number of linker-inserted veneers call sites :" 98 << VeneerCallers << "\n"); 99 } 100 101 } // namespace bolt 102 } // namespace llvm 103