| //===- 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) { | |
| std::unique_ptr<object::Archive> Archive; | |
| Error Err = object::Archive::create(B->getMemBufferRef()).moveInto(Archive); | |
| check_error(std::move(Err), B->getBufferIdentifier()); | |
| 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); | |
| } | |
| } |