xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/MachO.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===-------------- MachO.cpp - JIT linker function for MachO -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric //                     The LLVM Compiler Infrastructure
40b57cec5SDimitry Andric //
50b57cec5SDimitry Andric // This file is distributed under the University of Illinois Open Source
60b57cec5SDimitry Andric // License. See LICENSE.TXT for details.
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric //
100b57cec5SDimitry Andric // MachO jit-link function.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
178bcb0991SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO_arm64.h"
180b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h"
190b57cec5SDimitry Andric #include "llvm/Support/Format.h"
200b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
21*5ffd83dbSDimitry Andric #include "llvm/Support/SwapByteOrder.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #define DEBUG_TYPE "jitlink"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace llvm {
280b57cec5SDimitry Andric namespace jitlink {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx) {
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   // We don't want to do full MachO validation here. Just parse enough of the
330b57cec5SDimitry Andric   // header to find out what MachO linker to use.
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   StringRef Data = Ctx->getObjectBuffer().getBuffer();
360b57cec5SDimitry Andric   if (Data.size() < 4) {
37*5ffd83dbSDimitry Andric     StringRef BufferName = Ctx->getObjectBuffer().getBufferIdentifier();
38*5ffd83dbSDimitry Andric     Ctx->notifyFailed(make_error<JITLinkError>("Truncated MachO buffer \"" +
39*5ffd83dbSDimitry Andric                                                BufferName + "\""));
400b57cec5SDimitry Andric     return;
410b57cec5SDimitry Andric   }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   uint32_t Magic;
440b57cec5SDimitry Andric   memcpy(&Magic, Data.data(), sizeof(uint32_t));
450b57cec5SDimitry Andric   LLVM_DEBUG({
460b57cec5SDimitry Andric     dbgs() << "jitLink_MachO: magic = " << format("0x%08" PRIx32, Magic)
470b57cec5SDimitry Andric            << ", identifier = \""
480b57cec5SDimitry Andric            << Ctx->getObjectBuffer().getBufferIdentifier() << "\"\n";
490b57cec5SDimitry Andric   });
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM) {
520b57cec5SDimitry Andric     Ctx->notifyFailed(
530b57cec5SDimitry Andric         make_error<JITLinkError>("MachO 32-bit platforms not supported"));
540b57cec5SDimitry Andric     return;
550b57cec5SDimitry Andric   } else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) {
560b57cec5SDimitry Andric 
57*5ffd83dbSDimitry Andric     if (Data.size() < sizeof(MachO::mach_header_64)) {
58*5ffd83dbSDimitry Andric       StringRef BufferName = Ctx->getObjectBuffer().getBufferIdentifier();
59*5ffd83dbSDimitry Andric       Ctx->notifyFailed(make_error<JITLinkError>("Truncated MachO buffer \"" +
60*5ffd83dbSDimitry Andric                                                  BufferName + "\""));
61*5ffd83dbSDimitry Andric       return;
62*5ffd83dbSDimitry Andric     }
63*5ffd83dbSDimitry Andric 
64*5ffd83dbSDimitry Andric     // Read the CPU type from the header.
65*5ffd83dbSDimitry Andric     uint32_t CPUType;
66*5ffd83dbSDimitry Andric     memcpy(&CPUType, Data.data() + 4, sizeof(uint32_t));
670b57cec5SDimitry Andric     if (Magic == MachO::MH_CIGAM_64)
68*5ffd83dbSDimitry Andric       CPUType = ByteSwap_32(CPUType);
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric     LLVM_DEBUG({
71*5ffd83dbSDimitry Andric       dbgs() << "jitLink_MachO: cputype = " << format("0x%08" PRIx32, CPUType)
720b57cec5SDimitry Andric              << "\n";
730b57cec5SDimitry Andric     });
740b57cec5SDimitry Andric 
75*5ffd83dbSDimitry Andric     switch (CPUType) {
768bcb0991SDimitry Andric     case MachO::CPU_TYPE_ARM64:
778bcb0991SDimitry Andric       return jitLink_MachO_arm64(std::move(Ctx));
780b57cec5SDimitry Andric     case MachO::CPU_TYPE_X86_64:
790b57cec5SDimitry Andric       return jitLink_MachO_x86_64(std::move(Ctx));
800b57cec5SDimitry Andric     }
810b57cec5SDimitry Andric     Ctx->notifyFailed(make_error<JITLinkError>("MachO-64 CPU type not valid"));
820b57cec5SDimitry Andric     return;
830b57cec5SDimitry Andric   }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   Ctx->notifyFailed(make_error<JITLinkError>("MachO magic not valid"));
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric } // end namespace jitlink
890b57cec5SDimitry Andric } // end namespace llvm
90