Files
clang-p2996/llvm/lib/ExecutionEngine/Orc/LoadRelocatableObject.cpp
Lang Hames 3e1d4ec671 [ORC] loadRelocatableObject: universal binary support, clearer errors (#104406)
ORC supports loading relocatable object files into a JIT'd process. The
raw "add object file" API (ObjectLayer::add) accepts plain relocatable
object files as llvm::MemoryBuffers only and does not check that the
object file's format or architecture are compatible with the process
that it will be linked in to. This API is flexible, but places the
burden of error checking and universal binary support on clients.

This commit introduces a new utility, loadRelocatableObject, that takes
a path to load and a target triple and then:
1. If the path does not exist, returns a FileError containing the
invalid path.
2. If the path points to a MachO universal binary, identifies and
returns MemoryBuffer covering the slice that matches the given triple
(checking that the slice really does contains a valid MachO relocatable
object with a compatible arch).
3. If the path points to a regular relocatable object file, verifies
that the format and architecture are compatible with the triple.

Clients can use loadRelocatableObject in the common case of loading
object files from disk to simplify their code.

Note: Error checking for ELF and COFF is left as a FIXME.

rdar://133653290
2024-08-16 09:52:36 +10:00

70 lines
2.4 KiB
C++

//===----- LoadRelocatableObject.cpp -- Load relocatable object files -----===//
//
// 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/LoadRelocatableObject.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/ExecutionEngine/Orc/MachO.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>>
checkELFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, const Triple &TT) {
// TODO: Actually check the architecture of the file.
return std::move(Obj);
}
Expected<std::unique_ptr<MemoryBuffer>>
loadRelocatableObject(StringRef Path, const Triple &TT) {
auto Buf = MemoryBuffer::getFile(Path);
if (!Buf)
return createFileError(Path, Buf.getError());
std::optional<Triple::ObjectFormatType> RequireFormat;
if (TT.getObjectFormat() != Triple::UnknownObjectFormat)
RequireFormat = TT.getObjectFormat();
switch (identify_magic((*Buf)->getBuffer())) {
case file_magic::coff_object:
if (!RequireFormat || *RequireFormat == Triple::COFF)
return checkCOFFRelocatableObject(std::move(*Buf), TT);
break;
case file_magic::elf_relocatable:
if (!RequireFormat || *RequireFormat == Triple::ELF)
return checkELFRelocatableObject(std::move(*Buf), TT);
break;
case file_magic::macho_object:
if (!RequireFormat || *RequireFormat == Triple::MachO)
return checkMachORelocatableObject(std::move(*Buf), TT, false);
break;
case file_magic::macho_universal_binary:
if (!RequireFormat || *RequireFormat == Triple::MachO)
return loadMachORelocatableObjectFromUniversalBinary(Path,
std::move(*Buf), TT);
break;
default:
break;
}
return make_error<StringError>(
Path + " does not contain a relocatable object file compatible with " +
TT.str(),
inconvertibleErrorCode());
}
} // End namespace orc.
} // End namespace llvm.