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.
|