1 //===-------------- MachO.cpp - JIT linker function for MachO -------------===// 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 // MachO jit-link function. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ExecutionEngine/JITLink/MachO.h" 14 15 #include "llvm/BinaryFormat/MachO.h" 16 #include "llvm/ExecutionEngine/JITLink/MachO_arm64.h" 17 #include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h" 18 #include "llvm/Support/Format.h" 19 #include "llvm/Support/MemoryBuffer.h" 20 #include "llvm/Support/SwapByteOrder.h" 21 22 using namespace llvm; 23 24 #define DEBUG_TYPE "jitlink" 25 26 namespace llvm { 27 namespace jitlink { 28 29 Expected<std::unique_ptr<LinkGraph>> 30 createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer) { 31 StringRef Data = ObjectBuffer.getBuffer(); 32 if (Data.size() < 4) 33 return make_error<JITLinkError>("Truncated MachO buffer \"" + 34 ObjectBuffer.getBufferIdentifier() + "\""); 35 36 uint32_t Magic; 37 memcpy(&Magic, Data.data(), sizeof(uint32_t)); 38 LLVM_DEBUG({ 39 dbgs() << "jitLink_MachO: magic = " << format("0x%08" PRIx32, Magic) 40 << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() 41 << "\"\n"; 42 }); 43 44 if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM) 45 return make_error<JITLinkError>("MachO 32-bit platforms not supported"); 46 else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) { 47 48 if (Data.size() < sizeof(MachO::mach_header_64)) 49 return make_error<JITLinkError>("Truncated MachO buffer \"" + 50 ObjectBuffer.getBufferIdentifier() + 51 "\""); 52 53 // Read the CPU type from the header. 54 uint32_t CPUType; 55 memcpy(&CPUType, Data.data() + 4, sizeof(uint32_t)); 56 if (Magic == MachO::MH_CIGAM_64) 57 CPUType = llvm::byteswap<uint32_t>(CPUType); 58 59 LLVM_DEBUG({ 60 dbgs() << "jitLink_MachO: cputype = " << format("0x%08" PRIx32, CPUType) 61 << "\n"; 62 }); 63 64 switch (CPUType) { 65 case MachO::CPU_TYPE_ARM64: 66 return createLinkGraphFromMachOObject_arm64(ObjectBuffer); 67 case MachO::CPU_TYPE_X86_64: 68 return createLinkGraphFromMachOObject_x86_64(ObjectBuffer); 69 } 70 return make_error<JITLinkError>("MachO-64 CPU type not valid"); 71 } else 72 return make_error<JITLinkError>("Unrecognized MachO magic value"); 73 } 74 75 void link_MachO(std::unique_ptr<LinkGraph> G, 76 std::unique_ptr<JITLinkContext> Ctx) { 77 78 switch (G->getTargetTriple().getArch()) { 79 case Triple::aarch64: 80 return link_MachO_arm64(std::move(G), std::move(Ctx)); 81 case Triple::x86_64: 82 return link_MachO_x86_64(std::move(G), std::move(Ctx)); 83 default: 84 Ctx->notifyFailed(make_error<JITLinkError>("MachO-64 CPU type not valid")); 85 return; 86 } 87 } 88 89 } // end namespace jitlink 90 } // end namespace llvm 91