12f09f445SMaksim Panchenko //===- bolt/RuntimeLibs/RuntimeLibrary.cpp - Runtime 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 //===----------------------------------------------------------------------===// 8a34c753fSRafael Auler // 92f09f445SMaksim Panchenko // This file implements the RuntimeLibrary class. 102f09f445SMaksim Panchenko // 11a34c753fSRafael Auler //===----------------------------------------------------------------------===// 12a34c753fSRafael Auler 13a34c753fSRafael Auler #include "bolt/RuntimeLibs/RuntimeLibrary.h" 1405634f73SJob Noorman #include "bolt/Core/Linker.h" 15f71d32a0Sserge-sans-paille #include "bolt/RuntimeLibs/RuntimeLibraryVariables.inc" 16a34c753fSRafael Auler #include "bolt/Utils/Utils.h" 17a34c753fSRafael Auler #include "llvm/BinaryFormat/Magic.h" 18a34c753fSRafael Auler #include "llvm/Object/Archive.h" 1905634f73SJob Noorman #include "llvm/Object/ObjectFile.h" 20a34c753fSRafael Auler #include "llvm/Support/Path.h" 21a34c753fSRafael Auler 22a34c753fSRafael Auler #define DEBUG_TYPE "bolt-rtlib" 23a34c753fSRafael Auler 24a34c753fSRafael Auler using namespace llvm; 25a34c753fSRafael Auler using namespace bolt; 26a34c753fSRafael Auler 27a34c753fSRafael Auler void RuntimeLibrary::anchor() {} 28a34c753fSRafael Auler 29*abc2eae6STristan Ross std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath, 30a34c753fSRafael Auler StringRef LibFileName) { 31a34c753fSRafael Auler StringRef Dir = llvm::sys::path::parent_path(ToolPath); 32a34c753fSRafael Auler SmallString<128> LibPath = llvm::sys::path::parent_path(Dir); 33f71d32a0Sserge-sans-paille llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX); 34a34c753fSRafael Auler if (!llvm::sys::fs::exists(LibPath)) { 35a34c753fSRafael Auler // In some cases we install bolt binary into one level deeper in bin/, 36a34c753fSRafael Auler // we need to go back one more level to find lib directory. 3740c2e0faSMaksim Panchenko LibPath = llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir)); 38f71d32a0Sserge-sans-paille llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX); 39a34c753fSRafael Auler } 40a34c753fSRafael Auler llvm::sys::path::append(LibPath, LibFileName); 4103cba440SKazu Hirata return std::string(LibPath); 42a34c753fSRafael Auler } 43a34c753fSRafael Auler 44*abc2eae6STristan Ross std::string RuntimeLibrary::getLibPathByInstalled(StringRef LibFileName) { 45*abc2eae6STristan Ross SmallString<128> LibPath(CMAKE_INSTALL_FULL_LIBDIR); 46*abc2eae6STristan Ross llvm::sys::path::append(LibPath, LibFileName); 47*abc2eae6STristan Ross return std::string(LibPath); 48*abc2eae6STristan Ross } 49*abc2eae6STristan Ross 50*abc2eae6STristan Ross std::string RuntimeLibrary::getLibPath(StringRef ToolPath, 51*abc2eae6STristan Ross StringRef LibFileName) { 52*abc2eae6STristan Ross if (llvm::sys::fs::exists(LibFileName)) { 53*abc2eae6STristan Ross return std::string(LibFileName); 54*abc2eae6STristan Ross } 55*abc2eae6STristan Ross 56*abc2eae6STristan Ross std::string ByTool = getLibPathByToolPath(ToolPath, LibFileName); 57*abc2eae6STristan Ross if (llvm::sys::fs::exists(ByTool)) { 58*abc2eae6STristan Ross return ByTool; 59*abc2eae6STristan Ross } 60*abc2eae6STristan Ross 61*abc2eae6STristan Ross std::string ByInstalled = getLibPathByInstalled(LibFileName); 62*abc2eae6STristan Ross if (llvm::sys::fs::exists(ByInstalled)) { 63*abc2eae6STristan Ross return ByInstalled; 64*abc2eae6STristan Ross } 65*abc2eae6STristan Ross 66*abc2eae6STristan Ross errs() << "BOLT-ERROR: library not found: " << ByTool << ", " << ByInstalled 67*abc2eae6STristan Ross << ", or " << LibFileName << "\n"; 68*abc2eae6STristan Ross exit(1); 69*abc2eae6STristan Ross } 70*abc2eae6STristan Ross 7105634f73SJob Noorman void RuntimeLibrary::loadLibrary(StringRef LibPath, BOLTLinker &Linker, 7205634f73SJob Noorman BOLTLinker::SectionsMapper MapSections) { 73a34c753fSRafael Auler ErrorOr<std::unique_ptr<MemoryBuffer>> MaybeBuf = 74b392ec69SRafael Auler MemoryBuffer::getFile(LibPath, false, false); 75a34c753fSRafael Auler check_error(MaybeBuf.getError(), LibPath); 76a34c753fSRafael Auler std::unique_ptr<MemoryBuffer> B = std::move(MaybeBuf.get()); 77a34c753fSRafael Auler file_magic Magic = identify_magic(B->getBuffer()); 78a34c753fSRafael Auler 79a34c753fSRafael Auler if (Magic == file_magic::archive) { 80a34c753fSRafael Auler Error Err = Error::success(); 81a34c753fSRafael Auler object::Archive Archive(B.get()->getMemBufferRef(), Err); 82a34c753fSRafael Auler for (const object::Archive::Child &C : Archive.children(Err)) { 83a34c753fSRafael Auler std::unique_ptr<object::Binary> Bin = cantFail(C.getAsBinary()); 84883bf0e8SAmir Ayupov if (object::ObjectFile *Obj = dyn_cast<object::ObjectFile>(&*Bin)) 8505634f73SJob Noorman Linker.loadObject(Obj->getMemoryBufferRef(), MapSections); 86a34c753fSRafael Auler } 87a34c753fSRafael Auler check_error(std::move(Err), B->getBufferIdentifier()); 88a34c753fSRafael Auler } else if (Magic == file_magic::elf_relocatable || 89a34c753fSRafael Auler Magic == file_magic::elf_shared_object) { 90a34c753fSRafael Auler std::unique_ptr<object::ObjectFile> Obj = cantFail( 91a34c753fSRafael Auler object::ObjectFile::createObjectFile(B.get()->getMemBufferRef()), 92a34c753fSRafael Auler "error creating in-memory object"); 9305634f73SJob Noorman Linker.loadObject(Obj->getMemoryBufferRef(), MapSections); 94a34c753fSRafael Auler } else { 95a34c753fSRafael Auler errs() << "BOLT-ERROR: unrecognized library format: " << LibPath << "\n"; 96a34c753fSRafael Auler exit(1); 97a34c753fSRafael Auler } 98a34c753fSRafael Auler } 99