138 lines · cpp
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-exception6//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 18namespace llvm {19namespace orc {20 21static Expected<std::unique_ptr<MemoryBuffer>>22checkCOFFRelocatableObject(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 28static Expected<std::unique_ptr<MemoryBuffer>>29checkXCOFFRelocatableObject(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 35static Expected<std::unique_ptr<MemoryBuffer>>36checkELFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, const Triple &TT) {37 // TODO: Actually check the architecture of the file.38 return std::move(Obj);39}40 41Expected<std::pair<std::unique_ptr<MemoryBuffer>, LinkableFileKind>>42loadLinkableFile(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