1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
//===------- LoadLinkableFile.cpp -- Load relocatables and archives -------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/ExecutionEngine/Orc/MachO.h"
#include "llvm/Support/FileSystem.h"
#define DEBUG_TYPE "orc"
namespace llvm {
namespace orc {
static Expected<std::unique_ptr<MemoryBuffer>>
checkCOFFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj,
const Triple &TT) {
// TODO: Actually check the architecture of the file.
return std::move(Obj);
}
static Expected<std::unique_ptr<MemoryBuffer>>
checkXCOFFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj,
const Triple &TT) {
// TODO: Actually check the architecture of the file.
return std::move(Obj);
}
static Expected<std::unique_ptr<MemoryBuffer>>
checkELFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, const Triple &TT) {
// TODO: Actually check the architecture of the file.
return std::move(Obj);
}
Expected<std::pair<std::unique_ptr<MemoryBuffer>, LinkableFileKind>>
loadLinkableFile(StringRef Path, const Triple &TT, LoadArchives LA,
std::optional<StringRef> IdentifierOverride) {
if (!IdentifierOverride)
IdentifierOverride = Path;
Expected<sys::fs::file_t> FDOrErr =
sys::fs::openNativeFileForRead(Path, sys::fs::OF_None);
if (!FDOrErr)
return createFileError(Path, FDOrErr.takeError());
sys::fs::file_t FD = *FDOrErr;
auto CloseFile = make_scope_exit([&]() { sys::fs::closeFile(FD); });
auto Buf =
MemoryBuffer::getOpenFile(FD, *IdentifierOverride, /*FileSize=*/-1);
if (!Buf)
return make_error<StringError>(
StringRef("Could not load object at path ") + Path, Buf.getError());
std::optional<Triple::ObjectFormatType> RequireFormat;
if (TT.getObjectFormat() != Triple::UnknownObjectFormat)
RequireFormat = TT.getObjectFormat();
switch (identify_magic((*Buf)->getBuffer())) {
case file_magic::archive:
if (LA != LoadArchives::Never)
return std::make_pair(std::move(*Buf), LinkableFileKind::Archive);
return make_error<StringError>(
Path + " does not contain a relocatable object file",
inconvertibleErrorCode());
case file_magic::coff_object:
if (LA == LoadArchives::Required)
return make_error<StringError>(Path + " does not contain an archive",
inconvertibleErrorCode());
if (!RequireFormat || *RequireFormat == Triple::COFF) {
auto CheckedBuf = checkCOFFRelocatableObject(std::move(*Buf), TT);
if (!CheckedBuf)
return CheckedBuf.takeError();
return std::make_pair(std::move(*CheckedBuf),
LinkableFileKind::RelocatableObject);
}
break;
case file_magic::elf_relocatable:
if (LA == LoadArchives::Required)
return make_error<StringError>(Path + " does not contain an archive",
inconvertibleErrorCode());
if (!RequireFormat || *RequireFormat == Triple::ELF) {
auto CheckedBuf = checkELFRelocatableObject(std::move(*Buf), TT);
if (!CheckedBuf)
return CheckedBuf.takeError();
return std::make_pair(std::move(*CheckedBuf),
LinkableFileKind::RelocatableObject);
}
break;
case file_magic::macho_object:
if (LA == LoadArchives::Required)
return make_error<StringError>(Path + " does not contain an archive",
inconvertibleErrorCode());
if (!RequireFormat || *RequireFormat == Triple::MachO) {
auto CheckedBuf = checkMachORelocatableObject(std::move(*Buf), TT, false);
if (!CheckedBuf)
return CheckedBuf.takeError();
return std::make_pair(std::move(*CheckedBuf),
LinkableFileKind::RelocatableObject);
}
break;
case file_magic::macho_universal_binary:
if (!RequireFormat || *RequireFormat == Triple::MachO)
return loadLinkableSliceFromMachOUniversalBinary(
FD, std::move(*Buf), TT, LA, Path, *IdentifierOverride);
break;
case file_magic::xcoff_object_64:
if (!RequireFormat || *RequireFormat == Triple::XCOFF) {
auto CheckedBuf = checkXCOFFRelocatableObject(std::move(*Buf), TT);
if (!CheckedBuf)
return CheckedBuf.takeError();
return std::make_pair(std::move(*CheckedBuf),
LinkableFileKind::RelocatableObject);
}
break;
default:
break;
}
return make_error<StringError>(
Path +
" does not contain a relocatable object file or archive compatible "
"with " +
TT.str(),
inconvertibleErrorCode());
}
} // End namespace orc.
} // End namespace llvm.
|