1 //===- bolt/RuntimeLibs/RuntimeLibrary.cpp - Runtime Library --------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the RuntimeLibrary class.
11 //===----------------------------------------------------------------------===//
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"
22 #define DEBUG_TYPE "bolt-rtlib"
27 void RuntimeLibrary::anchor() {}
29 std::string
RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath
,
30 StringRef LibFileName
) {
31 StringRef Dir
= llvm::sys::path::parent_path(ToolPath
);
32 SmallString
<128> LibPath
= llvm::sys::path::parent_path(Dir
);
33 llvm::sys::path::append(LibPath
, "lib" LLVM_LIBDIR_SUFFIX
);
34 if (!llvm::sys::fs::exists(LibPath
)) {
35 // In some cases we install bolt binary into one level deeper in bin/,
36 // we need to go back one more level to find lib directory.
37 LibPath
= llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir
));
38 llvm::sys::path::append(LibPath
, "lib" LLVM_LIBDIR_SUFFIX
);
40 llvm::sys::path::append(LibPath
, LibFileName
);
41 return std::string(LibPath
);
44 std::string
RuntimeLibrary::getLibPathByInstalled(StringRef LibFileName
) {
45 SmallString
<128> LibPath(CMAKE_INSTALL_FULL_LIBDIR
);
46 llvm::sys::path::append(LibPath
, LibFileName
);
47 return std::string(LibPath
);
50 std::string
RuntimeLibrary::getLibPath(StringRef ToolPath
,
51 StringRef LibFileName
) {
52 if (llvm::sys::fs::exists(LibFileName
)) {
53 return std::string(LibFileName
);
56 std::string ByTool
= getLibPathByToolPath(ToolPath
, LibFileName
);
57 if (llvm::sys::fs::exists(ByTool
)) {
61 std::string ByInstalled
= getLibPathByInstalled(LibFileName
);
62 if (llvm::sys::fs::exists(ByInstalled
)) {
66 errs() << "BOLT-ERROR: library not found: " << ByTool
<< ", " << ByInstalled
67 << ", or " << LibFileName
<< "\n";
71 void RuntimeLibrary::loadLibrary(StringRef LibPath
, BOLTLinker
&Linker
,
72 BOLTLinker::SectionsMapper MapSections
) {
73 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> MaybeBuf
=
74 MemoryBuffer::getFile(LibPath
, false, false);
75 check_error(MaybeBuf
.getError(), LibPath
);
76 std::unique_ptr
<MemoryBuffer
> B
= std::move(MaybeBuf
.get());
77 file_magic Magic
= identify_magic(B
->getBuffer());
79 if (Magic
== file_magic::archive
) {
80 Error Err
= Error::success();
81 object::Archive
Archive(B
.get()->getMemBufferRef(), Err
);
82 for (const object::Archive::Child
&C
: Archive
.children(Err
)) {
83 std::unique_ptr
<object::Binary
> Bin
= cantFail(C
.getAsBinary());
84 if (object::ObjectFile
*Obj
= dyn_cast
<object::ObjectFile
>(&*Bin
))
85 Linker
.loadObject(Obj
->getMemoryBufferRef(), MapSections
);
87 check_error(std::move(Err
), B
->getBufferIdentifier());
88 } else if (Magic
== file_magic::elf_relocatable
||
89 Magic
== file_magic::elf_shared_object
) {
90 std::unique_ptr
<object::ObjectFile
> Obj
= cantFail(
91 object::ObjectFile::createObjectFile(B
.get()->getMemBufferRef()),
92 "error creating in-memory object");
93 Linker
.loadObject(Obj
->getMemoryBufferRef(), MapSections
);
95 errs() << "BOLT-ERROR: unrecognized library format: " << LibPath
<< "\n";