xref: /llvm-project/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp (revision abc2eae68290c453e1899a94eccc4ed5ea3b69c1)
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