117 lines · cpp
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-exception6//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#include "llvm/Support/Program.h"22 23#define DEBUG_TYPE "bolt-rtlib"24 25using namespace llvm;26using namespace bolt;27 28void RuntimeLibrary::anchor() {}29 30std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,31 StringRef LibFileName) {32 StringRef Dir = llvm::sys::path::parent_path(ToolPath);33 SmallString<128> LibPath = llvm::sys::path::parent_path(Dir);34 llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);35 if (!llvm::sys::fs::exists(LibPath)) {36 // In some cases we install bolt binary into one level deeper in bin/,37 // we need to go back one more level to find lib directory.38 LibPath = llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir));39 llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);40 }41 llvm::sys::path::append(LibPath, LibFileName);42 if (!llvm::sys::fs::exists(LibPath)) {43 // If it is a symlink, check the directory that the symlink points to.44 if (llvm::sys::fs::is_symlink_file(ToolPath)) {45 SmallString<256> RealPath;46 llvm::sys::fs::real_path(ToolPath, RealPath);47 if (llvm::ErrorOr<std::string> P =48 llvm::sys::findProgramByName(RealPath)) {49 outs() << "BOLT-INFO: library not found: " << LibPath << "\n"50 << "BOLT-INFO: " << ToolPath << " is a symlink; will look up "51 << LibFileName52 << " at the target directory that the symlink points to\n";53 return getLibPath(*P, LibFileName);54 }55 }56 errs() << "BOLT-ERROR: library not found: " << LibPath << "\n";57 exit(1);58 }59 return std::string(LibPath);60}61 62std::string RuntimeLibrary::getLibPathByInstalled(StringRef LibFileName) {63 SmallString<128> LibPath(CMAKE_INSTALL_FULL_LIBDIR);64 llvm::sys::path::append(LibPath, LibFileName);65 return std::string(LibPath);66}67 68std::string RuntimeLibrary::getLibPath(StringRef ToolPath,69 StringRef LibFileName) {70 if (llvm::sys::fs::exists(LibFileName)) {71 return std::string(LibFileName);72 }73 74 std::string ByTool = getLibPathByToolPath(ToolPath, LibFileName);75 if (llvm::sys::fs::exists(ByTool)) {76 return ByTool;77 }78 79 std::string ByInstalled = getLibPathByInstalled(LibFileName);80 if (llvm::sys::fs::exists(ByInstalled)) {81 return ByInstalled;82 }83 84 errs() << "BOLT-ERROR: library not found: " << ByTool << ", " << ByInstalled85 << ", or " << LibFileName << "\n";86 exit(1);87}88 89void RuntimeLibrary::loadLibrary(StringRef LibPath, BOLTLinker &Linker,90 BOLTLinker::SectionsMapper MapSections) {91 ErrorOr<std::unique_ptr<MemoryBuffer>> MaybeBuf =92 MemoryBuffer::getFile(LibPath, false, false);93 check_error(MaybeBuf.getError(), LibPath);94 std::unique_ptr<MemoryBuffer> B = std::move(MaybeBuf.get());95 file_magic Magic = identify_magic(B->getBuffer());96 97 if (Magic == file_magic::archive) {98 Error Err = Error::success();99 object::Archive Archive(B->getMemBufferRef(), Err);100 for (const object::Archive::Child &C : Archive.children(Err)) {101 std::unique_ptr<object::Binary> Bin = cantFail(C.getAsBinary());102 if (object::ObjectFile *Obj = dyn_cast<object::ObjectFile>(&*Bin))103 Linker.loadObject(Obj->getMemoryBufferRef(), MapSections);104 }105 check_error(std::move(Err), B->getBufferIdentifier());106 } else if (Magic == file_magic::elf_relocatable ||107 Magic == file_magic::elf_shared_object) {108 std::unique_ptr<object::ObjectFile> Obj =109 cantFail(object::ObjectFile::createObjectFile(B->getMemBufferRef()),110 "error creating in-memory object");111 Linker.loadObject(Obj->getMemoryBufferRef(), MapSections);112 } else {113 errs() << "BOLT-ERROR: unrecognized library format: " << LibPath << "\n";114 exit(1);115 }116}117