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