1 //===------- LoadLinkableFile.cpp -- Load relocatables and archives -------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h" 10 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" 15 16 #define DEBUG_TYPE "orc" 17 18 namespace llvm { 19 namespace orc { 20 21 static Expected<std::unique_ptr<MemoryBuffer>> 22 checkCOFFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, 23 const Triple &TT) { 24 // TODO: Actually check the architecture of the file. 25 return std::move(Obj); 26 } 27 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); 32 } 33 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; 39 40 Expected<sys::fs::file_t> FDOrErr = 41 sys::fs::openNativeFileForRead(Path, sys::fs::OF_None); 42 if (!FDOrErr) 43 return createFileError(Path, FDOrErr.takeError()); 44 sys::fs::file_t FD = *FDOrErr; 45 auto CloseFile = make_scope_exit([&]() { sys::fs::closeFile(FD); }); 46 47 auto Buf = 48 MemoryBuffer::getOpenFile(FD, *IdentifierOverride, /*FileSize=*/-1); 49 if (!Buf) 50 return make_error<StringError>( 51 StringRef("Could not load object at path ") + Path, Buf.getError()); 52 53 std::optional<Triple::ObjectFormatType> RequireFormat; 54 if (TT.getObjectFormat() != Triple::UnknownObjectFormat) 55 RequireFormat = TT.getObjectFormat(); 56 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()); 68 69 if (!RequireFormat || *RequireFormat == Triple::COFF) { 70 auto CheckedBuf = checkCOFFRelocatableObject(std::move(*Buf), TT); 71 if (!CheckedBuf) 72 return CheckedBuf.takeError(); 73 return std::make_pair(std::move(*CheckedBuf), 74 LinkableFileKind::RelocatableObject); 75 } 76 break; 77 case file_magic::elf_relocatable: 78 if (LA == LoadArchives::Required) 79 return make_error<StringError>(Path + " does not contain an archive", 80 inconvertibleErrorCode()); 81 82 if (!RequireFormat || *RequireFormat == Triple::ELF) { 83 auto CheckedBuf = checkELFRelocatableObject(std::move(*Buf), TT); 84 if (!CheckedBuf) 85 return CheckedBuf.takeError(); 86 return std::make_pair(std::move(*CheckedBuf), 87 LinkableFileKind::RelocatableObject); 88 } 89 break; 90 case file_magic::macho_object: 91 if (LA == LoadArchives::Required) 92 return make_error<StringError>(Path + " does not contain an archive", 93 inconvertibleErrorCode()); 94 95 if (!RequireFormat || *RequireFormat == Triple::MachO) { 96 auto CheckedBuf = checkMachORelocatableObject(std::move(*Buf), TT, false); 97 if (!CheckedBuf) 98 return CheckedBuf.takeError(); 99 return std::make_pair(std::move(*CheckedBuf), 100 LinkableFileKind::RelocatableObject); 101 } 102 break; 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); 107 break; 108 default: 109 break; 110 } 111 112 return make_error<StringError>( 113 Path + 114 " does not contain a relocatable object file or archive compatible " 115 "with " + 116 TT.str(), 117 inconvertibleErrorCode()); 118 } 119 120 } // End namespace orc. 121 } // End namespace llvm. 122