1*2f09f445SMaksim Panchenko //===- bolt/RuntimeLibs/HugifyRuntimeLibrary.cpp - Hugify RT Library ------===// 2a34c753fSRafael Auler // 3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information. 5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a34c753fSRafael Auler // 7a34c753fSRafael Auler //===----------------------------------------------------------------------===// 8*2f09f445SMaksim Panchenko // 9*2f09f445SMaksim Panchenko // This file implements the HugifyRuntimeLibrary class. 10*2f09f445SMaksim Panchenko // 11*2f09f445SMaksim Panchenko //===----------------------------------------------------------------------===// 12a34c753fSRafael Auler 13a34c753fSRafael Auler #include "bolt/RuntimeLibs/HugifyRuntimeLibrary.h" 14a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h" 15a34c753fSRafael Auler #include "llvm/ExecutionEngine/RuntimeDyld.h" 16a34c753fSRafael Auler #include "llvm/MC/MCStreamer.h" 17a34c753fSRafael Auler #include "llvm/Support/Alignment.h" 18a34c753fSRafael Auler #include "llvm/Support/CommandLine.h" 19a34c753fSRafael Auler 20a34c753fSRafael Auler using namespace llvm; 21a34c753fSRafael Auler using namespace bolt; 22a34c753fSRafael Auler 23a34c753fSRafael Auler namespace opts { 24a34c753fSRafael Auler 25a34c753fSRafael Auler extern cl::OptionCategory BoltOptCategory; 26a34c753fSRafael Auler 27a34c753fSRafael Auler extern cl::opt<bool> HotText; 28a34c753fSRafael Auler 29a34c753fSRafael Auler cl::opt<bool> 30a34c753fSRafael Auler Hugify("hugify", 31a34c753fSRafael Auler cl::desc("Automatically put hot code on 2MB page(s) (hugify) at " 32a34c753fSRafael Auler "runtime. No manual call to hugify is needed in the binary " 33a34c753fSRafael Auler "(which is what --hot-text relies on)."), 34a34c753fSRafael Auler cl::ZeroOrMore, cl::cat(BoltOptCategory)); 35a34c753fSRafael Auler 36a34c753fSRafael Auler static cl::opt<std::string> RuntimeHugifyLib( 37a34c753fSRafael Auler "runtime-hugify-lib", 38a34c753fSRafael Auler cl::desc("specify file name of the runtime hugify library"), cl::ZeroOrMore, 39a34c753fSRafael Auler cl::init("libbolt_rt_hugify.a"), cl::cat(BoltOptCategory)); 40a34c753fSRafael Auler 41a34c753fSRafael Auler } // namespace opts 42a34c753fSRafael Auler 43a34c753fSRafael Auler void HugifyRuntimeLibrary::adjustCommandLineOptions( 44a34c753fSRafael Auler const BinaryContext &BC) const { 45a34c753fSRafael Auler if (opts::HotText) { 46a34c753fSRafael Auler errs() 47a34c753fSRafael Auler << "BOLT-ERROR: -hot-text should be applied to binaries with " 48a34c753fSRafael Auler "pre-compiled manual hugify support, while -hugify will add hugify " 49a34c753fSRafael Auler "support automatcally. These two options cannot both be present.\n"; 50a34c753fSRafael Auler exit(1); 51a34c753fSRafael Auler } 52a34c753fSRafael Auler // After the check, we set HotText to be true because automated hugify support 53a34c753fSRafael Auler // relies on it. 54a34c753fSRafael Auler opts::HotText = true; 55a34c753fSRafael Auler if (!BC.StartFunctionAddress) { 56a34c753fSRafael Auler errs() << "BOLT-ERROR: hugify runtime libraries require a known entry " 57a34c753fSRafael Auler "point of " 58a34c753fSRafael Auler "the input binary\n"; 59a34c753fSRafael Auler exit(1); 60a34c753fSRafael Auler } 61a34c753fSRafael Auler } 62a34c753fSRafael Auler 63a34c753fSRafael Auler void HugifyRuntimeLibrary::emitBinary(BinaryContext &BC, MCStreamer &Streamer) { 64a34c753fSRafael Auler const BinaryFunction *StartFunction = 65a34c753fSRafael Auler BC.getBinaryFunctionAtAddress(*(BC.StartFunctionAddress)); 66a34c753fSRafael Auler assert(!StartFunction->isFragment() && "expected main function fragment"); 67a34c753fSRafael Auler if (!StartFunction) { 68a34c753fSRafael Auler errs() << "BOLT-ERROR: failed to locate function at binary start address\n"; 69a34c753fSRafael Auler exit(1); 70a34c753fSRafael Auler } 71a34c753fSRafael Auler 72a34c753fSRafael Auler const auto Flags = BinarySection::getFlags(/*IsReadOnly=*/false, 73a34c753fSRafael Auler /*IsText=*/false, 74a34c753fSRafael Auler /*IsAllocatable=*/true); 75a34c753fSRafael Auler MCSectionELF *Section = 76a34c753fSRafael Auler BC.Ctx->getELFSection(".bolt.hugify.entries", ELF::SHT_PROGBITS, Flags); 77a34c753fSRafael Auler 78a34c753fSRafael Auler // __bolt_hugify_init_ptr stores the poiter the hugify library needs to 79a34c753fSRafael Auler // jump to after finishing the init code. 80a34c753fSRafael Auler MCSymbol *InitPtr = BC.Ctx->getOrCreateSymbol("__bolt_hugify_init_ptr"); 81a34c753fSRafael Auler 82a34c753fSRafael Auler Section->setAlignment(llvm::Align(BC.RegularPageSize)); 83a34c753fSRafael Auler Streamer.SwitchSection(Section); 84a34c753fSRafael Auler 85a34c753fSRafael Auler Streamer.emitLabel(InitPtr); 86a34c753fSRafael Auler Streamer.emitSymbolAttribute(InitPtr, MCSymbolAttr::MCSA_Global); 87a34c753fSRafael Auler Streamer.emitValue( 88a34c753fSRafael Auler MCSymbolRefExpr::create(StartFunction->getSymbol(), *(BC.Ctx)), 89a34c753fSRafael Auler /*Size=*/8); 90a34c753fSRafael Auler } 91a34c753fSRafael Auler 92a34c753fSRafael Auler void HugifyRuntimeLibrary::link(BinaryContext &BC, StringRef ToolPath, 93a34c753fSRafael Auler RuntimeDyld &RTDyld, 94a34c753fSRafael Auler std::function<void(RuntimeDyld &)> OnLoad) { 95a34c753fSRafael Auler std::string LibPath = getLibPath(ToolPath, opts::RuntimeHugifyLib); 96a34c753fSRafael Auler loadLibrary(LibPath, RTDyld); 97a34c753fSRafael Auler OnLoad(RTDyld); 98a34c753fSRafael Auler RTDyld.finalizeWithMemoryManagerLocking(); 99a34c753fSRafael Auler if (RTDyld.hasError()) { 100a34c753fSRafael Auler outs() << "BOLT-ERROR: RTDyld failed: " << RTDyld.getErrorString() << "\n"; 101a34c753fSRafael Auler exit(1); 102a34c753fSRafael Auler } 103a34c753fSRafael Auler 104a34c753fSRafael Auler assert(!RuntimeStartAddress && 105a34c753fSRafael Auler "We don't currently support linking multiple runtime libraries"); 106a34c753fSRafael Auler RuntimeStartAddress = RTDyld.getSymbol("__bolt_hugify_self").getAddress(); 107a34c753fSRafael Auler if (!RuntimeStartAddress) { 108a34c753fSRafael Auler errs() << "BOLT-ERROR: instrumentation library does not define " 109a34c753fSRafael Auler "__bolt_hugify_self: " 110a34c753fSRafael Auler << LibPath << "\n"; 111a34c753fSRafael Auler exit(1); 112a34c753fSRafael Auler } 113a34c753fSRafael Auler } 114