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