1 //===------- LoadLinkableFile.cpp -- Load relocatables and archives -------===//
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 #include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h"
11 #include "llvm/ADT/ScopeExit.h"
12 #include "llvm/BinaryFormat/Magic.h"
13 #include "llvm/ExecutionEngine/Orc/MachO.h"
14 #include "llvm/Support/FileSystem.h"
16 #define DEBUG_TYPE "orc"
21 static Expected
<std::unique_ptr
<MemoryBuffer
>>
22 checkCOFFRelocatableObject(std::unique_ptr
<MemoryBuffer
> Obj
,
24 // TODO: Actually check the architecture of the file.
25 return std::move(Obj
);
28 static Expected
<std::unique_ptr
<MemoryBuffer
>>
29 checkELFRelocatableObject(std::unique_ptr
<MemoryBuffer
> Obj
, const Triple
&TT
) {
30 // TODO: Actually check the architecture of the file.
31 return std::move(Obj
);
34 Expected
<std::pair
<std::unique_ptr
<MemoryBuffer
>, LinkableFileKind
>>
35 loadLinkableFile(StringRef Path
, const Triple
&TT
, LoadArchives LA
,
36 std::optional
<StringRef
> IdentifierOverride
) {
37 if (!IdentifierOverride
)
38 IdentifierOverride
= Path
;
40 Expected
<sys::fs::file_t
> FDOrErr
=
41 sys::fs::openNativeFileForRead(Path
, sys::fs::OF_None
);
43 return createFileError(Path
, FDOrErr
.takeError());
44 sys::fs::file_t FD
= *FDOrErr
;
45 auto CloseFile
= make_scope_exit([&]() { sys::fs::closeFile(FD
); });
48 MemoryBuffer::getOpenFile(FD
, *IdentifierOverride
, /*FileSize=*/-1);
50 return make_error
<StringError
>(
51 StringRef("Could not load object at path ") + Path
, Buf
.getError());
53 std::optional
<Triple::ObjectFormatType
> RequireFormat
;
54 if (TT
.getObjectFormat() != Triple::UnknownObjectFormat
)
55 RequireFormat
= TT
.getObjectFormat();
57 switch (identify_magic((*Buf
)->getBuffer())) {
58 case file_magic::archive
:
59 if (LA
!= LoadArchives::Never
)
60 return std::make_pair(std::move(*Buf
), LinkableFileKind::Archive
);
61 return make_error
<StringError
>(
62 Path
+ " does not contain a relocatable object file",
63 inconvertibleErrorCode());
64 case file_magic::coff_object
:
65 if (LA
== LoadArchives::Required
)
66 return make_error
<StringError
>(Path
+ " does not contain an archive",
67 inconvertibleErrorCode());
69 if (!RequireFormat
|| *RequireFormat
== Triple::COFF
) {
70 auto CheckedBuf
= checkCOFFRelocatableObject(std::move(*Buf
), TT
);
72 return CheckedBuf
.takeError();
73 return std::make_pair(std::move(*CheckedBuf
),
74 LinkableFileKind::RelocatableObject
);
77 case file_magic::elf_relocatable
:
78 if (LA
== LoadArchives::Required
)
79 return make_error
<StringError
>(Path
+ " does not contain an archive",
80 inconvertibleErrorCode());
82 if (!RequireFormat
|| *RequireFormat
== Triple::ELF
) {
83 auto CheckedBuf
= checkELFRelocatableObject(std::move(*Buf
), TT
);
85 return CheckedBuf
.takeError();
86 return std::make_pair(std::move(*CheckedBuf
),
87 LinkableFileKind::RelocatableObject
);
90 case file_magic::macho_object
:
91 if (LA
== LoadArchives::Required
)
92 return make_error
<StringError
>(Path
+ " does not contain an archive",
93 inconvertibleErrorCode());
95 if (!RequireFormat
|| *RequireFormat
== Triple::MachO
) {
96 auto CheckedBuf
= checkMachORelocatableObject(std::move(*Buf
), TT
, false);
98 return CheckedBuf
.takeError();
99 return std::make_pair(std::move(*CheckedBuf
),
100 LinkableFileKind::RelocatableObject
);
103 case file_magic::macho_universal_binary
:
104 if (!RequireFormat
|| *RequireFormat
== Triple::MachO
)
105 return loadLinkableSliceFromMachOUniversalBinary(
106 FD
, std::move(*Buf
), TT
, LA
, Path
, *IdentifierOverride
);
112 return make_error
<StringError
>(
114 " does not contain a relocatable object file or archive compatible "
117 inconvertibleErrorCode());
120 } // End namespace orc.
121 } // End namespace llvm.