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 checkXCOFFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, 30 const Triple &TT) { 31 // TODO: Actually check the architecture of the file. 32 return std::move(Obj); 33 } 34 35 static Expected<std::unique_ptr<MemoryBuffer>> 36 checkELFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, const Triple &TT) { 37 // TODO: Actually check the architecture of the file. 38 return std::move(Obj); 39 } 40 41 Expected<std::pair<std::unique_ptr<MemoryBuffer>, LinkableFileKind>> 42 loadLinkableFile(StringRef Path, const Triple &TT, LoadArchives LA, 43 std::optional<StringRef> IdentifierOverride) { 44 if (!IdentifierOverride) 45 IdentifierOverride = Path; 46 47 Expected<sys::fs::file_t> FDOrErr = 48 sys::fs::openNativeFileForRead(Path, sys::fs::OF_None); 49 if (!FDOrErr) 50 return createFileError(Path, FDOrErr.takeError()); 51 sys::fs::file_t FD = *FDOrErr; 52 auto CloseFile = make_scope_exit([&]() { sys::fs::closeFile(FD); }); 53 54 auto Buf = 55 MemoryBuffer::getOpenFile(FD, *IdentifierOverride, /*FileSize=*/-1); 56 if (!Buf) 57 return make_error<StringError>( 58 StringRef("Could not load object at path ") + Path, Buf.getError()); 59 60 std::optional<Triple::ObjectFormatType> RequireFormat; 61 if (TT.getObjectFormat() != Triple::UnknownObjectFormat) 62 RequireFormat = TT.getObjectFormat(); 63 64 switch (identify_magic((*Buf)->getBuffer())) { 65 case file_magic::archive: 66 if (LA != LoadArchives::Never) 67 return std::make_pair(std::move(*Buf), LinkableFileKind::Archive); 68 return make_error<StringError>( 69 Path + " does not contain a relocatable object file", 70 inconvertibleErrorCode()); 71 case file_magic::coff_object: 72 if (LA == LoadArchives::Required) 73 return make_error<StringError>(Path + " does not contain an archive", 74 inconvertibleErrorCode()); 75 76 if (!RequireFormat || *RequireFormat == Triple::COFF) { 77 auto CheckedBuf = checkCOFFRelocatableObject(std::move(*Buf), TT); 78 if (!CheckedBuf) 79 return CheckedBuf.takeError(); 80 return std::make_pair(std::move(*CheckedBuf), 81 LinkableFileKind::RelocatableObject); 82 } 83 break; 84 case file_magic::elf_relocatable: 85 if (LA == LoadArchives::Required) 86 return make_error<StringError>(Path + " does not contain an archive", 87 inconvertibleErrorCode()); 88 89 if (!RequireFormat || *RequireFormat == Triple::ELF) { 90 auto CheckedBuf = checkELFRelocatableObject(std::move(*Buf), TT); 91 if (!CheckedBuf) 92 return CheckedBuf.takeError(); 93 return std::make_pair(std::move(*CheckedBuf), 94 LinkableFileKind::RelocatableObject); 95 } 96 break; 97 case file_magic::macho_object: 98 if (LA == LoadArchives::Required) 99 return make_error<StringError>(Path + " does not contain an archive", 100 inconvertibleErrorCode()); 101 102 if (!RequireFormat || *RequireFormat == Triple::MachO) { 103 auto CheckedBuf = checkMachORelocatableObject(std::move(*Buf), TT, false); 104 if (!CheckedBuf) 105 return CheckedBuf.takeError(); 106 return std::make_pair(std::move(*CheckedBuf), 107 LinkableFileKind::RelocatableObject); 108 } 109 break; 110 case file_magic::macho_universal_binary: 111 if (!RequireFormat || *RequireFormat == Triple::MachO) 112 return loadLinkableSliceFromMachOUniversalBinary( 113 FD, std::move(*Buf), TT, LA, Path, *IdentifierOverride); 114 break; 115 case file_magic::xcoff_object_64: 116 if (!RequireFormat || *RequireFormat == Triple::XCOFF) { 117 auto CheckedBuf = checkXCOFFRelocatableObject(std::move(*Buf), TT); 118 if (!CheckedBuf) 119 return CheckedBuf.takeError(); 120 return std::make_pair(std::move(*CheckedBuf), 121 LinkableFileKind::RelocatableObject); 122 } 123 break; 124 default: 125 break; 126 } 127 128 return make_error<StringError>( 129 Path + 130 " does not contain a relocatable object file or archive compatible " 131 "with " + 132 TT.str(), 133 inconvertibleErrorCode()); 134 } 135 136 } // End namespace orc. 137 } // End namespace llvm. 138