| //===- bolt/RuntimeLibs/RuntimeLibrary.cpp - Runtime Library --------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the RuntimeLibrary class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "bolt/RuntimeLibs/RuntimeLibrary.h" |
| #include "bolt/Core/Linker.h" |
| #include "bolt/RuntimeLibs/RuntimeLibraryVariables.inc" |
| #include "bolt/Utils/Utils.h" |
| #include "llvm/BinaryFormat/Magic.h" |
| #include "llvm/Object/Archive.h" |
| #include "llvm/Object/ObjectFile.h" |
| #include "llvm/Support/Path.h" |
| #include "llvm/Support/Program.h" |
| |
| #define DEBUG_TYPE "bolt-rtlib" |
| |
| using namespace llvm; |
| using namespace bolt; |
| |
| void RuntimeLibrary::anchor() {} |
| |
| std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath, |
| StringRef LibFileName) { |
| StringRef Dir = llvm::sys::path::parent_path(ToolPath); |
| SmallString<128> LibPath = llvm::sys::path::parent_path(Dir); |
| llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX); |
| if (!llvm::sys::fs::exists(LibPath)) { |
| // In some cases we install bolt binary into one level deeper in bin/, |
| // we need to go back one more level to find lib directory. |
| LibPath = llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir)); |
| llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX); |
| } |
| llvm::sys::path::append(LibPath, LibFileName); |
| if (!llvm::sys::fs::exists(LibPath)) { |
| // If it is a symlink, check the directory that the symlink points to. |
| if (llvm::sys::fs::is_symlink_file(ToolPath)) { |
| SmallString<256> RealPath; |
| llvm::sys::fs::real_path(ToolPath, RealPath); |
| if (llvm::ErrorOr<std::string> P = |
| llvm::sys::findProgramByName(RealPath)) { |
| outs() << "BOLT-INFO: library not found: " << LibPath << "\n" |
| << "BOLT-INFO: " << ToolPath << " is a symlink; will look up " |
| << LibFileName |
| << " at the target directory that the symlink points to\n"; |
| return getLibPath(*P, LibFileName); |
| } |
| } |
| errs() << "BOLT-ERROR: library not found: " << LibPath << "\n"; |
| exit(1); |
| } |
| return std::string(LibPath); |
| } |
| |
| std::string RuntimeLibrary::getLibPathByInstalled(StringRef LibFileName) { |
| SmallString<128> LibPath(CMAKE_INSTALL_FULL_LIBDIR); |
| llvm::sys::path::append(LibPath, LibFileName); |
| return std::string(LibPath); |
| } |
| |
| std::string RuntimeLibrary::getLibPath(StringRef ToolPath, |
| StringRef LibFileName) { |
| if (llvm::sys::fs::exists(LibFileName)) { |
| return std::string(LibFileName); |
| } |
| |
| std::string ByTool = getLibPathByToolPath(ToolPath, LibFileName); |
| if (llvm::sys::fs::exists(ByTool)) { |
| return ByTool; |
| } |
| |
| std::string ByInstalled = getLibPathByInstalled(LibFileName); |
| if (llvm::sys::fs::exists(ByInstalled)) { |
| return ByInstalled; |
| } |
| |
| errs() << "BOLT-ERROR: library not found: " << ByTool << ", " << ByInstalled |
| << ", or " << LibFileName << "\n"; |
| exit(1); |
| } |
| |
| void RuntimeLibrary::loadLibrary(StringRef LibPath, BOLTLinker &Linker, |
| BOLTLinker::SectionsMapper MapSections) { |
| ErrorOr<std::unique_ptr<MemoryBuffer>> MaybeBuf = |
| MemoryBuffer::getFile(LibPath, false, false); |
| check_error(MaybeBuf.getError(), LibPath); |
| std::unique_ptr<MemoryBuffer> B = std::move(MaybeBuf.get()); |
| file_magic Magic = identify_magic(B->getBuffer()); |
| |
| if (Magic == file_magic::archive) { |
| Error Err = Error::success(); |
| object::Archive Archive(B->getMemBufferRef(), Err); |
| for (const object::Archive::Child &C : Archive.children(Err)) { |
| std::unique_ptr<object::Binary> Bin = cantFail(C.getAsBinary()); |
| if (object::ObjectFile *Obj = dyn_cast<object::ObjectFile>(&*Bin)) |
| Linker.loadObject(Obj->getMemoryBufferRef(), MapSections); |
| } |
| check_error(std::move(Err), B->getBufferIdentifier()); |
| } else if (Magic == file_magic::elf_relocatable || |
| Magic == file_magic::elf_shared_object) { |
| std::unique_ptr<object::ObjectFile> Obj = |
| cantFail(object::ObjectFile::createObjectFile(B->getMemBufferRef()), |
| "error creating in-memory object"); |
| Linker.loadObject(Obj->getMemoryBufferRef(), MapSections); |
| } else { |
| errs() << "BOLT-ERROR: unrecognized library format: " << LibPath << "\n"; |
| exit(1); |
| } |
| } |