| //===------- LoadLinkableFile.cpp -- Load relocatables and archives -------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h" |
| |
| #include "llvm/ADT/ScopeExit.h" |
| #include "llvm/BinaryFormat/Magic.h" |
| #include "llvm/ExecutionEngine/Orc/MachO.h" |
| #include "llvm/Support/FileSystem.h" |
| |
| #define DEBUG_TYPE "orc" |
| |
| namespace llvm { |
| namespace orc { |
| |
| static Expected<std::unique_ptr<MemoryBuffer>> |
| checkCOFFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, |
| const Triple &TT) { |
| // TODO: Actually check the architecture of the file. |
| return std::move(Obj); |
| } |
| |
| static Expected<std::unique_ptr<MemoryBuffer>> |
| checkXCOFFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, |
| const Triple &TT) { |
| // TODO: Actually check the architecture of the file. |
| return std::move(Obj); |
| } |
| |
| static Expected<std::unique_ptr<MemoryBuffer>> |
| checkELFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, const Triple &TT) { |
| // TODO: Actually check the architecture of the file. |
| return std::move(Obj); |
| } |
| |
| Expected<std::pair<std::unique_ptr<MemoryBuffer>, LinkableFileKind>> |
| loadLinkableFile(StringRef Path, const Triple &TT, LoadArchives LA, |
| std::optional<StringRef> IdentifierOverride) { |
| if (!IdentifierOverride) |
| IdentifierOverride = Path; |
| |
| Expected<sys::fs::file_t> FDOrErr = |
| sys::fs::openNativeFileForRead(Path, sys::fs::OF_None); |
| if (!FDOrErr) |
| return createFileError(Path, FDOrErr.takeError()); |
| sys::fs::file_t FD = *FDOrErr; |
| auto CloseFile = make_scope_exit([&]() { sys::fs::closeFile(FD); }); |
| |
| auto Buf = |
| MemoryBuffer::getOpenFile(FD, *IdentifierOverride, /*FileSize=*/-1); |
| if (!Buf) |
| return make_error<StringError>( |
| StringRef("Could not load object at path ") + Path, Buf.getError()); |
| |
| std::optional<Triple::ObjectFormatType> RequireFormat; |
| if (TT.getObjectFormat() != Triple::UnknownObjectFormat) |
| RequireFormat = TT.getObjectFormat(); |
| |
| switch (identify_magic((*Buf)->getBuffer())) { |
| case file_magic::archive: |
| if (LA != LoadArchives::Never) |
| return std::make_pair(std::move(*Buf), LinkableFileKind::Archive); |
| return make_error<StringError>( |
| Path + " does not contain a relocatable object file", |
| inconvertibleErrorCode()); |
| case file_magic::coff_object: |
| if (LA == LoadArchives::Required) |
| return make_error<StringError>(Path + " does not contain an archive", |
| inconvertibleErrorCode()); |
| |
| if (!RequireFormat || *RequireFormat == Triple::COFF) { |
| auto CheckedBuf = checkCOFFRelocatableObject(std::move(*Buf), TT); |
| if (!CheckedBuf) |
| return CheckedBuf.takeError(); |
| return std::make_pair(std::move(*CheckedBuf), |
| LinkableFileKind::RelocatableObject); |
| } |
| break; |
| case file_magic::elf_relocatable: |
| if (LA == LoadArchives::Required) |
| return make_error<StringError>(Path + " does not contain an archive", |
| inconvertibleErrorCode()); |
| |
| if (!RequireFormat || *RequireFormat == Triple::ELF) { |
| auto CheckedBuf = checkELFRelocatableObject(std::move(*Buf), TT); |
| if (!CheckedBuf) |
| return CheckedBuf.takeError(); |
| return std::make_pair(std::move(*CheckedBuf), |
| LinkableFileKind::RelocatableObject); |
| } |
| break; |
| case file_magic::macho_object: |
| if (LA == LoadArchives::Required) |
| return make_error<StringError>(Path + " does not contain an archive", |
| inconvertibleErrorCode()); |
| |
| if (!RequireFormat || *RequireFormat == Triple::MachO) { |
| auto CheckedBuf = checkMachORelocatableObject(std::move(*Buf), TT, false); |
| if (!CheckedBuf) |
| return CheckedBuf.takeError(); |
| return std::make_pair(std::move(*CheckedBuf), |
| LinkableFileKind::RelocatableObject); |
| } |
| break; |
| case file_magic::macho_universal_binary: |
| if (!RequireFormat || *RequireFormat == Triple::MachO) |
| return loadLinkableSliceFromMachOUniversalBinary( |
| FD, std::move(*Buf), TT, LA, Path, *IdentifierOverride); |
| break; |
| case file_magic::xcoff_object_64: |
| if (!RequireFormat || *RequireFormat == Triple::XCOFF) { |
| auto CheckedBuf = checkXCOFFRelocatableObject(std::move(*Buf), TT); |
| if (!CheckedBuf) |
| return CheckedBuf.takeError(); |
| return std::make_pair(std::move(*CheckedBuf), |
| LinkableFileKind::RelocatableObject); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| return make_error<StringError>( |
| Path + |
| " does not contain a relocatable object file or archive compatible " |
| "with " + |
| TT.str(), |
| inconvertibleErrorCode()); |
| } |
| |
| } // End namespace orc. |
| } // End namespace llvm. |