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" 215ffd83dbSDimitry 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 30e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 31e8d8bef9SDimitry Andric createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer) { 32e8d8bef9SDimitry Andric StringRef Data = ObjectBuffer.getBuffer(); 33e8d8bef9SDimitry Andric if (Data.size() < 4) 34e8d8bef9SDimitry Andric return make_error<JITLinkError>("Truncated MachO buffer \"" + 35e8d8bef9SDimitry Andric ObjectBuffer.getBufferIdentifier() + "\""); 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric uint32_t Magic; 380b57cec5SDimitry Andric memcpy(&Magic, Data.data(), sizeof(uint32_t)); 390b57cec5SDimitry Andric LLVM_DEBUG({ 400b57cec5SDimitry Andric dbgs() << "jitLink_MachO: magic = " << format("0x%08" PRIx32, Magic) 41e8d8bef9SDimitry Andric << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() 42e8d8bef9SDimitry Andric << "\"\n"; 430b57cec5SDimitry Andric }); 440b57cec5SDimitry Andric 45e8d8bef9SDimitry Andric if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM) 46e8d8bef9SDimitry Andric return make_error<JITLinkError>("MachO 32-bit platforms not supported"); 47e8d8bef9SDimitry Andric else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) { 480b57cec5SDimitry Andric 49e8d8bef9SDimitry Andric if (Data.size() < sizeof(MachO::mach_header_64)) 50e8d8bef9SDimitry Andric return make_error<JITLinkError>("Truncated MachO buffer \"" + 51e8d8bef9SDimitry Andric ObjectBuffer.getBufferIdentifier() + 52e8d8bef9SDimitry Andric "\""); 535ffd83dbSDimitry Andric 545ffd83dbSDimitry Andric // Read the CPU type from the header. 555ffd83dbSDimitry Andric uint32_t CPUType; 565ffd83dbSDimitry Andric memcpy(&CPUType, Data.data() + 4, sizeof(uint32_t)); 570b57cec5SDimitry Andric if (Magic == MachO::MH_CIGAM_64) 585ffd83dbSDimitry Andric CPUType = ByteSwap_32(CPUType); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric LLVM_DEBUG({ 615ffd83dbSDimitry Andric dbgs() << "jitLink_MachO: cputype = " << format("0x%08" PRIx32, CPUType) 620b57cec5SDimitry Andric << "\n"; 630b57cec5SDimitry Andric }); 640b57cec5SDimitry Andric 655ffd83dbSDimitry Andric switch (CPUType) { 668bcb0991SDimitry Andric case MachO::CPU_TYPE_ARM64: 67*fe6060f1SDimitry Andric return createLinkGraphFromMachOObject_arm64(ObjectBuffer); 680b57cec5SDimitry Andric case MachO::CPU_TYPE_X86_64: 69*fe6060f1SDimitry Andric return createLinkGraphFromMachOObject_x86_64(ObjectBuffer); 700b57cec5SDimitry Andric } 71e8d8bef9SDimitry Andric return make_error<JITLinkError>("MachO-64 CPU type not valid"); 72e8d8bef9SDimitry Andric } else 73e8d8bef9SDimitry Andric return make_error<JITLinkError>("Unrecognized MachO magic value"); 74e8d8bef9SDimitry Andric } 75e8d8bef9SDimitry Andric 76e8d8bef9SDimitry Andric void link_MachO(std::unique_ptr<LinkGraph> G, 77e8d8bef9SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 78e8d8bef9SDimitry Andric 79e8d8bef9SDimitry Andric switch (G->getTargetTriple().getArch()) { 80e8d8bef9SDimitry Andric case Triple::aarch64: 81e8d8bef9SDimitry Andric return link_MachO_arm64(std::move(G), std::move(Ctx)); 82e8d8bef9SDimitry Andric case Triple::x86_64: 83e8d8bef9SDimitry Andric return link_MachO_x86_64(std::move(G), std::move(Ctx)); 84e8d8bef9SDimitry Andric default: 850b57cec5SDimitry Andric Ctx->notifyFailed(make_error<JITLinkError>("MachO-64 CPU type not valid")); 860b57cec5SDimitry Andric return; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric } // end namespace jitlink 910b57cec5SDimitry Andric } // end namespace llvm 92