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