10b57cec5SDimitry Andric //===-------------- MachO.cpp - JIT linker function for MachO -------------===// 20b57cec5SDimitry Andric // 3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // MachO jit-link function. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO.h" 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h" 168bcb0991SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO_arm64.h" 170b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h" 180b57cec5SDimitry Andric #include "llvm/Support/Format.h" 190b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 205ffd83dbSDimitry Andric #include "llvm/Support/SwapByteOrder.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define DEBUG_TYPE "jitlink" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric namespace llvm { 270b57cec5SDimitry Andric namespace jitlink { 280b57cec5SDimitry Andric 29e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 30e8d8bef9SDimitry Andric createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer) { 31e8d8bef9SDimitry Andric StringRef Data = ObjectBuffer.getBuffer(); 32e8d8bef9SDimitry Andric if (Data.size() < 4) 33e8d8bef9SDimitry Andric return make_error<JITLinkError>("Truncated MachO buffer \"" + 34e8d8bef9SDimitry Andric ObjectBuffer.getBufferIdentifier() + "\""); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric uint32_t Magic; 370b57cec5SDimitry Andric memcpy(&Magic, Data.data(), sizeof(uint32_t)); 380b57cec5SDimitry Andric LLVM_DEBUG({ 390b57cec5SDimitry Andric dbgs() << "jitLink_MachO: magic = " << format("0x%08" PRIx32, Magic) 40e8d8bef9SDimitry Andric << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() 41e8d8bef9SDimitry Andric << "\"\n"; 420b57cec5SDimitry Andric }); 430b57cec5SDimitry Andric 44e8d8bef9SDimitry Andric if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM) 45e8d8bef9SDimitry Andric return make_error<JITLinkError>("MachO 32-bit platforms not supported"); 46e8d8bef9SDimitry Andric else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) { 470b57cec5SDimitry Andric 48e8d8bef9SDimitry Andric if (Data.size() < sizeof(MachO::mach_header_64)) 49e8d8bef9SDimitry Andric return make_error<JITLinkError>("Truncated MachO buffer \"" + 50e8d8bef9SDimitry Andric ObjectBuffer.getBufferIdentifier() + 51e8d8bef9SDimitry Andric "\""); 525ffd83dbSDimitry Andric 535ffd83dbSDimitry Andric // Read the CPU type from the header. 545ffd83dbSDimitry Andric uint32_t CPUType; 555ffd83dbSDimitry Andric memcpy(&CPUType, Data.data() + 4, sizeof(uint32_t)); 560b57cec5SDimitry Andric if (Magic == MachO::MH_CIGAM_64) 575ffd83dbSDimitry Andric CPUType = ByteSwap_32(CPUType); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric LLVM_DEBUG({ 605ffd83dbSDimitry Andric dbgs() << "jitLink_MachO: cputype = " << format("0x%08" PRIx32, CPUType) 610b57cec5SDimitry Andric << "\n"; 620b57cec5SDimitry Andric }); 630b57cec5SDimitry Andric 645ffd83dbSDimitry Andric switch (CPUType) { 658bcb0991SDimitry Andric case MachO::CPU_TYPE_ARM64: 66fe6060f1SDimitry Andric return createLinkGraphFromMachOObject_arm64(ObjectBuffer); 670b57cec5SDimitry Andric case MachO::CPU_TYPE_X86_64: 68fe6060f1SDimitry Andric return createLinkGraphFromMachOObject_x86_64(ObjectBuffer); 690b57cec5SDimitry Andric } 70e8d8bef9SDimitry Andric return make_error<JITLinkError>("MachO-64 CPU type not valid"); 71e8d8bef9SDimitry Andric } else 72e8d8bef9SDimitry Andric return make_error<JITLinkError>("Unrecognized MachO magic value"); 73e8d8bef9SDimitry Andric } 74e8d8bef9SDimitry Andric 75e8d8bef9SDimitry Andric void link_MachO(std::unique_ptr<LinkGraph> G, 76e8d8bef9SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 77e8d8bef9SDimitry Andric 78e8d8bef9SDimitry Andric switch (G->getTargetTriple().getArch()) { 79e8d8bef9SDimitry Andric case Triple::aarch64: 80e8d8bef9SDimitry Andric return link_MachO_arm64(std::move(G), std::move(Ctx)); 81e8d8bef9SDimitry Andric case Triple::x86_64: 82e8d8bef9SDimitry Andric return link_MachO_x86_64(std::move(G), std::move(Ctx)); 83e8d8bef9SDimitry Andric default: 840b57cec5SDimitry Andric Ctx->notifyFailed(make_error<JITLinkError>("MachO-64 CPU type not valid")); 850b57cec5SDimitry Andric return; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric } // end namespace jitlink 900b57cec5SDimitry Andric } // end namespace llvm 91