1 //===--- RuntimeLibrary.cpp - The 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 //===----------------------------------------------------------------------===//
10 
11 #include "bolt/RuntimeLibs/RuntimeLibrary.h"
12 #include "bolt/Utils/Utils.h"
13 #include "llvm/BinaryFormat/Magic.h"
14 #include "llvm/ExecutionEngine/RuntimeDyld.h"
15 #include "llvm/Object/Archive.h"
16 #include "llvm/Support/Path.h"
17 
18 #define DEBUG_TYPE "bolt-rtlib"
19 
20 using namespace llvm;
21 using namespace bolt;
22 
23 void RuntimeLibrary::anchor() {}
24 
25 std::string RuntimeLibrary::getLibPath(StringRef ToolPath,
26                                        StringRef LibFileName) {
27   StringRef Dir = llvm::sys::path::parent_path(ToolPath);
28   SmallString<128> LibPath = llvm::sys::path::parent_path(Dir);
29   llvm::sys::path::append(LibPath, "lib");
30   if (!llvm::sys::fs::exists(LibPath)) {
31     // In some cases we install bolt binary into one level deeper in bin/,
32     // we need to go back one more level to find lib directory.
33     LibPath = llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir));
34     llvm::sys::path::append(LibPath, "lib");
35   }
36   llvm::sys::path::append(LibPath, LibFileName);
37   if (!llvm::sys::fs::exists(LibPath)) {
38     errs() << "BOLT-ERROR: library not found: " << LibPath << "\n";
39     exit(1);
40   }
41   return std::string(LibPath.str());
42 }
43 
44 void RuntimeLibrary::loadLibrary(StringRef LibPath, RuntimeDyld &RTDyld) {
45   ErrorOr<std::unique_ptr<MemoryBuffer>> MaybeBuf =
46       MemoryBuffer::getFile(LibPath, -1, false);
47   check_error(MaybeBuf.getError(), LibPath);
48   std::unique_ptr<MemoryBuffer> B = std::move(MaybeBuf.get());
49   file_magic Magic = identify_magic(B->getBuffer());
50 
51   if (Magic == file_magic::archive) {
52     Error Err = Error::success();
53     object::Archive Archive(B.get()->getMemBufferRef(), Err);
54     for (const object::Archive::Child &C : Archive.children(Err)) {
55       std::unique_ptr<object::Binary> Bin = cantFail(C.getAsBinary());
56       if (object::ObjectFile *Obj = dyn_cast<object::ObjectFile>(&*Bin)) {
57         RTDyld.loadObject(*Obj);
58       }
59     }
60     check_error(std::move(Err), B->getBufferIdentifier());
61   } else if (Magic == file_magic::elf_relocatable ||
62              Magic == file_magic::elf_shared_object) {
63     std::unique_ptr<object::ObjectFile> Obj = cantFail(
64         object::ObjectFile::createObjectFile(B.get()->getMemBufferRef()),
65         "error creating in-memory object");
66     RTDyld.loadObject(*Obj);
67   } else {
68     errs() << "BOLT-ERROR: unrecognized library format: " << LibPath << "\n";
69     exit(1);
70   }
71 }
72